cfengine-3.6.2/0000775000175100017510000000000012413020725013012 5ustar00a10038a1003800000000000000cfengine-3.6.2/ext/0000775000175100017510000000000012413020724013611 5ustar00a10038a1003800000000000000cfengine-3.6.2/ext/Makefile.in0000664000175100017510000005342012412324464015671 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ sbin_PROGRAMS = rpmvercmp$(EXEEXT) subdir = ext DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) rpmvercmp_SOURCES = rpmvercmp.c rpmvercmp_OBJECTS = rpmvercmp.$(OBJEXT) rpmvercmp_LDADD = $(LDADD) rpmvercmp_DEPENDENCIES = ../libcompat/libcompat.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = rpmvercmp.c DIST_SOURCES = rpmvercmp.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ LDADD = ../libcompat/libcompat.la 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) --foreign ext/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign ext/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list rpmvercmp$(EXEEXT): $(rpmvercmp_OBJECTS) $(rpmvercmp_DEPENDENCIES) $(EXTRA_rpmvercmp_DEPENDENCIES) @rm -f rpmvercmp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(rpmvercmp_OBJECTS) $(rpmvercmp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpmvercmp.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi 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-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ 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-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/ext/Makefile.am0000664000175100017510000000007612411001073015642 0ustar00a10038a1003800000000000000sbin_PROGRAMS = rpmvercmp LDADD = ../libcompat/libcompat.la cfengine-3.6.2/ext/rpmvercmp.c0000644000175100017510000001517012316547775016020 0ustar00a10038a1003800000000000000/* rpmvercmp.c contains code from RPM project, licensed as the following: RPM and it's source code are covered under two separate licenses. The entire code base may be distributed under the terms of the GNU General Public License (GPL), which appears immediately below. Alternatively, all of the source code in the lib subdirectory of the RPM source code distribution as well as any code derived from that code may instead be distributed under the GNU Library General Public License (LGPL), at the choice of the distributor. The complete text of the LGPL appears at the bottom of this file. This alternatively is allowed to enable applications to be linked against the RPM library (commonly called librpm) without forcing such applications to be distributed under the GPL. Any questions regarding the licensing of RPM should be addressed to marc@redhat.com and ewt@redhat.com. */ #include #include #include #include #include static inline int rstreq(const char *s1, const char *s2) { return (strcmp(s1, s2) == 0); } static inline int rislower(int c) { return (c >= 'a' && c <= 'z'); } static inline int risupper(int c) { return (c >= 'A' && c <= 'Z'); } static inline int risalpha(int c) { return (rislower(c) || risupper(c)); } static inline int risdigit(int c) { return (c >= '0' && c <= '9'); } static inline int risalnum(int c) { return (risalpha(c) || risdigit(c)); } static int rpmvercmp(const char * a, const char * b) { /* easy comparison to see if versions are identical */ if (rstreq(a, b)) return 0; char oldch1, oldch2; char abuf[strlen(a)+1], bbuf[strlen(b)+1]; char *str1 = abuf, *str2 = bbuf; char * one, * two; int rc; int isnum; strcpy(str1, a); strcpy(str2, b); one = str1; two = str2; /* loop through each version segment of str1 and str2 and compare them */ while (*one || *two) { while (*one && !risalnum(*one) && *one != '~') one++; while (*two && !risalnum(*two) && *two != '~') two++; /* handle the tilde separator, it sorts before everthing else */ if (*one == '~' || *two == '~') { if (*one != '~') return 1; if (*two != '~') return -1; one++; two++; continue; } /* If we ran to the end of either, we are finished with the loop */ if (!(*one && *two)) break; str1 = one; str2 = two; /* grab first completely alpha or completely numeric segment */ /* leave one and two pointing to the start of the alpha or numeric */ /* segment and walk str1 and str2 to end of segment */ if (risdigit(*str1)) { while (*str1 && risdigit(*str1)) str1++; while (*str2 && risdigit(*str2)) str2++; isnum = 1; } else { while (*str1 && risalpha(*str1)) str1++; while (*str2 && risalpha(*str2)) str2++; isnum = 0; } /* save character at the end of the alpha or numeric segment */ /* so that they can be restored after the comparison */ oldch1 = *str1; *str1 = '\0'; oldch2 = *str2; *str2 = '\0'; /* this cannot happen, as we previously tested to make sure that */ /* the first string has a non-null segment */ if (one == str1) return -1; /* arbitrary */ /* take care of the case where the two version segments are */ /* different types: one numeric, the other alpha (i.e. empty) */ /* numeric segments are always newer than alpha segments */ /* XXX See patch #60884 (and details) from bugzilla #50977. */ if (two == str2) return (isnum ? 1 : -1); if (isnum) { size_t onelen, twolen; /* this used to be done by converting the digit segments */ /* to ints using atoi() - it's changed because long */ /* digit segments can overflow an int - this should fix that. */ /* throw away any leading zeros - it's a number, right? */ while (*one == '0') one++; while (*two == '0') two++; /* whichever number has more digits wins */ onelen = strlen(one); twolen = strlen(two); if (onelen > twolen) return 1; if (twolen > onelen) return -1; } /* strcmp will return which one is greater - even if the two */ /* segments are alpha or if they are numeric. don't return */ /* if they are equal because there might be more segments to */ /* compare */ rc = strcmp(one, two); if (rc) return (rc < 1 ? -1 : 1); /* restore character that was replaced by null above */ *str1 = oldch1; one = str1; *str2 = oldch2; two = str2; } /* this catches the case where all numeric and alpha segments have */ /* compared identically but the segment sepparating characters were */ /* different */ if ((!*one) && (!*two)) return 0; /* whichever version still has characters left over wins */ if (!*one) return -1; else return 1; } typedef struct { char *epoch; char *version; char *release; } EVR; static void parseEVR(char * evr, EVR *evr_parsed) { char *s, *se; s = evr; while (*s && risdigit(*s)) s++; /* s points to epoch terminator */ se = strrchr(s, '-'); /* se points to version terminator */ if (*s == ':') { evr_parsed->epoch = evr; *s++ = '\0'; evr_parsed->version = s; if (*(evr_parsed->epoch) == '\0') evr_parsed->epoch = "0"; } else { evr_parsed->epoch = NULL; /* XXX disable epoch compare if missing */ evr_parsed->version = evr; } if (se) { *se++ = '\0'; evr_parsed->release = se; } else { evr_parsed->release = NULL; } } static int rpmVersionCompare(EVR *first, EVR *second) { uint32_t epochOne = first->epoch ? atoi(first->epoch) : 0; uint32_t epochTwo = second->epoch ? atoi(second->epoch) : 0; int rc; if (epochOne < epochTwo) return -1; else if (epochOne > epochTwo) return 1; rc = rpmvercmp(first->version, second->version); if (rc) return rc; return rpmvercmp(first->release ? first->release : "", second->release ? second->release : ""); } static void usage(void) { fprintf(stderr, "Usage: rpmvercmp lt \n"); fprintf(stderr, " rpmvercmp eq \n"); fprintf(stderr, "\n"); fprintf(stderr, "Returns 0 if requested comparison holds, 1 otherwise\n"); } int main(int argc, char **argv) { if (argc != 4) { usage(); exit(255); } if (!rstreq(argv[2], "lt") && !rstreq(argv[2], "eq")) { usage(); exit(255); } EVR first, second; parseEVR(argv[1], &first); parseEVR(argv[3], &second); int rc = rpmVersionCompare(&first, &second); if (rstreq(argv[2], "lt")) { exit(rc == -1 ? EXIT_SUCCESS : EXIT_FAILURE); } else { exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } } cfengine-3.6.2/tests/0000775000175100017510000000000012413020725014154 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/unit/0000775000175100017510000000000012413020725015133 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/unit/csv_parser_test.c0000664000175100017510000001137612400110676020516 0ustar00a10038a1003800000000000000#include #include #include #include #include static void test_new_csv_reader_basic() { Seq *list = NULL; char *lines[5] = { "aaaa,bbb,ccccc", "\"aaaa\",\"bbb\",\"ccccc\"", "\"aaaa\",bbb,\"ccccc\"", "aaaa,\"bbb\",ccccc", ",\"bbb\",ccccc", }; for (int i=0; i<5; i++) { list = SeqParseCsvString(lines[i]); assert_int_equal(list->length, 3); assert_string_equal(list->data[2], "ccccc"); if (list != NULL) { SeqDestroy(list); } else { assert_true(false); } } } static void test_new_csv_reader() { Seq *list = NULL; char line[]=" Type ,\"walo1\", \"walo2\" , \"wal,o \"\" 3\", \" ab,cd \", walo solo ,, \"walo\""; list = SeqParseCsvString(line); assert_int_equal(list->length, 8); assert_string_equal(list->data[3], "wal,o \" 3"); assert_string_equal(list->data[6], ""); assert_string_equal(list->data[7], "walo"); if (list != NULL) { SeqDestroy(list); } else { assert_true(false); } } static void test_new_csv_reader_lfln() { Seq *list = NULL; char line[]=" Type ,\"walo1\", \"walo2\" , \"wa\r\nl,o\n \"\"\r 3\", \" ab,cd \", walo solo ,, \"walo\" "; list = SeqParseCsvString(line); assert_int_equal(list->length, 8); assert_string_equal(list->data[3], "wa\r\nl,o\n \"\r 3"); if (list != NULL) { SeqDestroy(list); } else { assert_true(false); } } static void test_new_csv_reader_lfln_at_end() { Seq *list = NULL; char line[]=" Type ,\"walo1\", \"walo2\" , \"wal\r\n,o \"\" 3\", \" ab,cd \", walo solo , , \"walo\" \r\n "; list = SeqParseCsvString(line); assert_int_equal(list->length, 8); assert_string_equal(list->data[3], "wal\r\n,o \" 3"); assert_string_equal(list->data[6], " "); assert_string_equal(list->data[7], "walo"); if (list != NULL) { SeqDestroy(list); } else { assert_true(false); } } static void test_new_csv_reader_lfln_at_end2() { Seq *list = NULL; char line[]=" Type ,\"walo1\", \"walo2\" , \"wal\r\n,o \"\" 3\", \" ab,cd \", walo solo , ,walo\r\n"; list = SeqParseCsvString(line); assert_int_equal(list->length, 8); assert_string_equal(list->data[7], "walo"); if (list != NULL) { SeqDestroy(list); } else { assert_true(false); } } static void test_new_csv_reader_lfln_at_end3() { Seq *list = NULL; char line[]=" Type ,\"walo1\", \"walo2\" , \"wal\r\n,o \"\" 3\", \" ab,cd \", walo solo , , \r\n"; list = SeqParseCsvString(line); assert_int_equal(list->length, 8); assert_string_equal(list->data[7], " "); if (list != NULL) { SeqDestroy(list); } else { assert_true(false); } } static void test_get_next_line() { FILE *fp = fopen("./data/csv_file.csv", "r"); assert_true(fp); { char *line = GetCsvLineNext(fp); assert_true(line); assert_string_equal(line, "field_1, field_2\r\n"); Seq *list = SeqParseCsvString(line); assert_true(list); assert_int_equal(SeqLength(list), 2); assert_string_equal(SeqAt(list, 0), "field_1"); assert_string_equal(SeqAt(list, 1), " field_2"); SeqDestroy(list); free(line); } { char *line = GetCsvLineNext(fp); assert_true(line); assert_string_equal(line, "field_1, \"value1 \nvalue2 \nvalue3\"\r\n"); Seq *list = SeqParseCsvString(line); assert_true(list); assert_int_equal(SeqLength(list), 2); assert_string_equal(SeqAt(list, 0), "field_1"); assert_string_equal(SeqAt(list, 1), "value1 \nvalue2 \nvalue3"); SeqDestroy(list); free(line); } { char *line = GetCsvLineNext(fp); assert_true(line); assert_string_equal(line, "field_1, \"field,2\"\r\n"); Seq *list = SeqParseCsvString(line); assert_true(list); assert_int_equal(SeqLength(list), 2); assert_string_equal(SeqAt(list, 0), "field_1"); assert_string_equal(SeqAt(list, 1), "field,2"); SeqDestroy(list); free(line); } fclose(fp); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_new_csv_reader_basic), unit_test(test_new_csv_reader), unit_test(test_new_csv_reader_lfln), unit_test(test_new_csv_reader_lfln_at_end), unit_test(test_new_csv_reader_lfln_at_end2), unit_test(test_new_csv_reader_lfln_at_end3), unit_test(test_get_next_line) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/linux_process_test.c0000664000175100017510000000726212400110676021243 0ustar00a10038a1003800000000000000#include #include #include #include /* Stubs for /proc//stat. */ static const char *filecontents[2] = { "1 (i()))))))-:!#!#@)) S 1 3927 3927 1025 3927 4202752 359 0 2 0 0 0 0 0 20 0 1 0 65535 19234816 226 18446744073709551615 1 1 0 0 0 0 0 6 0 18446744073709551615 0 0 17 2 0 0 40 0 0", "3929 (getty) T 1 3929 3929 1027 3929 4202752 359 0 1 0 0 0 0 0 20 0 1 0 100000 19234816 225 18446744073709551615 1 1 0 0 0 0 0 6 0 18446744073709551615 0 0 17 0 0 0 42 0 0", }; static int filepos[2]; int open(const char *filename, ARG_UNUSED int flags, ...) { if (!strcmp(filename, "/proc/1/stat")) { filepos[0] = 0; return 0; } else if (!strcmp(filename, "/proc/2/stat")) { filepos[1] = 0; static int got_intr = false; if (!got_intr) { got_intr = true; errno = EINTR; return -1; } return 1; } else if (!strcmp(filename, "/proc/666/stat")) { errno = EACCES; return -1; } else { errno = ENOENT; return -1; } } ssize_t read(int fd, void *buffer, ARG_UNUSED size_t buf_size) { if (fd == 0) { if (filepos[0] < strlen(filecontents[0])) { memcpy(buffer, filecontents[0], strlen(filecontents[0])); filepos[0] = strlen(filecontents[0]); return strlen(filecontents[0]); } else { return 0; } } if (fd == 1) { static bool got_eintr = false; if (!got_eintr) { got_eintr = true; errno = EINTR; return -1; } else { got_eintr = false; } if (filepos[1] < strlen(filecontents[1])) { memcpy(buffer, filecontents[1] + filepos[1], 1); filepos[1]++; return 1; } else { return 0; } } errno = EIO; return -1; } int close(ARG_UNUSED int fd) { return 0; } static void test_get_start_time_process1(void) { time_t t = GetProcessStartTime(1); assert_int_equal(t, 65535 / sysconf(_SC_CLK_TCK)); } static void test_get_start_time_process2(void) { time_t t2 = GetProcessStartTime(2); assert_int_equal(t2, 100000 / sysconf(_SC_CLK_TCK)); } static void test_get_start_time_process3(void) { time_t t3 = GetProcessStartTime(3); assert_int_equal(t3, PROCESS_START_TIME_UNKNOWN); } static void test_get_start_time_process666(void) { time_t t4 = GetProcessStartTime(666); assert_int_equal(t4, PROCESS_START_TIME_UNKNOWN); } static void test_get_state_process1(void) { ProcessState s = GetProcessState(1); assert_int_equal(s, PROCESS_STATE_RUNNING); } static void test_get_state_process2(void) { ProcessState s = GetProcessState(2); assert_int_equal(s, PROCESS_STATE_STOPPED); } static void test_get_state_process3(void) { ProcessState s = GetProcessState(3); assert_int_equal(s, PROCESS_STATE_DOES_NOT_EXIST); } static void test_get_state_process666(void) { ProcessState s = GetProcessState(666); assert_int_equal(s, PROCESS_STATE_DOES_NOT_EXIST); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_get_start_time_process1), unit_test(test_get_start_time_process2), unit_test(test_get_start_time_process3), unit_test(test_get_start_time_process666), unit_test(test_get_state_process1), unit_test(test_get_state_process2), unit_test(test_get_state_process3), unit_test(test_get_state_process666), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/item_test.c0000644000175100017510000000601712316547775017323 0ustar00a10038a1003800000000000000#include #include #include static void test_prepend_item(void) { Item *ip = NULL, *list = NULL; ip = PrependItem(&list, "hello", "classes"); assert_int_not_equal(ip, NULL); assert_int_not_equal(list, NULL); DeleteItem(&list, ip); assert_int_equal(list, NULL); } static void test_list_len(void) { Item *list = NULL; PrependItem(&list, "one", "classes"); PrependItem(&list, "two", NULL); PrependItem(&list, "three", NULL); assert_int_equal(ListLen(list), 3); DeleteItemList(list); } /* FIXME: those functions are now internal to cf-agent */ #if 0 static void test_list_select_last_matching_finds_first(void) { EvalContext *ctx = EvalContextNew(); Item *list = NULL, *match = NULL, *prev = NULL; bool result = false; AppendItem(&list, "abc", NULL); AppendItem(&list, "def", NULL); AppendItem(&list, "ghi", NULL); AppendItem(&list, "jkl", NULL); result = SelectLastItemMatching(ctx, "abc", list, NULL, &match, &prev); assert_true(result); assert_int_equal(match, list); assert_int_equal(prev, CF_UNDEFINED_ITEM); DeleteItemList(list); EvalContextDestroy(ctx); } static void test_list_select_last_matching_finds_last(void) { EvalContext *ctx = EvalContextNew(); Item *list = NULL, *match = NULL, *prev = NULL; bool result; AppendItem(&list, "abc", NULL); AppendItem(&list, "def", NULL); AppendItem(&list, "ghi", NULL); AppendItem(&list, "abc", NULL); result = SelectLastItemMatching(ctx, "abc", list, NULL, &match, &prev); assert_true(result); assert_int_equal(match, list->next->next->next); assert_int_equal(prev, list->next->next); DeleteItemList(list); EvalContextDestroy(ctx); } static void test_list_select_last_matching_not_found(void) { EvalContext *ctx = EvalContextNew(); Item *list = NULL, *match = NULL, *prev = NULL; bool result; AppendItem(&list, "abc", NULL); AppendItem(&list, "def", NULL); AppendItem(&list, "ghi", NULL); AppendItem(&list, "abc", NULL); result = SelectLastItemMatching(ctx, "xyz", list, NULL, &match, &prev); assert_false(result); assert_int_equal(match, CF_UNDEFINED_ITEM); assert_int_equal(prev, CF_UNDEFINED_ITEM); DeleteItemList(list); EvalContextDestroy(ctx); } #endif static void test_list_compare(void) { Item *list1 = NULL, *list2 = NULL; bool result; result = ListsCompare(list1, list2); assert_true(result); AppendItem(&list1, "abc", NULL); AppendItem(&list1, "def", NULL); result = ListsCompare(list1, list2); assert_false(result); AppendItem(&list2, "def", NULL); AppendItem(&list2, "abc", NULL); result = ListsCompare(list1, list2); assert_true(result); DeleteItemList(list1); DeleteItemList(list2); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_prepend_item), unit_test(test_list_len), unit_test(test_list_compare) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/file_writer_test.c0000664000175100017510000000513412400110676020655 0ustar00a10038a1003800000000000000#include #include #include static Writer *global_w; static bool global_w_closed; /* Override libc's fwrite(). */ static size_t CFENGINE_TEST_fwrite(const void *ptr, size_t size, size_t nmemb, ARG_UNUSED FILE *stream) { for (int i = 0; i < nmemb; ++i) { char *b = xstrndup(ptr + i * size, size); WriterWrite(global_w, b); free(b); } return nmemb * size; } /* Override libc's fclose(). */ static int CFENGINE_TEST_fclose(ARG_UNUSED FILE *stream) { global_w_closed = true; return 0; } #include /* MUST be included after the overrides. */ void test_empty_file_buffer(void) { global_w = StringWriter(); global_w_closed = false; Writer *w = FileWriter(NULL); assert_int_equal(StringWriterLength(global_w), 0); assert_string_equal(StringWriterData(global_w), ""); WriterClose(w); WriterClose(global_w); assert_int_equal(global_w_closed, true); } void test_write_empty_file_buffer(void) { global_w = StringWriter(); Writer *w = FileWriter(NULL); WriterWrite(w, ""); assert_int_equal(StringWriterLength(global_w), 0); assert_string_equal(StringWriterData(global_w), ""); WriterClose(w); WriterClose(global_w); assert_int_equal(global_w_closed, true); } void test_write_file_buffer(void) { global_w = StringWriter(); Writer *w = FileWriter(NULL); WriterWrite(w, "123"); assert_int_equal(StringWriterLength(global_w), 3); assert_string_equal(StringWriterData(global_w), "123"); WriterClose(w); WriterClose(global_w); assert_int_equal(global_w_closed, true); } void test_multiwrite_file_buffer(void) { global_w = StringWriter(); Writer *w = FileWriter(NULL); WriterWrite(w, "123"); WriterWrite(w, "456"); assert_int_equal(StringWriterLength(global_w), 6); assert_string_equal(StringWriterData(global_w), "123456"); WriterClose(w); WriterClose(global_w); assert_int_equal(global_w_closed, true); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_empty_file_buffer), unit_test(test_write_empty_file_buffer), unit_test(test_write_file_buffer), unit_test(test_multiwrite_file_buffer), }; return run_tests(tests); } /* STUB */ void __ProgrammingError(ARG_UNUSED const char *file, ARG_UNUSED int lineno, ARG_UNUSED const char *format, ...) { fail(); exit(42); } void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } cfengine-3.6.2/tests/unit/mon_processes_test.c0000664000175100017510000000545612411001073021220 0ustar00a10038a1003800000000000000#include "test.h" #include "systype.h" #include "generic_agent.h" #include "item_lib.h" #include "mon.h" #include /* xsnprintf */ static void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/mon_processes_test.XXXXXX"); mkdtemp(CFWORKDIR); char buf[CF_BUFSIZE]; xsnprintf(buf, CF_BUFSIZE, "%s/state", CFWORKDIR); mkdir(buf, 0755); } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } static bool GetSysUsers( int *userListSz, int *numRootProcs, int *numOtherProcs) { FILE *fp; char user[CF_BUFSIZE]; char vbuff[CF_BUFSIZE]; char cbuff[CF_BUFSIZE]; #if defined(__sun) xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -eo user > %s/users.txt", CFWORKDIR); #elif defined(_AIX) xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -N -eo user > %s/users.txt", CFWORKDIR); #elif defined(__linux__) xsnprintf(cbuff, CF_BUFSIZE, "/bin/ps -eo user > %s/users.txt", CFWORKDIR); #else assert_true(1); return false; #endif Item *userList = NULL; system(cbuff); xsnprintf(cbuff, CF_BUFSIZE, "%s/users.txt", CFWORKDIR); if ((fp = fopen(cbuff, "r")) == NULL) { return false; } while (fgets(vbuff, CF_BUFSIZE, fp) != NULL) { sscanf(vbuff, "%s", user); if (strcmp(user, "USER") == 0) { continue; } if (!IsItemIn(userList, user)) { PrependItem(&userList, user, NULL); (*userListSz)++; } if (strcmp(user, "root") == 0) { (*numRootProcs)++; } else { (*numOtherProcs)++; } } fclose(fp); return true; } void test_processes_monitor(void) { # ifdef __sun return; //redmine 6316 # endif double cf_this[100] = { 0.0 }; MonProcessesGatherData(cf_this); MonProcessesGatherData(cf_this); MonProcessesGatherData(cf_this); int usr, rusr, ousr; usr = rusr = ousr = 0; bool res = GetSysUsers(&usr, &rusr, &ousr); if (res == false ) { assert_true(1); return; } usr = 3*usr; rusr = 3*rusr; ousr = 3*ousr; int upper = (int)((double)usr*1.10); int lower = (int)((double)usr*0.90); assert_in_range((long long)cf_this[ob_users], lower, upper); } int main() { strcpy(CFWORKDIR, "data"); #if defined(__sun) VSYSTEMHARDCLASS = PLATFORM_CONTEXT_SOLARIS; #elif defined(_AIX) VSYSTEMHARDCLASS = PLATFORM_CONTEXT_AIX; #elif defined(__linux__) VSYSTEMHARDCLASS = PLATFORM_CONTEXT_LINUX; #endif PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { unit_test(test_processes_monitor), }; int ret = run_tests(tests); tests_teardown(); return ret; } cfengine-3.6.2/tests/unit/addr_lib_test.c0000664000175100017510000000654312400110676020107 0ustar00a10038a1003800000000000000#include #include #include /** * @WARNING this test leaks all over the place. I'm strdup'ing because * ParseHostPort() might modify the string, and a string literal * will cause segfault since it is in read-only memory segment. */ static void test_ParseHostPort() { char *hostname, *port; ParseHostPort(xstrdup("www.cfengine.com"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("www.cfengine.com:80"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("www.cfengine.com:"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[www.cfengine.com]"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[www.cfengine.com]:80"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[www.cfengine.com]:"), &hostname, &port); assert_string_equal(hostname, "www.cfengine.com"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("1.2.3.4"), &hostname, &port); assert_string_equal(hostname, "1.2.3.4"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("1.2.3.4:80"), &hostname, &port); assert_string_equal(hostname, "1.2.3.4"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("1.2.3.4:"), &hostname, &port); assert_string_equal(hostname, "1.2.3.4"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[ffff::dd:12:34]"), &hostname, &port); assert_string_equal(hostname, "ffff::dd:12:34"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[ffff::dd:12:34]:80"), &hostname, &port); assert_string_equal(hostname, "ffff::dd:12:34"); assert_string_equal(port, "80"); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[ffff::dd:12:34]:"), &hostname, &port); assert_string_equal(hostname, "ffff::dd:12:34"); assert_int_equal(port, NULL); hostname = NULL; port = NULL; /***** CORNER CASES *****/ ParseHostPort(xstrdup(""), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[]"), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup("[]:"), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; ParseHostPort(xstrdup(":"), &hostname, &port); assert_int_equal(hostname, NULL); assert_int_equal(port, NULL); hostname = NULL; port = NULL; } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_ParseHostPort) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/csv_writer_test.c0000664000175100017510000000466012400110676020534 0ustar00a10038a1003800000000000000#include #include void test_empty(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), ""); } void test_single_field(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterField(c, "test"); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), "test\r\n"); } void test_several_fields(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterField(c, "test1"); CsvWriterField(c, "test2"); CsvWriterField(c, "test3"); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), "test1,test2,test3\r\n"); } void test_two_records(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterField(c, "test1"); CsvWriterNewRecord(c); CsvWriterField(c, "test2"); CsvWriterNewRecord(c); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), "test1\r\ntest2\r\n"); } void test_empty_record(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterNewRecord(c); CsvWriterField(c, "test2"); CsvWriterNewRecord(c); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), "\r\ntest2\r\n"); } void test_empty_last_record(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterField(c, "test1"); CsvWriterNewRecord(c); CsvWriterNewRecord(c); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), "test1\r\n\r\n"); } void test_escape(void) { Writer *w = StringWriter(); CsvWriter *c = CsvWriterOpen(w); CsvWriterField(c, ",\"\r\n"); CsvWriterClose(c); assert_string_equal(StringWriterClose(w), "\",\"\"\r\n\"\r\n"); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_empty), unit_test(test_single_field), unit_test(test_several_fields), unit_test(test_two_records), unit_test(test_empty_record), unit_test(test_empty_last_record), unit_test(test_escape), }; return run_tests(tests); } /* STUB OUT */ void __ProgrammingError(ARG_UNUSED const char *file, ARG_UNUSED int lineno, ARG_UNUSED const char *format, ...) { fail(); exit(42); } void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } cfengine-3.6.2/tests/unit/test.h0000664000175100017510000000160412400110676016265 0ustar00a10038a1003800000000000000/* ALWAYS INCLUDE FIRST, so that platform.h is included first as well! */ #ifndef CFENGINE_TEST_H #define CFENGINE_TEST_H #include #include #include #include #include #include /* Use this define for specific overrides inside all our source tree. */ #define CFENGINE_TEST char *file_read_string(FILE *in); void assert_file_equal(FILE *a, FILE *b); #define assert_double_close(a, b) _assert_double_close(a, b, __FILE__, __LINE__) void _assert_double_close(double left, double right, const char *const file, const int line); #define PRINT_TEST_BANNER() \ printf("==================================================\n"); \ printf("Starting test: %s\n", __FILE__); \ printf("==================================================\n") #endif cfengine-3.6.2/tests/unit/README0000664000175100017510000000640412236160673016031 0ustar00a10038a1003800000000000000How to add unit tests ===================== 1. Make sure what you are trying to write is actually a unit test. A unit test should execute in milliseconds. If you are testing functionality that e.g. requires a generic agent to be set up, consider writing an acceptance test. A unit test should test a small piece of code (a function) in isolation. 2. You typically want to test some function of a datastructure, e.g. CfAssoc. Check to see if a test suite (e.g. assoc_test.c), exists already. If not, create one. 2.1 (Optional) Creating a new test suite Create a new file, e.g. mystruct_test.c, preferably by copying some existing file so you get the boilerplate. In Makefile.am, append mystruct_test to check_PROGRAMS, and add an automake entry such as mystruct_test_SOURCES = $(MOCKERY_SOURCES) mystruct_test.c mystruct_test_LDADD = ../../libpromises/libpromises.la 3. We are using cmockery as our testing framework. Google for it and read/skim their basic intro page. 4. Suppose you want to test your new ToString function for CfAssoc. In assoc_test.c, you could do the following. 4.1 Write the test static test_to_string(void **state) { /* assert some condition here */ } 4.2 In the main function of assoc_test.c, add the test to the suite int main() { const UnitTest tests[] = { unit_test(test_create_destroy), unit_test(test_copy), unit_test(test_to_string) }; return run_tests(tests); } 5. Mocking. Suppose you want to test some function that calls a database, but you don't want to deal with setting up and managing the state of the database. Furthermore, you don't actually want to test the database in this test. What you need to do is to stub out the function. For example, suppose your tested function calls some DB_Insert("host123", 42); A mock function is a dummy replacement function with NOOP functionality, so in this case, in your test suite, you could add a static int written_measure = -1; static void DB_Insert(const char* key, int measure) { written_measure = measure; } Then, if later your function tries to retrieve it back, you could do static int DB_Query(const char*key) { return written_measure; } Now, the key is to not have the test link towards the actual definition of the function, so in Makefile.am, rather than linking against all of libpromises, you probably want to be more specific, for example str_test_SOURCES = $(MOCKERY_SOURCES) str_test.c ../../libpromises/string_lib.c str_test_LDADD = ../../libcompat/libcompat.la Finally, if you made some mocking functions and you think it will be useful to other tests later, consider extracting them in a separate file, e.g. db_mock.c. 6. Memory checking. We don't really care about the quality of code in the unit tests, but we do care that the code tested is not leaking memory. So it's important to free everything you allocate in the test code. Then, to check to see if your code leaks, you can run valgrind --leak-check=yes .libs/lt-mystruct_test Valgrind can do stuff beyond simple leak checking, so learning about it could be a worthwhile investment. cfengine-3.6.2/tests/unit/key_test.c0000664000175100017510000000517512400110676017137 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include /* * Initialization */ static int initialized = 0; static RSA *rsa = NULL; void test_setup() { rsa = RSA_new(); if (rsa) { BIGNUM *bn = NULL; bn = BN_new(); if (!bn) { RSA_free(rsa); initialized = 0; return; } BN_set_word(bn, 3); RSA_generate_key_ex(rsa, 1024, bn, NULL); BN_free(bn); } initialized = 1; } void test_teardown() { rsa = NULL; initialized = 0; } #define ASSERT_IF_NOT_INITIALIZED \ assert_int_equal(1, initialized) /* * Tests */ static void test_key_basic(void) { test_setup(); ASSERT_IF_NOT_INITIALIZED; Key *key = NULL; assert_true(key == NULL); key = KeyNew(rsa, HASH_METHOD_MD5); assert_true(key != NULL); assert_int_equal(HASH_METHOD_MD5, KeyHashMethod(key)); assert_true(rsa == KeyRSA(key)); unsigned int length = 0; assert_true(KeyBinaryHash(key, &length) != NULL); assert_int_equal(CF_MD5_LEN, length); assert_true(KeyPrintableHash(key) != NULL); /* Negative cases */ assert_true(NULL == KeyNew(NULL, HASH_METHOD_MD5)); assert_true(NULL == KeyNew(rsa, HASH_METHOD_NONE)); assert_true(NULL == KeyNew(NULL, HASH_METHOD_NONE)); /* Finish */ KeyDestroy(&key); assert_true(key == NULL); test_teardown(); } static void test_key_hash(void) { test_setup(); ASSERT_IF_NOT_INITIALIZED; Key *key = NULL; assert_true(key == NULL); key = KeyNew(rsa, HASH_METHOD_MD5); assert_true(key != NULL); assert_int_equal(HASH_METHOD_MD5, KeyHashMethod(key)); /* We now examine the first four bytes of the hash, to check the printable bit */ const char *md5_hash = KeyPrintableHash(key); assert_true((md5_hash[0] == 'M') && (md5_hash[1] == 'D') && (md5_hash[2] == '5') && (md5_hash[3] == '=')); /* When we change the hashing algorithm, a new hash is automatically generated. */ assert_int_equal(0, KeySetHashMethod(key, HASH_METHOD_SHA256)); const char *sha256_hash = KeyPrintableHash(key); assert_true((sha256_hash[0] == 'S') && (sha256_hash[1] == 'H') && (sha256_hash[2] == 'A') && (sha256_hash[3] == '=')); KeyDestroy(&key); test_teardown(); } /* * Main routine * Notice the calls to both setup and teardown. */ int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_key_basic), unit_test(test_key_hash) }; OpenSSL_add_all_digests(); int result = run_tests(tests); return result; } cfengine-3.6.2/tests/unit/rb-tree-test.c0000664000175100017510000001114412243421446017623 0ustar00a10038a1003800000000000000#include #include #include #include #include static void *_IntCopy(const void *_a) { return xmemdup(_a, sizeof(int)); } static int _IntCompare(const void *_a, const void *_b) { const int *a = _a, *b = _b; return *a - *b; } static RBTree *IntTreeNew_(void) { return RBTreeNew(_IntCopy, _IntCompare, free, _IntCopy, _IntCompare, free); } static void test_new_destroy(void) { RBTree *t = IntTreeNew_(); RBTreeDestroy(t); } static void test_put_overwrite(void) { RBTree *t = IntTreeNew_(); int a = 42; assert_false(RBTreePut(t, &a, &a)); int *r = RBTreeGet(t, &a); assert_int_equal(a, *r); assert_true(RBTreePut(t, &a, &a)); r = RBTreeGet(t, &a); assert_int_equal(a, *r); RBTreeDestroy(t); } static void test_put_remove(void) { RBTree *t = IntTreeNew_(); int a = 42; assert_false(RBTreePut(t, &a, &a)); int *r = RBTreeGet(t, &a); assert_int_equal(a, *r); assert_true(RBTreeRemove(t, &a)); r = RBTreeGet(t, &a); assert_true(r == NULL); assert_false(RBTreeRemove(t, &a)); r = RBTreeGet(t, &a); assert_true(r == NULL); RBTreeDestroy(t); } static void test_put_remove_inorder(void) { RBTree *t = IntTreeNew_(); for (int i = 0; i < 20000; i++) { RBTreePut(t, &i, &i); } for (int i = 0; i < 20000; i++) { int *r = RBTreeGet(t, &i); assert_int_equal(i, *r); } for (int i = 0; i < 20000; i++) { RBTreeRemove(t, &i); } RBTreeDestroy(t); } static void test_iterate_empty(void) { RBTree *t = IntTreeNew_(); RBTreeIterator *it = RBTreeIteratorNew(t); void *r = NULL; while (RBTreeIteratorNext(it, &r, NULL)) { fail(); } assert_true(r == NULL); RBTreeIteratorDestroy(it); RBTreeDestroy(t); } static void test_iterate(void) { RBTree *t = IntTreeNew_(); for (int i = 0; i < 20; i++) { RBTreePut(t, &i, &i); } assert_int_equal(20, RBTreeSize(t)); RBTreeIterator *it = RBTreeIteratorNew(t); for (int i = 0; i < 20; i++) { int *k = NULL; int *v = NULL; assert_true(RBTreeIteratorNext(it, (void **)&k, (void **)&v)); assert_int_equal(i, *k); assert_int_equal(i, *v); } assert_false(RBTreeIteratorNext(it, NULL, NULL)); RBTreeIteratorDestroy(it); RBTreeDestroy(t); } static void test_put_remove_random(void) { Seq *nums = SeqNew(20000, free); srand(0); for (int i = 0; i < 20000; i++) { int k = rand() % 1000; SeqAppend(nums, xmemdup(&k, sizeof(int))); } RBTree *t = IntTreeNew_(); for (size_t i = 0; i < SeqLength(nums); i++) { RBTreePut(t, SeqAt(nums, i), SeqAt(nums, i)); } for (size_t i = 0; i < SeqLength(nums); i++) { int *k = SeqAt(nums, i); int *r = RBTreeGet(t, k); assert_int_equal(*k, *r); } for (size_t i = 0; i < SeqLength(nums); i++) { RBTreeRemove(t, SeqAt(nums, i)); } SeqDestroy(nums); RBTreeDestroy(t); } static void test_clear(void) { RBTree *t = IntTreeNew_(); for (int i = 0; i < 20000; i++) { RBTreePut(t, &i, &i); } int k = 5; assert_true(RBTreeGet(t, &k) != NULL); assert_int_equal(20000, RBTreeSize(t)); RBTreeClear(t); assert_true(RBTreeGet(t, &k) == NULL); assert_int_equal(0, RBTreeSize(t)); for (int i = 0; i < 20000; i++) { RBTreePut(t, &i, &i); } assert_true(RBTreeGet(t, &k) != NULL); assert_int_equal(20000, RBTreeSize(t)); RBTreeDestroy(t); } static void test_equal(void) { RBTree *a = IntTreeNew_(); RBTree *b = IntTreeNew_(); for (int i = 0; i < 20000; i++) { RBTreePut(a, &i, &i); RBTreePut(b, &i, &i); } assert_true(RBTreeEqual(a, b)); RBTreeDestroy(a); RBTreeDestroy(b); } static void test_copy(void) { RBTree *a = IntTreeNew_(); for (int i = 0; i < 20000; i++) { RBTreePut(a, &i, &i); } RBTree *b = RBTreeCopy(a, NULL, NULL); assert_true(RBTreeEqual(a, b)); RBTreeDestroy(a); RBTreeDestroy(b); } int main() { const UnitTest tests[] = { unit_test(test_new_destroy), unit_test(test_put_overwrite), unit_test(test_put_remove), unit_test(test_put_remove_inorder), unit_test(test_iterate_empty), unit_test(test_iterate), unit_test(test_put_remove_random), unit_test(test_clear), unit_test(test_equal), unit_test(test_copy), }; PRINT_TEST_BANNER(); return run_tests(tests); } cfengine-3.6.2/tests/unit/sort_test.c0000664000175100017510000000756112400110676017337 0ustar00a10038a1003800000000000000#include #include #include #include #include /* * Those testcases only perform smoke testing of sorting functionality. */ void test_sort_item_list_names(void) { Item *head = xcalloc(1, sizeof(Item)); head->name = "c"; head->next = xcalloc(1, sizeof(Item)); head->next->name = "b"; head->next->next = xcalloc(1, sizeof(Item)); head->next->next->name = "a"; Item *sorted = SortItemListNames(head); assert_string_equal(sorted->name, "a"); assert_string_equal(sorted->next->name, "b"); assert_string_equal(sorted->next->next->name, "c"); assert_int_equal(sorted->next->next->next, NULL); } void test_sort_item_list_classes(void) { Item *head = xcalloc(1, sizeof(Item)); head->classes = "b"; head->next = xcalloc(1, sizeof(Item)); head->next->classes = "c"; head->next->next = xcalloc(1, sizeof(Item)); head->next->next->classes = "a"; Item *sorted = SortItemListClasses(head); assert_string_equal(sorted->classes, "a"); assert_string_equal(sorted->next->classes, "b"); assert_string_equal(sorted->next->next->classes, "c"); assert_int_equal(sorted->next->next->next, NULL); } void test_sort_item_list_counters(void) { Item *head = xcalloc(1, sizeof(Item)); head->counter = -1; head->next = xcalloc(1, sizeof(Item)); head->next->counter = 42; head->next->next = xcalloc(1, sizeof(Item)); head->next->next->counter = 146; Item *sorted = SortItemListCounters(head); /* Weird. Counters are sorted backwards */ assert_int_equal(sorted->counter, 146); assert_int_equal(sorted->next->counter, 42); assert_int_equal(sorted->next->next->counter, -1); assert_int_equal(sorted->next->next->next, NULL); } void test_sort_item_list_times(void) { Item *head = xcalloc(1, sizeof(Item)); head->time = 1; head->next = xcalloc(1, sizeof(Item)); head->next->time = 1998; head->next->next = xcalloc(1, sizeof(Item)); head->next->next->time = 4000; Item *sorted = SortItemListCounters(head); assert_int_equal(sorted->time, 4000); assert_int_equal(sorted->next->time, 1998); assert_int_equal(sorted->next->next->time, 1); assert_int_equal(sorted->next->next->next, NULL); } int FirstItemShorter(const char *lhs, const char *rhs) { return strlen(lhs) < strlen(rhs); } void test_sort_rlist(void) { Rlist *list = NULL; RlistAppendScalar(&list, "bbb"); RlistAppendScalar(&list, "cc"); RlistAppendScalar(&list, "a"); Rlist *sorted = SortRlist(list, &FirstItemShorter); assert_string_equal(RlistScalarValue(sorted), "a"); assert_string_equal(RlistScalarValue(sorted->next), "cc"); assert_string_equal(RlistScalarValue(sorted->next->next), "bbb"); assert_int_equal(sorted->next->next->next, NULL); RlistDestroy(sorted); } void test_alpha_sort_rlist_names(void) { Rlist *list = NULL; RlistAppendScalar(&list, "c"); RlistAppendScalar(&list, "a"); RlistAppendScalar(&list, "b"); Rlist *sorted = AlphaSortRListNames(list); assert_string_equal(RlistScalarValue(sorted), "a"); assert_string_equal(RlistScalarValue(sorted->next), "b"); assert_string_equal(RlistScalarValue(sorted->next->next), "c"); assert_int_equal(sorted->next->next->next, NULL); RlistDestroy(sorted); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_sort_item_list_names), unit_test(test_sort_item_list_classes), unit_test(test_sort_item_list_counters), unit_test(test_sort_item_list_times), unit_test(test_sort_rlist), unit_test(test_alpha_sort_rlist_names), }; return run_tests(tests); } /* STUBS */ /* void __ProgrammingError(const char *file, int lineno, const char *format, ...) { fail(); exit(42); } void FatalError(char *s, ...) { fail(); exit(42); } */ cfengine-3.6.2/tests/unit/conversion_test.c0000664000175100017510000000134312243421446020532 0ustar00a10038a1003800000000000000#include #include #include static void test_str_to_service_policy(void) { assert_int_equal(ServicePolicyFromString("start"), SERVICE_POLICY_START); assert_int_equal(ServicePolicyFromString("restart"), SERVICE_POLICY_RESTART); } static void test_double_from_string(void) { { double val; assert_true(DoubleFromString("1.2k", &val)); assert_double_close(1200.0, val); } { double val; assert_false(DoubleFromString("abc", &val)); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_str_to_service_policy), unit_test(test_double_from_string), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/version_test.c0000664000175100017510000001335012400110676020026 0ustar00a10038a1003800000000000000#include #include #include #include #include static void test_creation_destruction(void) { char right_version[] = "1.2.3"; char wrong_version[] = "a.0.1"; char right_unix_version[] = "1.2.3-4"; char wrong_unix_version_0[] = "3-5.1-1"; char wrong_unix_version_1[] = "3.5-1-1"; char wrong_unix_version_2[] = "3.5.1.1"; char right_windows_version[] = "1.2.3.4-5"; char wrong_windows_version_0[] = "3-5.1.0-1"; char wrong_windows_version_1[] = "3.5-1.0-1"; char wrong_windows_version_2[] = "3.5.1-0-1"; char wrong_windows_version_3[] = "3.5.1.0.1"; char large_version_0[] = "256.1.2.3-4"; char large_version_1[] = "1.256.3-4"; char large_version_2[] = "1.2.256.3-4"; char large_version_3[] = "1.2.3.256-4"; Version *version = NULL; version = VersionNew(); assert_true (version != NULL); assert_int_equal(version->major, 0); assert_int_equal(version->minor, 0); assert_int_equal(version->patch, 0); assert_int_equal(version->extra, 0); assert_int_equal(version->build, 0); VersionDestroy(&version); assert_true (version == NULL); version = VersionNewFromCharP(right_version, strlen(right_version)); assert_true(version != NULL); assert_int_equal(version->major, 1); assert_int_equal(version->minor, 2); assert_int_equal(version->patch, 3); assert_int_equal(version->extra, 0); assert_int_equal(version->build, 0); VersionDestroy(&version); assert_true (version == NULL); version = VersionNewFromCharP(right_unix_version, strlen(right_unix_version)); assert_true(version != NULL); assert_int_equal(version->major, 1); assert_int_equal(version->minor, 2); assert_int_equal(version->patch, 3); assert_int_equal(version->extra, 0); assert_int_equal(version->build, 4); VersionDestroy(&version); assert_true (version == NULL); version = VersionNewFromCharP(right_windows_version, strlen(right_windows_version)); assert_true(version != NULL); assert_int_equal(version->major, 1); assert_int_equal(version->minor, 2); assert_int_equal(version->patch, 3); assert_int_equal(version->extra, 4); assert_int_equal(version->build, 5); VersionDestroy(&version); assert_true (version == NULL); version = VersionNewFromCharP(wrong_version, strlen(wrong_version)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_unix_version_0, strlen(wrong_unix_version_0)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_unix_version_1, strlen(wrong_unix_version_1)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_unix_version_2, strlen(wrong_unix_version_2)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_windows_version_0, strlen(wrong_windows_version_0)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_windows_version_1, strlen(wrong_windows_version_1)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_windows_version_2, strlen(wrong_windows_version_2)); assert_true(version == NULL); version = VersionNewFromCharP(wrong_windows_version_3, strlen(wrong_windows_version_3)); assert_true(version == NULL); version = VersionNewFromCharP(large_version_0, strlen(large_version_0)); assert_true(version == NULL); version = VersionNewFromCharP(large_version_1, strlen(large_version_1)); assert_true(version == NULL); version = VersionNewFromCharP(large_version_2, strlen(large_version_2)); assert_true(version == NULL); version = VersionNewFromCharP(large_version_3, strlen(large_version_3)); assert_true(version == NULL); /* Creation from a buffer uses the same path as the creation from a char p, we just test the two main cases */ Buffer *buffer = NULL; buffer = BufferNewFrom(right_version, strlen(right_version)); assert_true (buffer != NULL); version = VersionNewFrom(buffer); assert_true(version != NULL); assert_int_equal(version->major, 1); assert_int_equal(version->minor, 2); assert_int_equal(version->patch, 3); assert_int_equal(version->extra, 0); assert_int_equal(version->build, 0); VersionDestroy(&version); assert_true (version == NULL); BufferDestroy(buffer); buffer = BufferNewFrom(wrong_version, strlen(wrong_version)); assert_true (buffer != NULL); version = VersionNewFrom(buffer); assert_true(version == NULL); BufferDestroy(buffer); } static void test_comparison(void) { char lowest_version[] = "0.0.0.0-0"; char normal_version[] = "1.2.3.0-4"; char normal_version_with_extra[] = "1.2.3.9-4"; char highest_version[] = "255.255.255.0-255"; Version *a = NULL; Version *b = NULL; a = VersionNewFromCharP(lowest_version, strlen(lowest_version)); assert_true(a != NULL); b = VersionNewFromCharP(normal_version, strlen(normal_version)); assert_true(b != NULL); assert_true(VersionCompare(a, b) < 0); assert_true(VersionCompare(b, a) > 0); assert_true(VersionCompare(a, b) != 0); VersionDestroy(&a); assert_true(a == NULL); a = VersionNewFromCharP(normal_version_with_extra, strlen(normal_version_with_extra)); assert_true(a != NULL); assert_int_equal(VersionCompare(a,b), 0); VersionDestroy(&b); assert_true(b == NULL); b = VersionNewFromCharP(highest_version, strlen(highest_version)); assert_true(VersionCompare(a,b) < 0); VersionDestroy(&a); assert_true(a == NULL); VersionDestroy(&b); assert_true(b == NULL); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_creation_destruction) , unit_test(test_comparison) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/files_lib_test.c0000664000175100017510000001010712400110676020266 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ #define FILE_CONTENTS "8aysd9a8ydhsdkjnaldn12lk\njndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1lkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1lkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1lkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1lkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljew\nnbfdhwjebfkjhbnkjdn1lkdjn1lkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1l\rkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1\r\nlkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1lkjn38aysd9a8ydhsdkjnaldn12lkjndl1jndljewnbfdhwjebfkjhbnkjdn1lkdjn1lkjn3" #define FILE_SIZE (sizeof(FILE_CONTENTS) - 1) char CFWORKDIR[CF_BUFSIZE]; char FILE_NAME[CF_BUFSIZE]; char FILE_NAME_EMPTY[CF_BUFSIZE]; static void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/files_lib_test.XXXXXX"); mkdtemp(CFWORKDIR); xsnprintf(FILE_NAME, CF_BUFSIZE, "%s/cfengine_file_test", CFWORKDIR); xsnprintf(FILE_NAME_EMPTY, CF_BUFSIZE, "%s/cfengine_file_test_empty", CFWORKDIR); } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } void test_file_write(void) { bool res = FileWriteOver(FILE_NAME, FILE_CONTENTS); assert_true(res); } void test_file_read_all(void) { bool truncated; Writer *w = FileRead(FILE_NAME, FILE_SIZE, &truncated); assert_int_equal(StringWriterLength(w), FILE_SIZE); assert_string_equal(StringWriterData(w), FILE_CONTENTS); assert_int_equal(truncated, false); WriterClose(w); Writer *w2 = FileRead(FILE_NAME, FILE_SIZE * 10, &truncated); assert_int_equal(StringWriterLength(w2), FILE_SIZE); assert_string_equal(StringWriterData(w2), FILE_CONTENTS); assert_int_equal(truncated, false); WriterClose(w2); Writer *w3 = FileRead(FILE_NAME, FILE_SIZE * 10, NULL); assert_int_equal(StringWriterLength(w3), FILE_SIZE); assert_string_equal(StringWriterData(w3), FILE_CONTENTS); WriterClose(w3); } void test_file_read_truncate(void) { char expected_output[FILE_SIZE + 1]; bool truncated = false; Writer *w = FileRead(FILE_NAME, FILE_SIZE - 1, &truncated); assert_int_equal(StringWriterLength(w), FILE_SIZE - 1); strlcpy(expected_output, FILE_CONTENTS, FILE_SIZE); assert_string_equal(StringWriterData(w), expected_output); assert_int_equal(truncated, true); WriterClose(w); bool truncated2 = false; Writer *w2 = FileRead(FILE_NAME, 10, &truncated2); assert_int_equal(StringWriterLength(w2), 10); strlcpy(expected_output, FILE_CONTENTS, 11); assert_string_equal(StringWriterData(w2), expected_output); assert_int_equal(truncated2, true); WriterClose(w2); bool truncated3 = false; Writer *w3 = FileRead(FILE_NAME, 1, &truncated3); assert_int_equal(StringWriterLength(w3), 1); strlcpy(expected_output, FILE_CONTENTS, 2); assert_string_equal(StringWriterData(w3), expected_output); assert_int_equal(truncated3, true); WriterClose(w3); } void test_file_read_empty(void) { int creat_fd = creat(FILE_NAME_EMPTY, 0600); assert_true(creat_fd > -1); int close_res = close(creat_fd); assert_int_equal(close_res, 0); bool truncated = true; Writer *w = FileRead(FILE_NAME_EMPTY, 100, &truncated); assert_int_equal(StringWriterLength(w), 0); assert_string_equal(StringWriterData(w), ""); assert_int_equal(truncated, false); } void test_file_read_invalid(void) { Writer *w = FileRead("nonexisting file", 100, NULL); assert_false(w); } int main() { PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { unit_test(test_file_write), unit_test(test_file_read_all), unit_test(test_file_read_truncate), unit_test(test_file_read_empty), unit_test(test_file_read_invalid), }; int ret = run_tests(tests); tests_teardown(); return ret; } cfengine-3.6.2/tests/unit/process_terminate_unix_test.c0000664000175100017510000001525612400110676023141 0ustar00a10038a1003800000000000000#include #include #include #include /* This mock implements single fake process with a several tunable parameters: - process' start time, - reaction time for STOP/CONT/INT/TERM/KILL signal, - whether SIGINT/SIGTERM are blocked, - does the caller have permission to send signals to fake process This mock also records what signals were delivered to the process to check later. */ /* Settings */ time_t proc_1_start_time; time_t proc_1_reaction_time; bool proc_1_int_blocked; bool proc_1_term_blocked; bool proc_1_have_access; /* State */ time_t current_time; bool exists; bool stopped; time_t signal_time; bool has_stop; bool has_cont; bool has_int; bool has_term; bool has_kill; /* History */ bool was_stopped; int exit_signal; void InitTime(void) { current_time = 1; } void InitFakeProcess(time_t start_time, time_t reaction_time, bool int_blocked, bool term_blocked, bool have_access) { proc_1_start_time = start_time; proc_1_reaction_time = reaction_time; proc_1_int_blocked = int_blocked; proc_1_term_blocked = term_blocked; proc_1_have_access = have_access; exists = true; stopped = false; signal_time = -1; has_stop = false; has_cont = false; has_int = false; has_term = false; has_kill = false; was_stopped = false; exit_signal = 0; } time_t GetProcessStartTime(pid_t pid) { assert_int_equal(pid, 1); if (proc_1_have_access && exists) { return proc_1_start_time; } else { return PROCESS_START_TIME_UNKNOWN; } } ProcessState GetProcessState(pid_t pid) { assert_int_equal(pid, 1); if (!proc_1_have_access || !exists) { return PROCESS_STATE_DOES_NOT_EXIST; } if (stopped) { return PROCESS_STATE_STOPPED; } else { return PROCESS_STATE_RUNNING; } } int kill(pid_t pid, int signal) { assert_int_equal(pid, 1); if (!proc_1_have_access) { errno = EPERM; return -1; } if (!exists) { errno = ESRCH; return -1; } if (signal == 0) { return 0; } if (signal_time == -1) { signal_time = current_time + proc_1_reaction_time; } if (signal == SIGSTOP) { has_stop = true; } else if (signal == SIGCONT) { has_cont = true; } else if (signal == SIGINT) { has_int = true; } else if (signal == SIGTERM) { has_term = true; } else if (signal == SIGKILL) { has_kill = true; } else { errno = EINVAL; return -1; } return 0; } void FakeProcessDoSignals(void) { if (has_stop) { stopped = true; was_stopped = true; has_stop = false; } if (has_cont) { stopped = false; has_cont = false; } if (has_int) { if (!proc_1_int_blocked) { exists = false; exit_signal = SIGINT; stopped = false; signal_time = -1; } has_int = false; } if (has_term) { if (!proc_1_term_blocked) { exists = false; exit_signal = SIGTERM; stopped = false; signal_time = -1; } has_term = false; } if (has_kill) { exists = false; exit_signal = SIGKILL; stopped = false; signal_time = -1; has_kill = false; } signal_time = -1; } int nanosleep(const struct timespec *req, struct timespec *rem) { time_t sleep_time; /* Simulate EINTR every second time */ static bool got_eintr = false; if (!got_eintr) { got_eintr = true; sleep_time = 2 * req->tv_nsec / 3; } else { got_eintr = false; sleep_time = req->tv_nsec; } time_t next_time = current_time + sleep_time; if (signal_time != -1 && next_time >= signal_time) { FakeProcessDoSignals(); } current_time = next_time; if (got_eintr) { rem->tv_sec = 0; rem->tv_nsec = req->tv_nsec - sleep_time; errno = EINTR; return -1; } else { return 0; } } /* Tests */ void test_kill_simple_process(void) { InitTime(); InitFakeProcess(12345, 100, false, false, true); int res = GracefulTerminate(1, 12345); assert_true(res); FakeProcessDoSignals(); assert_false(exists); assert_int_equal(exit_signal, SIGINT); } void test_kill_wrong_process(void) { InitTime(); InitFakeProcess(66666, 100, false, false, true); int res = GracefulTerminate(1, 12345); assert_true(res); FakeProcessDoSignals(); assert_true(exists); assert_false(stopped); assert_false(was_stopped); /* We should not touch this process at all */ assert_int_equal(signal_time, (time_t)-1); /* No pending signals either */ } void test_kill_long_reacting_signal(void) { /* This process is very slow in reaction. It should not be left stopped though */ InitTime(); InitFakeProcess(12345, 2000000000, false, false, true); int res = GracefulTerminate(1, 12345); assert_true(res); FakeProcessDoSignals(); assert_true(exists); /* We should not kill this process */ assert_false(stopped); /* It should either be running or waiting to process SIGCONT */ } void test_kill_no_sigint(void) { /* This process blocks SIGINT */ InitTime(); InitFakeProcess(12345, 100, true, false, true); int res = GracefulTerminate(1, 12345); assert_true(res); FakeProcessDoSignals(); assert_false(exists); assert_int_equal(exit_signal, SIGTERM); } void test_kill_no_sigint_sigterm(void) { /* This process only can be killed by SIGKILL */ InitTime(); InitFakeProcess(12345, 100, true, true, true); int res = GracefulTerminate(1, 12345); assert_true(res); FakeProcessDoSignals(); assert_false(exists); assert_int_equal(exit_signal, SIGKILL); } void test_kill_anothers_process(void) { /* This process is not owned by killer */ InitTime(); InitFakeProcess(12345, 100, true, true, false); int res = GracefulTerminate(1, 12345); assert_true(res); FakeProcessDoSignals(); assert_true(exists); assert_false(was_stopped); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_kill_simple_process), unit_test(test_kill_wrong_process), unit_test(test_kill_long_reacting_signal), unit_test(test_kill_no_sigint), unit_test(test_kill_no_sigint_sigterm), unit_test(test_kill_anothers_process), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/policy_test.c0000664000175100017510000003354412400110676017647 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include #include #include /* xsnprintf */ static Policy *TestParsePolicy(const char *filename) { char path[PATH_MAX]; xsnprintf(path, sizeof(path), "%s/%s", TESTDATADIR, filename); return ParserParseFile(AGENT_TYPE_COMMON, path, PARSER_WARNING_ALL, PARSER_WARNING_ALL); } static void DumpErrors(Seq *errs) { if (SeqLength(errs) > 0) { Writer *writer = FileWriter(stdout); for (size_t i = 0; i < errs->length; i++) { PolicyErrorWrite(writer, errs->data[i]); } FileWriterDetach(writer); } } static Seq *LoadAndCheck(const char *filename) { Policy *p = TestParsePolicy(filename); Seq *errs = SeqNew(10, PolicyErrorDestroy); PolicyCheckPartial(p, errs); DumpErrors(errs); return errs; } static Seq *LoadAndCheckString(const char *policy_code) { char tmp[] = TESTDATADIR "/cfengine_test.XXXXXX"; mkstemp(tmp); { FILE *out = fopen(tmp, "w"); Writer *w = FileWriter(out); WriterWrite(w, policy_code); WriterClose(w); } Policy *p = ParserParseFile(AGENT_TYPE_COMMON, tmp, PARSER_WARNING_ALL, PARSER_WARNING_ALL); assert_true(p); Seq *errs = SeqNew(10, PolicyErrorDestroy); PolicyCheckPartial(p, errs); unlink(tmp); return errs; } static void test_failsafe(void) { char tmp[] = TESTDATADIR "/cfengine_test.XXXXXX"; mkstemp(tmp); WriteBuiltinFailsafePolicyToPath(tmp); Policy *failsafe = ParserParseFile(AGENT_TYPE_COMMON, tmp, PARSER_WARNING_ALL, PARSER_WARNING_ALL); unlink(tmp); assert_true(failsafe); Seq *errs = SeqNew(10, PolicyErrorDestroy); PolicyCheckPartial(failsafe, errs); DumpErrors(errs); assert_int_equal(0, SeqLength(errs)); { EvalContext *ctx = EvalContextNew(); PolicyCheckRunnable(ctx, failsafe, errs, false); DumpErrors(errs); assert_int_equal(0, SeqLength(errs)); EvalContextDestroy(ctx); } assert_int_equal(0, (SeqLength(errs))); SeqDestroy(errs); PolicyDestroy(failsafe); } static void test_bundle_redefinition(void) { Seq *errs = LoadAndCheck("bundle_redefinition.cf"); assert_int_equal(2, errs->length); SeqDestroy(errs); } static void test_bundle_reserved_name(void) { Seq *errs = LoadAndCheck("bundle_reserved_name.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } static void test_body_redefinition(void) { Seq *errs = LoadAndCheck("body_redefinition.cf"); assert_int_equal(2, errs->length); SeqDestroy(errs); } static void test_body_control_no_arguments(void) { Seq *errs = LoadAndCheck("body_control_no_arguments.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } static void test_vars_multiple_types(void) { Seq *errs = LoadAndCheck("vars_multiple_types.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } static void test_methods_invalid_arity(void) { Seq *errs = LoadAndCheck("methods_invalid_arity.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } static void test_promise_duplicate_handle(void) { Seq *errs = LoadAndCheck("promise_duplicate_handle.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } static void test_policy_json_to_from(void) { EvalContext *ctx = EvalContextNew(); Policy *policy = NULL; { Policy *original = TestParsePolicy("benchmark.cf"); JsonElement *json = PolicyToJson(original); PolicyDestroy(original); policy = PolicyFromJson(json); JsonDestroy(json); } assert_true(policy); assert_int_equal(1, SeqLength(policy->bundles)); assert_int_equal(2, SeqLength(policy->bodies)); { Bundle *main_bundle = PolicyGetBundle(policy, NULL, "agent", "main"); assert_true(main_bundle); { { const PromiseType *files = BundleGetPromiseType(main_bundle, "files"); assert_true(files); assert_int_equal(1, SeqLength(files->promises)); for (size_t i = 0; i < SeqLength(files->promises); i++) { Promise *promise = SeqAt(files->promises, i); if (strcmp("/tmp/stuff", promise->promiser) == 0) { assert_string_equal("any", promise->classes); assert_int_equal(2, SeqLength(promise->conlist)); { Constraint *create = PromiseGetConstraint(promise, "create"); assert_true(create); assert_string_equal("create", create->lval); assert_string_equal("true", RvalScalarValue(create->rval)); } { Constraint *create = PromiseGetConstraint(promise, "perms"); assert_true(create); assert_string_equal("perms", create->lval); assert_string_equal("myperms", RvalScalarValue(create->rval)); } } else { fprintf(stderr, "Found unknown promise"); fail(); } } } { const char* reportOutput[2] = { "Hello, CFEngine", "Hello, world" }; const char* reportClass[2] = { "cfengine", "any" }; const PromiseType *reports = BundleGetPromiseType(main_bundle, "reports"); assert_true(reports); assert_int_equal(2, SeqLength(reports->promises)); for (size_t i = 0; i < SeqLength(reports->promises); i++) { Promise *promise = SeqAt(reports->promises, i); if (strcmp(reportOutput[i], promise->promiser) == 0) { assert_string_equal(reportClass[i], promise->classes); assert_int_equal(1, SeqLength(promise->conlist)); { Constraint *friend_pattern = SeqAt(promise->conlist, 0); assert_true(friend_pattern); assert_string_equal("friend_pattern", friend_pattern->lval); assert_int_equal(RVAL_TYPE_FNCALL, friend_pattern->rval.type); FnCall *fn = RvalFnCallValue(friend_pattern->rval); assert_string_equal("hash", fn->name); assert_int_equal(2, RlistLen(fn->args)); } } else { fprintf(stderr, "Found unknown promise"); fail(); } } } } } { Body *myperms = PolicyGetBody(policy, NULL, "perms", "myperms"); assert_true(myperms); { Seq *mode_cps = BodyGetConstraint(myperms, "mode"); assert_int_equal(1, SeqLength(mode_cps)); Constraint *mode = SeqAt(mode_cps, 0); assert_string_equal("mode", mode->lval); assert_string_equal("555", RvalScalarValue(mode->rval)); } } PolicyDestroy(policy); EvalContextDestroy(ctx); } static void test_policy_json_offsets(void) { JsonElement *json = NULL; { Policy *original = TestParsePolicy("benchmark.cf"); json = PolicyToJson(original); PolicyDestroy(original); } assert_true(json); JsonElement *json_bundles = JsonObjectGetAsArray(json, "bundles"); { JsonElement *main_bundle = JsonArrayGetAsObject(json_bundles, 0); int line = JsonPrimitiveGetAsInteger(JsonObjectGet(main_bundle, "line")); assert_int_equal(9, line); JsonElement *json_promise_types = JsonObjectGetAsArray(main_bundle, "promiseTypes"); { JsonElement *json_reports_type = JsonArrayGetAsObject(json_promise_types, 0); line = JsonPrimitiveGetAsInteger(JsonObjectGet(json_reports_type, "line")); assert_int_equal(11, line); JsonElement *json_contexts = JsonObjectGetAsArray(json_reports_type, "contexts"); JsonElement *cf_context = JsonArrayGetAsObject(json_contexts, 0); JsonElement *cf_context_promises = JsonObjectGetAsArray(cf_context, "promises"); JsonElement *hello_cf_promise = JsonArrayGetAsObject(cf_context_promises, 0); line = JsonPrimitiveGetAsInteger(JsonObjectGet(hello_cf_promise, "line")); assert_int_equal(13, line); JsonElement *hello_cf_attribs = JsonObjectGetAsArray(hello_cf_promise, "attributes"); { JsonElement *friend_pattern_attrib = JsonArrayGetAsObject(hello_cf_attribs, 0); line = JsonPrimitiveGetAsInteger(JsonObjectGet(friend_pattern_attrib, "line")); assert_int_equal(14, line); } } } JsonElement *json_bodies = JsonObjectGetAsArray(json, "bodies"); { JsonElement *control_body = JsonArrayGetAsObject(json_bodies, 0); int line = JsonPrimitiveGetAsInteger(JsonObjectGet(control_body, "line")); assert_int_equal(4, line); JsonElement *myperms_body = JsonArrayGetAsObject(json_bodies, 1); line = JsonPrimitiveGetAsInteger(JsonObjectGet(myperms_body, "line")); assert_int_equal(28, line); JsonElement *myperms_contexts = JsonObjectGetAsArray(myperms_body, "contexts"); JsonElement *any_context = JsonArrayGetAsObject(myperms_contexts, 0); JsonElement *any_attribs = JsonObjectGetAsArray(any_context, "attributes"); { JsonElement *mode_attrib = JsonArrayGetAsObject(any_attribs, 0); line = JsonPrimitiveGetAsInteger(JsonObjectGet(mode_attrib, "line")); assert_int_equal(30, line); } } JsonDestroy(json); } static void test_util_bundle_qualified_name(void) { Bundle *b = xcalloc(1, sizeof(struct Bundle_)); assert_false(BundleQualifiedName(b)); b->name = "bar"; char *fqname = BundleQualifiedName(b); assert_string_equal("default:bar", fqname); free(fqname); b->ns = "foo"; fqname = BundleQualifiedName(b); assert_string_equal("foo:bar", fqname); free(fqname); free(b); } static void test_util_qualified_name_components(void) { { char *ns = QualifiedNameNamespaceComponent(":"); assert_string_equal("", ns); free(ns); char *sym = QualifiedNameScopeComponent(":"); assert_string_equal("", sym); free(sym); } { char *ns = QualifiedNameNamespaceComponent(""); assert_false(ns); free(ns); char *sym = QualifiedNameScopeComponent(""); assert_string_equal("", sym); free(sym); } { char *ns = QualifiedNameNamespaceComponent("foo"); assert_false(ns); free(ns); char *sym = QualifiedNameScopeComponent("foo"); assert_string_equal("foo", sym); free(sym); } { char *ns = QualifiedNameNamespaceComponent(":foo"); assert_string_equal("", ns); free(ns); char *sym = QualifiedNameScopeComponent(":foo"); assert_string_equal("foo", sym); free(sym); } { char *ns = QualifiedNameNamespaceComponent("foo:"); assert_string_equal("foo", ns); free(ns); char *sym = QualifiedNameScopeComponent("foo:"); assert_string_equal("", sym); free(sym); } { char *ns = QualifiedNameNamespaceComponent("foo:bar"); assert_string_equal("foo", ns); free(ns); char *sym = QualifiedNameScopeComponent("foo:bar"); assert_string_equal("bar", sym); free(sym); } } static void test_promiser_empty_varref(void) { Seq *errs = LoadAndCheck("promiser_empty_varref.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } static void test_constraint_comment_nonscalar(void) { Seq *errs = LoadAndCheck("constraint_comment_nonscalar.cf"); assert_int_equal(1, errs->length); SeqDestroy(errs); } // TODO: consider moving this into a mod_common_test static void test_body_action_with_log_repaired_needs_log_string(void) { { Seq *errs = LoadAndCheckString("body action foo {" " log_repaired => '/tmp/abc';" "}"); assert_int_equal(1, errs->length); SeqDestroy(errs); } { Seq *errs = LoadAndCheckString("body action foo {" " log_repaired => '/tmp/abc';" " log_string => 'stuff';" "}"); assert_int_equal(0, errs->length); SeqDestroy(errs); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_failsafe), unit_test(test_bundle_redefinition), unit_test(test_bundle_reserved_name), unit_test(test_body_redefinition), unit_test(test_body_control_no_arguments), unit_test(test_vars_multiple_types), unit_test(test_methods_invalid_arity), unit_test(test_promise_duplicate_handle), unit_test(test_policy_json_to_from), unit_test(test_policy_json_offsets), unit_test(test_util_bundle_qualified_name), unit_test(test_util_qualified_name_components), unit_test(test_constraint_comment_nonscalar), unit_test(test_promiser_empty_varref), unit_test(test_body_action_with_log_repaired_needs_log_string), }; return run_tests(tests); } // STUBS cfengine-3.6.2/tests/unit/changes_migration_test.c0000664000175100017510000001373512400110676022031 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include /* xsnprintf */ char CFWORKDIR[CF_BUFSIZE]; #include const char *GetWorkDir() { return CFWORKDIR; } #define NO_FILES 4 char *CHECKSUM_VALUE[NO_FILES] = { "0001", "0002", "0003", "0004", }; struct stat filestat_value; static void test_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/changes_migration_test.XXXXXX"); mkdtemp(CFWORKDIR); char state_dir[PATH_MAX]; xsnprintf(state_dir, sizeof(state_dir), "%s/state", CFWORKDIR); mkdir(state_dir, 0755); CF_DB *db; assert_true(OpenDB(&db, dbid_checksums)); // Hand crafted from the old version of NewIndexKey(). char checksum_key[NO_FILES][30] = { { 'M','D','5','\0','\0','\0','\0','\0', '/','e','t','c','/','h','o','s','t','s','\0' }, { 'M','D','5','\0','\0','\0','\0','\0', '/','e','t','c','/','p','a','s','s','w','d','\0' }, { 'M','D','5','\0','\0','\0','\0','\0', '/','f','i','l','e','1','\0' }, { 'M','D','5','\0','\0','\0','\0','\0', '/','f','i','l','e','2','\0' }, }; for (int c = 0; c < NO_FILES; c++) { int ksize = CHANGES_HASH_FILE_NAME_OFFSET + strlen(checksum_key[c] + CHANGES_HASH_FILE_NAME_OFFSET) + 1; int vsize = strlen(CHECKSUM_VALUE[c]) + 1; assert_true(WriteComplexKeyDB(db, checksum_key[c], ksize, CHECKSUM_VALUE[c], vsize)); } CloseDB(db); assert_true(OpenDB(&db, dbid_filestats)); char *filestat_key[NO_FILES] = { "/etc/hosts", "/etc/passwd", "/file1", "/file2", }; filestat_value.st_uid = 4321; memset(&filestat_value, 0, sizeof(filestat_value)); for (int c = 0; c < NO_FILES; c++) { assert_true(WriteDB(db, filestat_key[c], &filestat_value, sizeof(filestat_value))); } CloseDB(db); } static void test_migration(void) { CF_DB *db; Seq *list = SeqNew(NO_FILES, free); // Hand crafted from the new version of NewIndexKey(). char checksum_key[NO_FILES][30] = { { 'H','_','M','D','5','\0','\0','\0','\0','\0', '/','e','t','c','/','h','o','s','t','s','\0' }, { 'H','_','M','D','5','\0','\0','\0','\0','\0', '/','e','t','c','/','p','a','s','s','w','d','\0' }, { 'H','_','M','D','5','\0','\0','\0','\0','\0', '/','f','i','l','e','1','\0' }, { 'H','_','M','D','5','\0','\0','\0','\0','\0', '/','f','i','l','e','2','\0' }, }; char *filestat_key[NO_FILES] = { "S_/etc/hosts", "S_/etc/passwd", "S_/file1", "S_/file2", }; // Should cause migration to happen. assert_true(FileChangesGetDirectoryList("/etc", list)); assert_int_equal(SeqLength(list), 2); assert_string_equal(SeqAt(list, 0), "hosts"); assert_string_equal(SeqAt(list, 1), "passwd"); SeqClear(list); assert_true(FileChangesGetDirectoryList("/", list)); assert_int_equal(SeqLength(list), 2); assert_string_equal(SeqAt(list, 0), "file1"); assert_string_equal(SeqAt(list, 1), "file2"); assert_true(OpenDB(&db, dbid_changes)); for (int c = 0; c < NO_FILES; c++) { { int ksize = 2 + CHANGES_HASH_FILE_NAME_OFFSET + strlen(checksum_key[c] + 2 + CHANGES_HASH_FILE_NAME_OFFSET) + 1; int vsize = ValueSizeDB(db, checksum_key[c], ksize); assert_int_equal(vsize, strlen(CHECKSUM_VALUE[c]) + 1); char value[vsize]; assert_true(ReadComplexKeyDB(db, checksum_key[c], ksize, value, vsize)); assert_int_equal(memcmp(value, CHECKSUM_VALUE[c], vsize), 0); } { int vsize = ValueSizeDB(db, filestat_key[c], strlen(filestat_key[c]) + 1); assert_int_equal(vsize, sizeof(struct stat)); char value[vsize]; assert_true(ReadDB(db, filestat_key[c], value, vsize)); assert_int_equal(memcmp(value, &filestat_value, vsize), 0); } } int db_entries = 0; CF_DBC *db_cursor; assert_true(NewDBCursor(db, &db_cursor)); char *key, *value; int ksize, vsize; while (NextDB(db_cursor, &key, &ksize, (void **)&value, &vsize)) { db_entries++; } DeleteDBCursor(db_cursor); // 2 x Directories ("/" and "/etc") // 4 x File hashes // 4 x File stats assert_int_equal(db_entries, 10); CloseDB(db); } static void test_teardown(void) { DeleteDirectoryTree(CFWORKDIR); rmdir(CFWORKDIR); } int main() { const UnitTest tests[] = { unit_test(test_setup), unit_test(test_migration), unit_test(test_teardown), }; PRINT_TEST_BANNER(); int ret = run_tests(tests); return ret; } cfengine-3.6.2/tests/unit/var_expressions_test.c0000644000175100017510000001322112316547775021612 0ustar00a10038a1003800000000000000#include #include static void test_plain_variable_with_no_stuff_in_it(void) { VarRef *ref = VarRefParse("foo"); assert_false(ref->ns); assert_false(ref->scope); assert_string_equal("foo", ref->lval); assert_int_equal(0, ref->num_indices); assert_false(ref->indices); VarRefDestroy(ref); } static void test_scoped(void) { VarRef *ref = VarRefParse("scope.lval"); assert_false(ref->ns); assert_string_equal("scope", ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(0, ref->num_indices); assert_false(ref->indices); VarRefDestroy(ref); } static void test_full(void) { VarRef *ref = VarRefParse("ns:scope.lval"); assert_string_equal("ns", ref->ns); assert_string_equal("scope", ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(0, ref->num_indices); assert_false(ref->indices); VarRefDestroy(ref); } static void test_dotted_array(void) { VarRef *ref = VarRefParse("ns:scope.lval[la.la]"); assert_string_equal("ns", ref->ns); assert_string_equal("scope", ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(1, ref->num_indices); assert_string_equal("la.la", ref->indices[0]); VarRefDestroy(ref); } static void test_levels(void) { VarRef *ref = VarRefParse("ns:scope.lval[x][y][z]"); assert_string_equal("ns", ref->ns); assert_string_equal("scope", ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(3, ref->num_indices); assert_string_equal("x", ref->indices[0]); assert_string_equal("y", ref->indices[1]); assert_string_equal("z", ref->indices[2]); VarRefDestroy(ref); } static void test_unqualified_array(void) { VarRef *ref = VarRefParse("lval[x]"); assert_false(ref->ns); assert_false(ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(1, ref->num_indices); assert_string_equal("x", ref->indices[0]); VarRefDestroy(ref); } static void test_qualified_array(void) { VarRef *ref = VarRefParse("scope.lval[x]"); assert_false(ref->ns); assert_string_equal("scope", ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(1, ref->num_indices); assert_string_equal("x", ref->indices[0]); VarRefDestroy(ref); } static void test_nested_array(void) { VarRef *ref = VarRefParse("scope.lval[$(other[x])]"); assert_false(ref->ns); assert_string_equal("scope", ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(1, ref->num_indices); assert_string_equal("$(other[x])", ref->indices[0]); VarRefDestroy(ref); } static void test_array_with_dot_colon_in_index(void) { VarRef *ref = VarRefParse("lval[x-x.x:x]"); assert_false(ref->ns); assert_false(ref->scope); assert_string_equal("lval", ref->lval); assert_int_equal(1, ref->num_indices); assert_string_equal("x-x.x:x", ref->indices[0]); VarRefDestroy(ref); } static void test_special_scope(void) { { Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "ns", "b", "agent", NULL, NULL); { VarRef *ref = VarRefParseFromBundle("c.lval", bp); assert_string_equal("ns", ref->ns); assert_string_equal("c", ref->scope); assert_string_equal("lval", ref->lval); VarRefDestroy(ref); } { VarRef *ref = VarRefParseFromBundle("sys.lval", bp); assert_false(ref->ns); assert_string_equal("sys", ref->scope); assert_string_equal("lval", ref->lval); VarRefDestroy(ref); } } } static void CheckToStringQualified(const char *str, const char *expect) { VarRef *ref = VarRefParse(str); char *out = VarRefToString(ref, true); assert_string_equal(expect, out); free(out); VarRefDestroy(ref); } static void test_to_string_qualified(void) { CheckToStringQualified("ns:scope.lval[x][y]", "ns:scope.lval[x][y]"); CheckToStringQualified("ns:scope.lval[x]", "ns:scope.lval[x]"); CheckToStringQualified("ns:scope.lval", "ns:scope.lval"); CheckToStringQualified("scope.lval", "default:scope.lval"); CheckToStringQualified("lval", "lval"); } static void test_to_string_unqualified(void) { { VarRef *ref = VarRefParse("ns:scope.lval[x][y]"); char *out = VarRefToString(ref, false); assert_string_equal("lval[x][y]", out); free(out); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("ns:scope.lval[x]"); char *out = VarRefToString(ref, false); assert_string_equal("lval[x]", out); free(out); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("scope.lval"); char *out = VarRefToString(ref, false); assert_string_equal("lval", out); free(out); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("lval"); char *out = VarRefToString(ref, false); assert_string_equal("lval", out); free(out); VarRefDestroy(ref); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_plain_variable_with_no_stuff_in_it), unit_test(test_scoped), unit_test(test_full), unit_test(test_dotted_array), unit_test(test_levels), unit_test(test_unqualified_array), unit_test(test_qualified_array), unit_test(test_nested_array), unit_test(test_array_with_dot_colon_in_index), unit_test(test_special_scope), unit_test(test_to_string_qualified), unit_test(test_to_string_unqualified), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/string_expressions_test.c0000664000175100017510000000460212400110676022311 0ustar00a10038a1003800000000000000#include #include #include #include #include static char *ForbiddenVarRefEval(ARG_UNUSED const char *varname, ARG_UNUSED VarRefType type, ARG_UNUSED void *param) { fail(); } static char *IdentityVarRefEval(const char *varname, ARG_UNUSED VarRefType type, ARG_UNUSED void *param) { return xstrdup(varname); } static char *AppendAVarRefEval(const char *varname, ARG_UNUSED VarRefType type, ARG_UNUSED void *param) { return StringConcatenate(2, "a", varname); } static char *DiscriminateVarTypesVarRefEval(const char *varname, VarRefType type, ARG_UNUSED void *param) { if (type == VAR_REF_TYPE_SCALAR) { return StringConcatenate(3, "cozy(", varname, ")"); } else { return StringConcatenate(3, "ugly{", varname, "}"); } } static void CheckParse(const char *string_expression, const char *expected_output, VarRefEvaluator evaluator, void *param) { StringParseResult res = ParseStringExpression(string_expression, 0, strlen(string_expression)); assert_true(res.result); char *eval_result = EvalStringExpression(res.result, evaluator, param); assert_string_equal(expected_output, eval_result); free(eval_result); FreeStringExpression(res.result); } static void test_literal(void) { CheckParse("hello", "hello", ForbiddenVarRefEval, NULL); } static void test_var_naked(void) { CheckParse("$(foo)", "foo", IdentityVarRefEval, NULL); } static void test_var_naked_two_level(void) { CheckParse("$($(foo))", "aafoo", AppendAVarRefEval, NULL); } static void test_var_one_level(void) { CheckParse("$(foo)x$(bar)y$(baz)", "fooxbarybaz", IdentityVarRefEval, NULL); } static void test_different_var_types(void) { CheckParse("@{a$(b@(c)${d})@(e)}", "ugly{acozy(bugly{c}cozy(d))ugly{e}}", DiscriminateVarTypesVarRefEval, NULL); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_literal), unit_test(test_var_naked), unit_test(test_var_naked_two_level), unit_test(test_var_one_level), unit_test(test_different_var_types), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/class_test.c0000664000175100017510000000666312400110676017457 0ustar00a10038a1003800000000000000#include #include static void test_class_ref(void) { { ClassRef ref = ClassRefParse("class"); assert_true(ref.ns == NULL); assert_string_equal("class", ref.name); char *expr = ClassRefToString(ref.ns, ref.name); assert_string_equal("class", expr); free(expr); ClassRefDestroy(ref); } { ClassRef ref = ClassRefParse("default:class"); assert_string_equal("default", ref.ns); assert_string_equal("class", ref.name); char *expr = ClassRefToString(ref.ns, ref.name); assert_string_equal("class", expr); free(expr); ClassRefDestroy(ref); } { ClassRef ref = ClassRefParse("ns:class"); assert_string_equal("ns", ref.ns); assert_string_equal("class", ref.name); char *expr = ClassRefToString(ref.ns, ref.name); assert_string_equal("ns:class", expr); free(expr); ClassRefDestroy(ref); } } static void test_ns(void) { { ClassTable *t = ClassTableNew(); assert_false(ClassTablePut(t, "foo", "127.0.0.1", true, CONTEXT_SCOPE_BUNDLE, NULL)); Class *cls = ClassTableGet(t, "foo", "127_0_0_1"); assert_string_equal("foo", cls->ns); assert_string_equal("127_0_0_1", cls->name); assert_true(cls->is_soft); cls = ClassTableMatch(t, "foo:127_0_.*"); assert_true(cls); cls = ClassTableMatch(t, "foo:127_1_.*"); assert_false(cls); cls = ClassTableMatch(t, "127_0_.*"); assert_false(cls); ClassTableDestroy(t); } } static void test_default_ns(void) { { ClassTable *t = ClassTableNew(); assert_false(ClassTablePut(t, NULL, "127.0.0.1", false, CONTEXT_SCOPE_NAMESPACE, NULL)); Class *cls = ClassTableGet(t, NULL, "127_0_0_1"); assert_true(cls->ns == NULL); cls = ClassTableGet(t, "default", "127_0_0_1"); assert_true(cls->ns == NULL); assert_string_equal("127_0_0_1", cls->name); assert_false(cls->is_soft); cls = ClassTableMatch(t, "127_0_.*"); assert_true(cls); cls = ClassTableMatch(t, "127_1_.*"); assert_false(cls); ClassTableDestroy(t); } { ClassTable *t = ClassTableNew(); assert_false(ClassTablePut(t, "default", "127.0.0.1", false, CONTEXT_SCOPE_NAMESPACE, NULL)); Class *cls = ClassTableGet(t, NULL, "127_0_0_1"); assert_true(cls->ns == NULL); cls = ClassTableGet(t, "default", "127_0_0_1"); assert_true(cls->ns == NULL); assert_string_equal("127_0_0_1", cls->name); assert_false(cls->is_soft); ClassTableDestroy(t); } } static void test_put_replace(void) { ClassTable *t = ClassTableNew(); assert_false(ClassTablePut(t, NULL, "test", false, CONTEXT_SCOPE_NAMESPACE, NULL)); Class *cls = ClassTableGet(t, NULL, "test"); assert_true(cls); assert_int_equal(CONTEXT_SCOPE_NAMESPACE, cls->scope); assert_true(ClassTablePut(t, NULL, "test", true, CONTEXT_SCOPE_BUNDLE, NULL)); cls = ClassTableGet(t, NULL, "test"); assert_true(cls); assert_int_equal(CONTEXT_SCOPE_BUNDLE, cls->scope); ClassTableDestroy(t); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_default_ns), unit_test(test_ns), unit_test(test_class_ref), unit_test(test_put_replace), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/files_interfaces_test.c0000664000175100017510000000464212400110676021652 0ustar00a10038a1003800000000000000#include #include #include /* xsnprintf */ #define FILE_SIZE (sizeof(FILE_CONTENTS) - 1) #define FILE_LINE "some garbage!" #define FILE_CORRUPTED_LINE "some \0 , gar\0bage!" #define LINE_SIZE (sizeof(FILE_LINE) - 1) char CFWORKDIR[CF_BUFSIZE]; char FILE_NAME[CF_BUFSIZE]; char FILE_NAME_CORRUPT[CF_BUFSIZE]; char FILE_NAME_EMPTY[CF_BUFSIZE]; static void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/files_interfaces_test.XXXXXX"); mkdtemp(CFWORKDIR); xsnprintf(FILE_NAME, CF_BUFSIZE, "%s/cf_files_interfaces_test", CFWORKDIR); xsnprintf(FILE_NAME_CORRUPT, CF_BUFSIZE, "%s/cf_files_interfaces_test_corrupt", CFWORKDIR); xsnprintf(FILE_NAME_EMPTY, CF_BUFSIZE, "%s/cf_files_interfaces_test_empty", CFWORKDIR); } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } static void CreateGarbage(const char *filename) { FILE *fh = fopen(filename, "w"); for(int i = 0; i < 10; ++i) { fwrite(FILE_LINE, 14, 1, fh); } fclose(fh); } static void CreateCorruptedGarbage(const char *filename) { FILE *fh = fopen(filename, "w"); for(int i = 0; i < 10; ++i) { fwrite(FILE_CORRUPTED_LINE, 18, 1, fh); } fclose(fh); } static void test_cfreadline_valid(void) { CreateGarbage(FILE_NAME); FILE *fin = fopen(FILE_NAME, "r"); //test with non-empty file and valid file pointer size_t bs = CF_BUFSIZE; char *b = xmalloc(bs); ssize_t read = CfReadLine(&b, &bs, fin); assert_true(read > 0); assert_string_equal(b, FILE_LINE); if (fin) { fclose(fin); } free(b); } static void test_cfreadline_corrupted(void) { CreateCorruptedGarbage(FILE_NAME); FILE *fin = fopen(FILE_NAME, "r"); size_t bs = CF_BUFSIZE; char *b = xmalloc(bs); //test with non-empty file and valid file pointer ssize_t read = CfReadLine(&b, &bs, fin); assert_true(read > 0); assert_string_not_equal(b, FILE_LINE); if (fin) { fclose(fin); } free(b); } int main() { PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { unit_test(test_cfreadline_valid), unit_test(test_cfreadline_corrupted), }; PRINT_TEST_BANNER(); int ret = run_tests(tests); tests_teardown(); return ret; } cfengine-3.6.2/tests/unit/queue_test.c0000664000175100017510000000222512400110676017464 0ustar00a10038a1003800000000000000#include #include #include #include static void test_basics(void) { Queue *q = QueueNew(free); assert_int_equal(0, QueueCount(q)); assert_true(QueueIsEmpty(q)); QueueEnqueue(q, xstrdup("hello")); assert_int_equal(1, QueueCount(q)); assert_false(QueueIsEmpty(q)); assert_string_equal("hello", QueueHead(q)); QueueEnqueue(q, xstrdup("world")); assert_int_equal(2, QueueCount(q)); assert_string_equal("hello", QueueHead(q)); char *head = QueueDequeue(q); assert_string_equal("hello", head); free(head); assert_string_equal("world", QueueHead(q)); head = QueueDequeue(q); assert_string_equal("world", head); free(head); QueueDestroy(q); } static void test_destroy(void) { Queue *q = QueueNew(free); QueueEnqueue(q, xstrdup("1")); QueueEnqueue(q, xstrdup("2")); QueueEnqueue(q, xstrdup("3")); assert_int_equal(3, QueueCount(q)); QueueDestroy(q); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_basics), unit_test(test_destroy) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/file_lib_test.c0000664000175100017510000011246312411001073020103 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #define TEMP_DIR "/tmp/file_lib_test" #define TEST_FILE "file_lib_test.txt" #define TEST_LINK "file_lib_test.link" #define TEST_DIR "file_lib_test.dir" #define TEST_SUBDIR "file_lib_test.sub" #define TEST_SUBSUBDIR "file_lib_test.sub/sub" #define TEST_STRING "BLUE balloon" #define TEST_SUBSTRING "YELLOW balloon" #define TEST_SUBSUBSTRING "RED balloon" // These are just a way to pass parameters into switch_symlink_hook(). // Since it can be called from CFEngine code, we need to do it like this. // The way COUNTDOWN works is that it counts down towards zero for each // component in the path passed to safe_open(). When it reaches zero, // the symlink will be inserted at that moment. int TEST_SYMLINK_COUNTDOWN = 0; const char *TEST_SYMLINK_NAME = ""; const char *TEST_SYMLINK_TARGET = ""; // If this is true, when the countdown has been reached, we alternate // between deleting and creating the link. This is to test the race condition // when creating files. Defaults to false. bool TEST_SYMLINK_ALTERNATE = false; static int ORIG_DIR = -1; void switch_symlink_hook(void) { if (--TEST_SYMLINK_COUNTDOWN <= 0) { if (TEST_SYMLINK_COUNTDOWN == 0 || (TEST_SYMLINK_ALTERNATE && (TEST_SYMLINK_COUNTDOWN & 1))) { rmdir(TEST_SYMLINK_NAME); unlink(TEST_SYMLINK_NAME); } if (TEST_SYMLINK_COUNTDOWN == 0 || (TEST_SYMLINK_ALTERNATE && !(TEST_SYMLINK_COUNTDOWN & 1))) { assert_int_equal(symlink(TEST_SYMLINK_TARGET, TEST_SYMLINK_NAME), 0); // If we already are root, we must force the link to be non-root, // otherwise the test may have no purpose. if (getuid() == 0) { // 100 exists in most installations, but it doesn't really matter. assert_int_equal(lchown(TEST_SYMLINK_NAME, 100, 100), 0); } } } } static void complain_missing_sudo(const char *function) { printf("WARNING!!! %s will not run without root privileges.\n" "Tried using sudo with no luck.\n", function); } static void chdir_or_exit(const char *path) { if (chdir(path) < 0) { // Don't risk writing into folders we shouldn't. Just bail. exit(EXIT_FAILURE); } } static void save_test_dir(void) { ORIG_DIR = open(".", O_RDONLY); assert_true(ORIG_DIR >= 0); } static void close_test_dir(void) { close(ORIG_DIR); } static void clear_tempfiles(void) { unlink(TEMP_DIR "/" TEST_FILE); unlink(TEMP_DIR "/" TEST_LINK); unlink(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE); unlink(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE); rmdir(TEMP_DIR "/" TEST_SUBSUBDIR); rmdir(TEMP_DIR "/" TEST_SUBDIR); rmdir(TEMP_DIR); } static void setup_tempfiles(void) { clear_tempfiles(); mkdir(TEMP_DIR, 0755); chdir_or_exit(TEMP_DIR); mkdir(TEST_SUBDIR, 0755); mkdir(TEST_SUBSUBDIR, 0755); int fd = open(TEMP_DIR "/" TEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); int result = write(fd, TEST_STRING, strlen(TEST_STRING)); close(fd); fd = open(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); result = write(fd, TEST_SUBSTRING, strlen(TEST_SUBSTRING)); close(fd); fd = open(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644); result = write(fd, TEST_SUBSUBSTRING, strlen(TEST_SUBSUBSTRING)); close(fd); if (getuid() == 0) { // 100 exists in most installations, but it doesn't really matter. result = chown(TEMP_DIR "/" TEST_FILE, 100, 100); result = chown(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE, 100, 100); result = chown(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, 100, 100); result = chown(TEMP_DIR "/" TEST_SUBDIR, 100, 100); result = chown(TEMP_DIR "/" TEST_SUBSUBDIR, 100, 100); } (void)result; TEST_SYMLINK_ALTERNATE = false; } static void return_to_test_dir(void) { if (fchdir(ORIG_DIR) < 0) { // Don't risk writing into folders we shouldn't. Just bail. exit(EXIT_FAILURE); } } static void check_contents(int fd, const char *str) { char buf[strlen(str) + 1]; assert_int_equal(read(fd, buf, strlen(str)), strlen(str)); buf[strlen(str)] = '\0'; assert_string_equal(buf, str); } static void test_safe_open_currentdir(void) { setup_tempfiles(); int fd; assert_true((fd = safe_open(TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_STRING); close(fd); return_to_test_dir(); } static void test_safe_open_subdir(void) { setup_tempfiles(); int fd; assert_true((fd = safe_open(TEST_SUBDIR "/" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_subsubdir(void) { setup_tempfiles(); int fd; assert_true((fd = safe_open(TEST_SUBSUBDIR "/" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_updir(void) { setup_tempfiles(); chdir_or_exit(TEST_SUBDIR); int fd; assert_true((fd = safe_open("../" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_STRING); close(fd); return_to_test_dir(); } static void test_safe_open_upupdir(void) { setup_tempfiles(); chdir_or_exit(TEST_SUBSUBDIR); int fd; assert_true((fd = safe_open("../../" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_STRING); close(fd); return_to_test_dir(); } static void test_safe_open_generic_relative_dir(void) { setup_tempfiles(); int fd; assert_true((fd = safe_open(TEST_SUBSUBDIR "/../" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_generic_absolute_dir(void) { setup_tempfiles(); int fd; assert_true((fd = safe_open(TEMP_DIR "/" TEST_SUBDIR "/../" TEST_SUBSUBDIR "/../" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_extra_slashes_relative(void) { setup_tempfiles(); int fd; assert_true((fd = safe_open(TEST_SUBSUBDIR "//..////" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_extra_slashes_absolute(void) { setup_tempfiles(); chdir_or_exit(TEST_SUBSUBDIR); int fd; assert_true((fd = safe_open("/" TEMP_DIR "/" TEST_SUBDIR "//..//" TEST_SUBSUBDIR "/..//" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_unsafe_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = "/etc/passwd"; switch_symlink_hook(); assert_true(safe_open(TEMP_DIR "/" TEST_LINK, O_RDONLY) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_safe_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_FILE; switch_symlink_hook(); int fd; assert_true((fd = safe_open(TEMP_DIR "/" TEST_LINK, O_RDONLY)) >= 0); check_contents(fd, TEST_STRING); close(fd); return_to_test_dir(); } static void test_safe_open_unsafe_inserted_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = "/etc/passwd"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_LINK, O_RDONLY) < 0); assert_int_equal(errno, ENOENT); return_to_test_dir(); } static void test_safe_open_safe_inserted_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_LINK, O_RDONLY) < 0); assert_int_equal(errno, ENOENT); return_to_test_dir(); } static void test_safe_open_unsafe_switched_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = "/etc/passwd"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_FILE, O_RDONLY) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_safe_switched_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 3; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); int fd; assert_true((fd = safe_open(TEMP_DIR "/" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_unsafe_dir_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = "/etc"; switch_symlink_hook(); assert_true(safe_open(TEMP_DIR "/" TEST_LINK "/passwd", O_RDONLY) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_safe_dir_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEST_SUBDIR; switch_symlink_hook(); int fd; assert_true((fd = safe_open(TEST_LINK "/" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_unsafe_inserted_dir_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = "/etc"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_LINK "/passwd", O_RDONLY) < 0); assert_int_equal(errno, ENOENT); return_to_test_dir(); } static void test_safe_open_safe_inserted_dir_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEST_SUBDIR; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_LINK "/" TEST_FILE, O_RDONLY) < 0); assert_int_equal(errno, ENOENT); return_to_test_dir(); } static void test_safe_open_unsafe_switched_dir_symlink(void) { setup_tempfiles(); assert_int_equal(mkdir(TEMP_DIR "/" TEST_LINK, 0755), 0); if (getuid() == 0) { assert_int_equal(chown(TEMP_DIR "/" TEST_LINK, 100, 100), 0); } TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = "/etc"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_LINK "/passwd", O_RDONLY) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_safe_switched_dir_symlink(void) { setup_tempfiles(); assert_int_equal(mkdir(TEMP_DIR "/" TEST_LINK, 0755), 0); if (getuid() == 0) { assert_int_equal(chown(TEMP_DIR "/" TEST_LINK, 100, 100), 0); } TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEST_SUBDIR; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); int fd; assert_true((fd = safe_open(TEST_LINK "/" TEST_FILE, O_RDONLY)) >= 0); check_contents(fd, TEST_SUBSTRING); close(fd); return_to_test_dir(); } static void test_safe_open_create_safe_inserted_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); int fd; assert_true((fd = safe_open(TEST_LINK, O_RDONLY | O_CREAT, 0644)) >= 0); check_contents(fd, TEST_STRING); close(fd); return_to_test_dir(); } static void test_safe_open_create_alternating_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_ALTERNATE = true; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_LINK, O_RDONLY | O_CREAT, 0644) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_create_unsafe_switched_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = "/etc/passwd"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_FILE, O_RDONLY | O_CREAT, 0644) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_create_dangling_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = "/etc/file-that-for-sure-does-not-exist"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_FILE, O_RDONLY | O_CREAT, 0644) < 0); assert_int_equal(errno, EACCES); return_to_test_dir(); } static void test_safe_open_dangling_symlink(void) { setup_tempfiles(); TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = "/etc/file-that-for-sure-does-not-exist"; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_true(safe_open(TEST_FILE, O_RDONLY, 0644) < 0); assert_int_equal(errno, ENOENT); return_to_test_dir(); } static void test_safe_open_root(void) { int fd; struct stat statbuf; assert_true((fd = safe_open("/", O_RDONLY)) >= 0); assert_int_equal(fchdir(fd), 0); assert_int_equal(stat("etc", &statbuf), 0); close(fd); return_to_test_dir(); } static void test_safe_open_ending_slashes(void) { setup_tempfiles(); int fd; // Whether a regular file with ending slash fails to open is platform dependent, // so should be the same as open(). fd = open(TEMP_DIR "/" TEST_FILE "///", O_RDONLY); bool ending_file_slash_ok; if (fd >= 0) { close(fd); ending_file_slash_ok = true; } else { ending_file_slash_ok = false; } fd = safe_open(TEMP_DIR "/" TEST_FILE "///", O_RDONLY); assert_true(ending_file_slash_ok ? (fd >= 0) : (fd < 0)); if (fd >= 0) { close(fd); } else { assert_int_equal(errno, ENOTDIR); } assert_true((fd = safe_open(TEMP_DIR "/", O_RDONLY)) >= 0); close(fd); return_to_test_dir(); } static void test_safe_open_null(void) { setup_tempfiles(); int fd; assert_false((fd = safe_open(NULL, O_RDONLY)) >= 0); assert_int_equal(errno, EINVAL); return_to_test_dir(); } static void test_safe_open_empty(void) { setup_tempfiles(); int fd; assert_false((fd = safe_open("", O_RDONLY)) >= 0); assert_int_equal(errno, ENOENT); return_to_test_dir(); } static void test_safe_fopen(void) { setup_tempfiles(); FILE *fptr; char buf = 'a'; assert_true(fptr = safe_fopen(TEST_FILE, "r")); assert_int_equal(fread(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); assert_int_not_equal(fwrite(&buf, 1, 1, fptr), 1); assert_true(ferror(fptr)); clearerr(fptr); fclose(fptr); assert_true(fptr = safe_fopen(TEST_FILE, "a")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_true(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); assert_true(fptr = safe_fopen(TEST_FILE, "r+")); assert_int_equal(fread(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); assert_true(fptr = safe_fopen(TEST_FILE, "a+")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); assert_true(fptr = safe_fopen(TEST_FILE, "w")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_true(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); assert_true(fptr = safe_fopen(TEST_FILE, "w+")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); unlink(TEST_FILE); assert_false(fptr = safe_fopen(TEST_FILE, "r")); unlink(TEST_FILE); assert_true(fptr = safe_fopen(TEST_FILE, "a")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_true(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); unlink(TEST_FILE); assert_true(fptr = safe_fopen(TEST_FILE, "w")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_true(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); unlink(TEST_FILE); assert_false(fptr = safe_fopen(TEST_FILE, "r+")); unlink(TEST_FILE); assert_true(fptr = safe_fopen(TEST_FILE, "a+")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); unlink(TEST_FILE); assert_true(fptr = safe_fopen(TEST_FILE, "w+")); assert_int_not_equal(fread(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); assert_int_equal(fwrite(&buf, 1, 1, fptr), 1); assert_false(ferror(fptr)); clearerr(fptr); fclose(fptr); return_to_test_dir(); } static void test_safe_chown_plain_file(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(chown(TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_chown(TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_chown_relative_file(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(chown(TEST_SUBSUBDIR "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_chown(TEST_SUBSUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_chown_absolute_file(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(chown(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_chown(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_chown_file_extra_slashes(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(chown("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, 100, 100), 0); assert_int_equal(stat("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_chown("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, 0, 0), 0); assert_int_equal(stat("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_chown_plain_directory(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(chown(TEST_SUBDIR, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_chown(TEST_SUBDIR, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_chown_unsafe_link(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_int_equal(chown(TEST_SUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); assert_int_equal(safe_chown(TEST_FILE, 100, 100), -1); assert_int_equal(errno, EACCES); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_plain_file(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown(TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_relative_file(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown(TEST_SUBSUBDIR "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEST_SUBSUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_absolute_file(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEMP_DIR "/" TEST_SUBSUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_file_extra_slashes(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, 100, 100), 0); assert_int_equal(stat("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, 0, 0), 0); assert_int_equal(stat("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_plain_directory(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown(TEST_SUBDIR, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEST_SUBDIR, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_unsafe_link(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_int_equal(lchown(TEST_SUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); // Unsafe links should succeed, because we are operating on the *link*, not the target. assert_int_equal(safe_lchown(TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); } static void test_safe_lchown_unsafe_link_to_directory(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR; switch_symlink_hook(); assert_int_equal(lchown(TEST_SUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); assert_int_equal(lchown(TEST_SUBDIR, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); assert_int_equal(safe_lchown(TEST_LINK "/" TEST_FILE, 100, 100), -1); assert_int_equal(errno, EACCES); assert_int_equal(lchown(TEST_SUBDIR "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(lchown(TEST_SUBDIR, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEST_LINK "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); return_to_test_dir(); } static void test_safe_chmod_plain_file(void) { setup_tempfiles(); struct stat statbuf; assert_int_equal(chmod(TEST_FILE, 0777), 0); assert_int_equal(stat(TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0777); assert_int_equal(safe_chmod(TEST_FILE, 0644), 0); assert_int_equal(stat(TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0644); return_to_test_dir(); } static void test_safe_chmod_relative_file(void) { setup_tempfiles(); struct stat statbuf; assert_int_equal(chmod(TEST_SUBDIR "/" TEST_FILE, 0777), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0777); assert_int_equal(safe_chmod(TEST_SUBDIR "/" TEST_FILE, 0644), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0644); return_to_test_dir(); } static void test_safe_chmod_absolute_file(void) { setup_tempfiles(); struct stat statbuf; assert_int_equal(chmod(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE, 0777), 0); assert_int_equal(stat(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0777); assert_int_equal(safe_chmod(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE, 0644), 0); assert_int_equal(stat(TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0644); return_to_test_dir(); } static void test_safe_chmod_extra_slashes(void) { setup_tempfiles(); struct stat statbuf; assert_int_equal(chmod("/" TEMP_DIR "///" TEST_SUBDIR "//" TEST_FILE, 0777), 0); assert_int_equal(stat("/" TEMP_DIR "///" TEST_SUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0777); assert_int_equal(safe_chmod("/" TEMP_DIR "///" TEST_SUBDIR "//" TEST_FILE, 0644), 0); assert_int_equal(stat("/" TEMP_DIR "///" TEST_SUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0644); return_to_test_dir(); } static void test_safe_chmod_unsafe_link(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //switch_symlink_hook(); assert_int_equal(chown(TEST_SUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(chmod(TEST_SUBDIR "/" TEST_FILE, 0777), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0777); assert_int_equal(safe_chmod(TEST_FILE, 0644), -1); assert_int_equal(errno, EACCES); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_mode & 0777, 0777); return_to_test_dir(); } static void test_safe_creat_exists(void) { setup_tempfiles(); int fd; struct stat buf; assert_true((fd = safe_creat(TEST_FILE, 0644)) >= 0); assert_int_equal(fstat(fd, &buf), 0); assert_int_equal(buf.st_size, 0); close(fd); return_to_test_dir(); } static void test_safe_creat_doesnt_exist(void) { setup_tempfiles(); int fd; struct stat buf; unlink(TEST_FILE); assert_true((fd = safe_creat(TEST_FILE, 0644)) >= 0); assert_int_equal(fstat(fd, &buf), 0); assert_int_equal(buf.st_size, 0); close(fd); return_to_test_dir(); } static void try_gaining_root_privileges(ARG_UNUSED int argc, char **argv) { if (system("sudo -n /bin/true") == 0) { execlp("sudo", "sudo", "-n", argv[0], NULL); // Should never get here. } } int main(int argc, char **argv) { if (getuid() != 0) { try_gaining_root_privileges(argc, argv); } PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(save_test_dir), unit_test(test_safe_open_currentdir), unit_test(test_safe_open_subdir), unit_test(test_safe_open_subsubdir), unit_test(test_safe_open_updir), unit_test(test_safe_open_upupdir), unit_test(test_safe_open_generic_relative_dir), unit_test(test_safe_open_generic_absolute_dir), unit_test(test_safe_open_extra_slashes_relative), unit_test(test_safe_open_extra_slashes_absolute), unit_test(test_safe_open_unsafe_symlink), unit_test(test_safe_open_safe_symlink), unit_test(test_safe_open_unsafe_inserted_symlink), unit_test(test_safe_open_safe_inserted_symlink), unit_test(test_safe_open_unsafe_switched_symlink), unit_test(test_safe_open_safe_switched_symlink), unit_test(test_safe_open_unsafe_dir_symlink), unit_test(test_safe_open_safe_dir_symlink), unit_test(test_safe_open_unsafe_inserted_dir_symlink), unit_test(test_safe_open_safe_inserted_dir_symlink), unit_test(test_safe_open_unsafe_switched_dir_symlink), unit_test(test_safe_open_safe_switched_dir_symlink), unit_test(test_safe_open_create_safe_inserted_symlink), unit_test(test_safe_open_create_alternating_symlink), unit_test(test_safe_open_create_unsafe_switched_symlink), unit_test(test_safe_open_create_dangling_symlink), unit_test(test_safe_open_dangling_symlink), unit_test(test_safe_open_root), unit_test(test_safe_open_ending_slashes), unit_test(test_safe_open_null), unit_test(test_safe_open_empty), unit_test(test_safe_fopen), unit_test(test_safe_chown_plain_file), unit_test(test_safe_chown_relative_file), unit_test(test_safe_chown_absolute_file), unit_test(test_safe_chown_file_extra_slashes), unit_test(test_safe_chown_plain_directory), unit_test(test_safe_chown_unsafe_link), unit_test(test_safe_lchown_plain_file), unit_test(test_safe_lchown_relative_file), unit_test(test_safe_lchown_absolute_file), unit_test(test_safe_lchown_file_extra_slashes), unit_test(test_safe_lchown_plain_directory), unit_test(test_safe_lchown_unsafe_link), unit_test(test_safe_lchown_unsafe_link_to_directory), unit_test(test_safe_chmod_plain_file), unit_test(test_safe_chmod_relative_file), unit_test(test_safe_chmod_absolute_file), unit_test(test_safe_chmod_extra_slashes), unit_test(test_safe_chmod_unsafe_link), unit_test(test_safe_creat_exists), unit_test(test_safe_creat_doesnt_exist), unit_test(close_test_dir), unit_test(clear_tempfiles), }; int ret = run_tests(tests); return ret; } cfengine-3.6.2/tests/unit/findhub_test.c0000664000175100017510000002061112400110676017756 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ #include #include #include #include #include #include void (*avahi_simple_poll_quit_ptr)(AvahiSimplePoll *); char* (*avahi_address_snprint_ptr)(char *, size_t , const AvahiAddress *); int (*avahi_service_resolver_free_ptr)(AvahiServiceResolver *); int (*avahi_client_errno_ptr)(AvahiClient *); const char* (*avahi_strerror_ptr)(int); AvahiServiceResolver* (*avahi_service_resolver_new_ptr)(AvahiClient *, AvahiIfIndex, AvahiProtocol, const char *, const char *, const char *, AvahiProtocol, AvahiLookupFlags, AvahiServiceResolverCallback, void *); AvahiClient* (*avahi_service_browser_get_client_ptr)(AvahiServiceBrowser *); AvahiClient* (*avahi_service_resolver_get_client_ptr)(AvahiServiceResolver *); AvahiSimplePoll* (*avahi_simple_poll_new_ptr)(); const AvahiPoll* (*avahi_simple_poll_get_ptr)(AvahiSimplePoll *s); AvahiClient* (*avahi_client_new_ptr)(const AvahiPoll *, AvahiClientFlags, AvahiClientCallback, void *, int *); int (*avahi_simple_poll_loop_ptr)(AvahiSimplePoll *); int (*avahi_service_browser_free_ptr)(AvahiServiceBrowser *); void (*avahi_client_free_ptr)(AvahiClient *client); void (*avahi_simple_poll_free_ptr)(AvahiSimplePoll *); AvahiServiceBrowser* (*avahi_service_browser_new_ptr)(AvahiClient *, AvahiIfIndex, AvahiProtocol, const char *, const char *, AvahiLookupFlags, AvahiServiceBrowserCallback, void*); int hostcount; void *dlopen(const char *filename, int flag) { return (void*)1; } void *dlsym(void *handle, const char *symbol) { if (strcmp(symbol, "avahi_simple_poll_quit") == 0) { return &avahi_simple_poll_quit; } else if (strcmp(symbol, "avahi_address_snprint") == 0) { return &avahi_address_snprint; } else if (strcmp(symbol, "avahi_service_resolver_free") == 0) { return &avahi_service_resolver_free; } else if (strcmp(symbol, "avahi_client_errno") == 0) { return &avahi_client_errno; } else if (strcmp(symbol, "avahi_strerror") == 0) { return &avahi_strerror; } else if (strcmp(symbol, "avahi_service_resolver_new") == 0) { return &avahi_service_resolver_new; } else if (strcmp(symbol, "avahi_service_browser_get_client") == 0) { return &avahi_service_browser_get_client; } else if (strcmp(symbol, "avahi_service_resolver_get_client") == 0) { return &avahi_service_resolver_get_client; } else if (strcmp(symbol, "avahi_simple_poll_new") == 0) { return &avahi_simple_poll_new; } else if (strcmp(symbol, "avahi_simple_poll_get") == 0) { return &avahi_simple_poll_get; } else if (strcmp(symbol, "avahi_client_new") == 0) { return &avahi_client_new; } else if (strcmp(symbol, "avahi_simple_poll_loop") == 0) { return &avahi_simple_poll_loop; } else if (strcmp(symbol, "avahi_service_browser_free") == 0) { return &avahi_service_browser_free; } else if (strcmp(symbol, "avahi_client_free") == 0) { return &avahi_client_free; } else if (strcmp(symbol, "avahi_simple_poll_free") == 0) { return &avahi_simple_poll_free; } else if (strcmp(symbol, "avahi_service_browser_new") == 0) { return &avahi_service_browser_new; } return NULL; } int dlclose(void *handle) { return 0; } AvahiSimplePoll *avahi_simple_poll_new() { AvahiSimplePoll *sp = (AvahiSimplePoll*)1; return sp; } void avahi_simple_poll_free(AvahiSimplePoll *poll) { } const AvahiPoll *avahi_simple_poll_get(AvahiSimplePoll *s) { AvahiPoll *p = { 0 }; return p; } void avahi_simple_poll_quit(AvahiSimplePoll *poll) { } char *avahi_address_snprint(char *buffer, size_t size, const AvahiAddress *address) { xsnprintf(buffer, size, "10.0.0.100"); return NULL; } int avahi_service_resolver_free(AvahiServiceResolver *resolver) { return 0; } int avahi_client_errno(AvahiClient *c) { return 1; } const char *avahi_strerror(int error) { return "Avahi error occured"; } AvahiServiceResolver *avahi_service_resolver_new(AvahiClient *c, AvahiIfIndex index, AvahiProtocol protocol, const char * s1, const char *s2, const char *s3, AvahiProtocol protocol2, AvahiLookupFlags flags, AvahiServiceResolverCallback callback, void *data) { return (AvahiServiceResolver *)1; } AvahiClient *avahi_service_browser_get_client(AvahiServiceBrowser *sb) { return (AvahiClient *)1; } AvahiClient *avahi_service_resolver_get_client(AvahiServiceResolver *sr) { return (AvahiClient *)1; } AvahiClient *avahi_client_new(const AvahiPoll *poll, AvahiClientFlags cf, AvahiClientCallback callback, void *data, int *stat) { if (hostcount == 4) { return NULL; } return (AvahiClient *)1; } int avahi_simple_poll_loop(AvahiSimplePoll *sp) { AvahiAddress *addr = calloc(1, sizeof(AvahiAddress)); AvahiServiceResolver *sr = { (AvahiServiceResolver*)1 }; switch(hostcount) { case 1: resolve_callback(sr, 0, 0, AVAHI_RESOLVER_FOUND, "cfenginehub", "tcp", "local", "host1", addr, 5308, NULL, 0, NULL); return 0; case 2: resolve_callback(sr, 0, 0, AVAHI_RESOLVER_FOUND, "cfenginehub", "tcp", "local", "host1", addr, 5308, NULL, 0, NULL); resolve_callback(sr, 0, 0, AVAHI_RESOLVER_FOUND, "cfenginehub", "tcp", "local", "host2", addr, 1234, NULL, 0, NULL); resolve_callback(sr, 0, 0, AVAHI_RESOLVER_FOUND, "cfenginehub", "tcp", "local", "host3", addr, 4321, NULL, 0, NULL); return 0; default: free(addr); }; return 0; } int avahi_service_browser_free(AvahiServiceBrowser *sb) { return 0; } void avahi_client_free(AvahiClient *c) { } AvahiServiceBrowser *avahi_service_browser_new(AvahiClient *c, AvahiIfIndex index, AvahiProtocol protocol, const char *s1, const char *s2, AvahiLookupFlags flags, AvahiServiceBrowserCallback callback, void *data) { AvahiServiceBrowser *browser = (AvahiServiceBrowser *)1; return browser; } static void test_noHubsFound(void) { List *list = NULL; hostcount = 0; assert_int_equal(ListHubs(&list), 0); assert_int_not_equal(list, NULL); ListDestroy(&list); } static void test_oneHubFound(void) { List *list = NULL; hostcount = 1; assert_int_equal(ListHubs(&list), 1); assert_int_not_equal(list, NULL); ListIterator *i = NULL; i = ListIteratorGet(list); assert_true(i != NULL); HostProperties *host = (HostProperties *)ListIteratorData(i); assert_int_equal(host->Port,5308); assert_string_equal(host->Hostname, "host1"); assert_string_equal(host->IPAddress, "10.0.0.100"); ListIteratorDestroy(&i); ListDestroy(&list); } static void test_multipleHubsFound(void) { List *list = NULL; hostcount = 2; assert_int_equal(ListHubs(&list), 3); assert_int_not_equal(list, NULL); ListIterator *i = NULL; i = ListIteratorGet(list); HostProperties *host1 = (HostProperties *)ListIteratorData(i); assert_int_not_equal(ListIteratorNext(i), -1); HostProperties *host2 = (HostProperties *)ListIteratorData(i); assert_int_not_equal(ListIteratorNext(i), -1); HostProperties *host3 = (HostProperties *)ListIteratorData(i); assert_int_equal(host1->Port, 5308); assert_string_equal(host1->Hostname, "host1"); assert_string_equal(host1->IPAddress, "10.0.0.100"); assert_int_equal(host2->Port, 1234); assert_string_equal(host2->Hostname, "host2"); assert_string_equal(host2->IPAddress, "10.0.0.100"); assert_int_equal(host3->Port, 4321); assert_string_equal(host3->Hostname, "host3"); assert_string_equal(host3->IPAddress, "10.0.0.100"); ListIteratorDestroy(&i); ListDestroy(&list); } static void test_errorOccurred(void) { List *list = NULL; hostcount = 4; assert_int_equal(ListHubs(&list), -1); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_noHubsFound), unit_test(test_oneHubFound), unit_test(test_multipleHubsFound), unit_test(test_errorOccurred) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/set_test.c0000644000175100017510000000315712316547775017162 0ustar00a10038a1003800000000000000#include #include #include void test_stringset_from_string(void) { StringSet *s = StringSetFromString("one,two, three four,,", ','); assert_true(StringSetContains(s, "one")); assert_true(StringSetContains(s, "two")); assert_true(StringSetContains(s, " three four")); assert_true(StringSetContains(s, "")); assert_int_equal(4, StringSetSize(s)); StringSetDestroy(s); } void test_stringset_clear(void) { StringSet *s = StringSetNew(); StringSetAdd(s, xstrdup("a")); StringSetAdd(s, xstrdup("b")); assert_int_equal(2, StringSetSize(s)); StringSetClear(s); assert_int_equal(0, StringSetSize(s)); StringSetDestroy(s); } void test_stringset_serialization(void) { { StringSet *set = StringSetNew(); StringSetAdd(set, xstrdup("tag_1")); StringSetAdd(set, xstrdup("tag_2")); StringSetAdd(set, xstrdup("tag_3")); Buffer *buff = StringSetToBuffer(set, ','); assert_true(buff); assert_string_equal(BufferData(buff), "tag_1,tag_2,tag_3"); BufferDestroy(buff); StringSetDestroy(set); } { StringSet *set = StringSetNew(); Buffer *buff = StringSetToBuffer(set, ','); assert_true(buff); assert_string_equal(BufferData(buff), ""); BufferDestroy(buff); StringSetDestroy(set); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_stringset_from_string), unit_test(test_stringset_serialization), unit_test(test_stringset_clear) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/rlist_test.c0000664000175100017510000005172612400110676017507 0ustar00a10038a1003800000000000000#include #include #include #include #include #include /* Stubs */ void FatalError(ARG_UNUSED char *s, ...) { mock_assert(0, "0", __FILE__, __LINE__); abort(); } static void test_length(void) { Rlist *list = NULL; assert_int_equal(RlistLen(list), 0); RlistPrepend(&list, "stuff", RVAL_TYPE_SCALAR); assert_int_equal(RlistLen(list), 1); RlistPrepend(&list, "more-stuff", RVAL_TYPE_SCALAR); assert_int_equal(RlistLen(list), 2); RlistDestroy(list); } static void test_prepend_scalar_idempotent(void) { Rlist *list = NULL; RlistPrependScalarIdemp(&list, "stuff"); RlistPrependScalarIdemp(&list, "stuff"); assert_string_equal(RlistScalarValue(list), "stuff"); assert_int_equal(RlistLen(list), 1); RlistDestroy(list); } static void test_copy(void) { Rlist *list = NULL, *copy = NULL; RlistPrepend(&list, "stuff", RVAL_TYPE_SCALAR); RlistPrepend(&list, "more-stuff", RVAL_TYPE_SCALAR); copy = RlistCopy(list); assert_string_equal(RlistScalarValue(list), RlistScalarValue(copy)); assert_string_equal(RlistScalarValue(list->next), RlistScalarValue(copy->next)); RlistDestroy(list); RlistDestroy(copy); } static void test_rval_to_scalar(void) { Rval rval = { "abc", RVAL_TYPE_SCALAR }; assert_string_equal("abc", RvalScalarValue(rval)); } static void test_rval_to_scalar2(void) { Rval rval = { NULL, RVAL_TYPE_FNCALL }; expect_assert_failure(RvalScalarValue(rval)); } static void test_rval_to_list(void) { Rval rval = { NULL, RVAL_TYPE_SCALAR }; expect_assert_failure(RvalRlistValue(rval)); } static void test_rval_to_list2(void) { Rval rval = { NULL, RVAL_TYPE_LIST }; assert_false(RvalRlistValue(rval)); } static void test_rval_to_fncall(void) { Rval rval = { NULL, RVAL_TYPE_SCALAR }; expect_assert_failure(RvalFnCallValue(rval)); } static void test_rval_to_fncall2(void) { Rval rval = { NULL, RVAL_TYPE_FNCALL }; assert_false(RvalFnCallValue(rval)); } static void test_last(void) { Rlist *l = NULL; assert_true(RlistLast(l) == NULL); RlistAppendScalar(&l, "a"); assert_string_equal("a", RlistScalarValue(RlistLast(l))); RlistAppendScalar(&l, "b"); assert_string_equal("b", RlistScalarValue(RlistLast(l))); RlistDestroy(l); } static bool is_even(void *item, void *data) { long d = StringToLong(data); long i = StringToLong(item); return i % 2 == d; } static void test_filter(void) { Rlist *list = NULL; for (int i = 0; i < 10; i++) { char *item = StringFromLong(i); RlistAppend(&list, item, RVAL_TYPE_SCALAR); } assert_int_equal(10, RlistLen(list)); int mod_by = 0; RlistFilter(&list, is_even, &mod_by, free); assert_int_equal(5, RlistLen(list)); int i = 0; for (Rlist *rp = list; rp; rp = rp->next) { int k = StringToLong(rp->val.item); assert_int_equal(i, k); i += 2; } RlistDestroy(list); } static void test_filter_everything(void) { Rlist *list = NULL; for (int i = 1; i < 10; i += 2) { char *item = StringFromLong(i); RlistAppend(&list, item, RVAL_TYPE_SCALAR); } assert_int_equal(5, RlistLen(list)); int mod_by = 0; RlistFilter(&list, is_even, &mod_by, free); assert_int_equal(0, RlistLen(list)); assert_true(list == NULL); } static void test_reverse(void) { Rlist *list = RlistFromSplitString("a,b,c", ','); RlistReverse(&list); assert_int_equal(3, RlistLen(list)); assert_string_equal("c", RlistScalarValue(list)); assert_string_equal("b", RlistScalarValue(list->next)); assert_string_equal("a", RlistScalarValue(list->next->next)); RlistDestroy(list); } static void test_split_escaped(void) { Rlist *list = RlistFromSplitString("a\\,b\\c\\,d,w\\,x\\,y\\,z", ','); assert_int_equal(2, RlistLen(list)); assert_string_equal("a,b\\c,d", RlistScalarValue(list)); assert_string_equal("w,x,y,z", RlistScalarValue(list->next)); RlistDestroy(list); } static void test_split_long(void) { char buf[CF_MAXVARSIZE * 2], *tail = buf + CF_MAXVARSIZE; memset(buf, '$', sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; buf[CF_MAXVARSIZE - 1] = ','; Rlist *list = RlistFromSplitString(buf, ','); assert_int_equal(2, RlistLen(list)); assert_string_equal(tail, RlistScalarValue(list)); assert_string_equal(tail, RlistScalarValue(list->next)); RlistDestroy(list); } static void test_split_long_escaped(void) { char buf[CF_MAXVARSIZE * 2 + 2], *tail = buf + CF_MAXVARSIZE + 1; memset(buf, '$', sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; buf[CF_MAXVARSIZE] = ','; memcpy(buf + CF_MAXVARSIZE / 2, "\\,", 2); memcpy(tail + CF_MAXVARSIZE / 2, "\\,", 2); Rlist *list = RlistFromSplitString(buf, ','); assert_int_equal(2, RlistLen(list)); tail[CF_MAXVARSIZE / 2] = '$'; /* blot out the back-slash */ assert_string_equal(tail + 1, RlistScalarValue(list)); assert_string_equal(tail + 1, RlistScalarValue(list->next)); RlistDestroy(list); } /***************************************************************************/ static struct ParseRoulette { int nfields; char *str; } PR[] = { /*Simple */ { 1, "{\"a\"}"}, { 2, "{\"a\",\"b\"}"}, { 3, "{\"a\",\"b\",\"c\"}"}, /*Simple empty */ { 1, "{\"\"}"}, { 2, "{\"\",\"\"}"}, { 3, "{\"\",\"\",\"\"}"}, /*Simple mixed kind of quotations */ { 1, "{\"'\"}"}, { 1, "{'\"'}"}, { 1, "{\",\"}"}, { 1, "{','}"}, { 1, "{\"\\\\\"}"}, { 1, "{'\\\\'}"}, { 1, "{\"}\"}"}, { 1, "{'}'}"}, { 1, "{\"{\"}"}, { 1, "{'{'}"}, { 1, "{\"'\"}"}, { 1, "{'\"'}"}, { 1, "{'\\\",'}"}, /* [",] */ { 1, "{\"\\',\"}"}, /* [",] */ { 1, "{',\\\"'}"}, /* [,"] */ { 1, "{\",\\'\"}"}, /* [,"] */ { 1, "{\",,\"}"}, /* [\\] */ { 1, "{',,'}"}, /* [\\] */ { 1, "{\"\\\\\\\\\"}"}, /* [\\] */ { 1, "{'\\\\\\\\'}"}, /* [\\] */ { 1, "{'\\\\\\\"'}"}, /* [\"] */ { 1, "{\"\\\\\\'\"}"}, /* [\"] */ { 1, "{'\\\"\\\\'}"}, /* ["\] */ { 1, "{\"\\'\\\\\"}"}, /* ["\] */ /*Very long */ { 1, "{\"AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA\"}"}, { 1, "{'AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA'}"}, { 2, "{\"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA\" , \"Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb''bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbB\" }"}, { 2, "{'Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA' , 'Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbB' }"}, { 2, "{\"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA\" , 'Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbB' }"}, /*Inner space (inside elements) */ { 1, "{\" \"}"}, { 1, "{\" \"}"}, { 1, "{\" \"}"}, { 1, "{\"\t\"}"}, /*Outer space (outside elements) */ { 1, " {\"\"} "}, { 1, " {\"a\"} "}, { 2, " {\"a\",\"b\"} "}, { 1, "{ \"a\" }"}, { 2, "{ \"a\",\"b\" }"}, { 2, "{ \"a\" ,\"b\" }"}, { 2, "{ \"a\", \"b\" }"}, { 2, "{ \"a\", \"b\"} "}, /*Normal */ { 4, " { \" ab,c,d\\\\ \" , ' e,f\\\"g ' ,\"hi\\\\jk\", \"l''m \" } "}, { 21, " { 'A\\\"\\\\ ', \" \\\\\", \"}B\", \"\\\\\\\\\" , \" \\\\C\\'\" , \"\\',\" , ',\\\"D' , \" ,, \", \"E\\\\\\\\F\", \"\", \"{\", \" G '\" , \"\\\\\\'\", ' \\\" H \\\\ ', \", ,\" , \"I\", \" \", \"\\' J \", '\\\",', \",\\'\", \",\" } "}, { 3, "{ \" aaa \", \" bbbb \" , \" cc \" } "}, { 3, " { \" a'a \", \" b''b \" , \" c'c \" } "}, { 3, " { ' a\"a ', ' b\"\"b ' , ' c\"c ' } "}, { 3, " { ' a\"a ', \" b''b \" , ' c\"c ' } "}, { 3, " { ' a,\"a } { ', \" } b','b \" , ' {, c\"c } ' } "}, { -1, (char *)NULL} }; static char *PFR[] = { /* trim left failure */ "", " ", "a", "\"", "'", "\"\"", "''", "'\"", "\"'", /* trim right failure */ "{", "{ ", "{a", "{\"", "{'", "{\"\"", "{''", "{\"'", /* parse failure */ /* un-even number of quotation marks */ "{\"\"\"}", "{\"\",\"}", "{\"\"\"\"}", "{\"\"\"\"\"}", "{\"\",\"\"\"}", "{\"\"\"\",\"}", "{\"\",\"\",\"}", "{'''}", "{'','}", "{''''}", "{'''''}", "{'','''}", "{'''','}", "{\"}", "{'}", "{'','','}", "{\"\"'}", "{\"\",'}", "{\"'\"'}", "{\"\"'\"\"}", "{\"\",'\"\"}", "{'\"\"\",\"}", "{'',\"\",'}", /* Misplaced commas*/ "{\"a\",}", "{,\"a\"}", "{,,\"a\"}", "{\"a\",,\"b\"}", "{'a',}", "{,'a'}", "{,,'a'}", "{'a',,'b'}", "{\"a\",,'b'}", "{'a',,\"b\"}", " {,}", " {,,}", " {,,,}", " {,\"\"}", " {\"\",}", " {,\"\",}", " {\"\",,}", " {\"\",,,}", " {,,\"\",,}", " {\"\",\"\",}", " {\"\",\"\",,}", " { \"\" , \"\" , , }", " {,''}", " {'',}", " {,'',}", " {'',,}", " {'',,,}", " {,,'',,}", " {'','',}", " {'','',,}", " { '' , '' , , }", " {'',\"\",}", " {\"\",'',,}", " { '' , \"\" , , }", " { \"\" , '' , , }", /*Ignore space's oddities */ "\" {\"\"}", "{ {\"\"}", "{\"\"}\"", "{\"\"}\\", "{\"\"} } ", "a{\"\"}", " a {\"\"}", "{a\"\"}", "{ a \"\"}", "{\"\"}a", "{\"\"} a ", "{\"\"a}", "{\"\" a }", "a{\"\"}b", "{a\"\"b}", "a{\"\"b}", "{a\"\"}b", "{\"\"a\"\"}", "{\"\",\"\"a\"\"}", "' {''}", "{ {''}", "{''}'", "{''}\\", "{''} } ", "a{''}", " a {''}", "{a''}", "{ a ''}", "{''}a", "{''} a ", "{''a}", "{'' a }", "a{''}b", "{a''b}", "a{''b}", "{a''}b", "{''a''}", "{'',''a''}", "{''a\"\"}", "{\"\"a''}", "{\"\",''a''}", "{'',\"\"a''}", "{'',''a\"\"}", "{\"\",''a\"\"}", /* Bad type of quotation inside an element */ "{'aa'aa'}", "{\"aa\"aa\"}", "{'aa\"''}", "{'aa\"\"''}", "{\"aa'\"\"}", "{\"aa''\"\"}", "{'aa\"'', 'aa\"\"'',\"aa'\"\"}", "{\"aa\"aa\", 'aa\"'', 'aa\"\"''}", "{ \"aa\"aa\" ,'aa\"\"'',\"aa''\"\" }", NULL }; static void test_new_parser_success() { Rlist *list = NULL; int i = 0; while (PR[i].nfields != -1) { list = RlistParseString(PR[i].str); assert_int_equal(PR[i].nfields, RlistLen(list)); if (list != NULL) { RlistDestroy(list); } i++; } } static void test_new_parser_failure() { int i = 0; Rlist *list = NULL; while (PFR[i] != NULL) { list = RlistParseString(PFR[i]); assert_true(RlistLast(list) == NULL); if(list) RlistDestroy(list); i++; } } static void test_regex_split() { Rlist *list = RlistFromRegexSplitNoOverflow("one-->two-->three", "-+>", 3); assert_int_equal(3, RlistLen(list)); assert_string_equal(RlistScalarValue(list), "one"); assert_string_equal(RlistScalarValue(list->next), "two"); assert_string_equal(RlistScalarValue(list->next->next), "three"); RlistDestroy(list); } static void test_regex_split_too_few_chunks() { Rlist *list = RlistFromRegexSplitNoOverflow("one:two:three", ":", 2); assert_int_equal(2, RlistLen(list)); assert_string_equal(RlistScalarValue(list), "one"); assert_string_equal(RlistScalarValue(list->next), "two:three"); RlistDestroy(list); } static void test_regex_split_too_many_chunks() { Rlist *list = RlistFromRegexSplitNoOverflow("one:two:three:", ":", 10); assert_int_equal(4, RlistLen(list)); assert_string_equal(RlistScalarValue(list), "one"); assert_string_equal(RlistScalarValue(list->next), "two"); assert_string_equal(RlistScalarValue(list->next->next), "three"); assert_string_equal(RlistScalarValue(list->next->next->next), ""); RlistDestroy(list); } static void test_regex_split_empty_chunks() { Rlist *list = RlistFromRegexSplitNoOverflow(":one:two:three:", ":", 5); assert_int_equal(5, RlistLen(list)); assert_string_equal(RlistScalarValue(list), ""); assert_string_equal(RlistScalarValue(list->next), "one"); assert_string_equal(RlistScalarValue(list->next->next), "two"); assert_string_equal(RlistScalarValue(list->next->next->next), "three"); assert_string_equal(RlistScalarValue(list->next->next->next->next), ""); RlistDestroy(list); } static void test_regex_split_no_match() { Rlist *list = RlistFromRegexSplitNoOverflow(":one:two:three:", "/", 2); assert_int_equal(1, RlistLen(list)); assert_string_equal(RlistScalarValue(list), ":one:two:three:"); RlistDestroy(list); } static void test_regex_split_adjacent_separators() { Rlist *list = RlistFromRegexSplitNoOverflow(":one::two::three:", ":", 3); assert_int_equal(3, RlistLen(list)); assert_string_equal(RlistScalarValue(list), ""); assert_string_equal(RlistScalarValue(list->next), "one"); assert_string_equal(RlistScalarValue(list->next->next), ":two::three:"); RlistDestroy(list); list = RlistFromRegexSplitNoOverflow(":one::two:::three:", ":", 4); assert_int_equal(4, RlistLen(list)); assert_string_equal(RlistScalarValue(list), ""); assert_string_equal(RlistScalarValue(list->next), "one"); assert_string_equal(RlistScalarValue(list->next->next), ""); assert_string_equal(RlistScalarValue(list->next->next->next), "two:::three:"); RlistDestroy(list); list = RlistFromRegexSplitNoOverflow(":one::two:::three:", ":", 7); assert_int_equal(7, RlistLen(list)); assert_string_equal(RlistScalarValue(list), ""); assert_string_equal(RlistScalarValue(list->next), "one"); assert_string_equal(RlistScalarValue(list->next->next), ""); assert_string_equal(RlistScalarValue(list->next->next->next), "two"); assert_string_equal(RlistScalarValue(list->next->next->next->next), ""); assert_string_equal(RlistScalarValue(list->next->next->next->next->next), ""); assert_string_equal(RlistScalarValue(list->next->next->next->next->next->next), "three:"); RlistDestroy(list); } static void test_regex_split_real_regex() { //whole string is matched by regex in below example Rlist *list = RlistFromRegexSplitNoOverflow("one-two-three", ".+", 3); assert_int_equal(2, RlistLen(list)); assert_string_equal(RlistScalarValue(list), ""); assert_string_equal(RlistScalarValue(list->next), ""); RlistDestroy(list); list = RlistFromRegexSplitNoOverflow("one>>>two<<<>four", "[<>]+", 4); assert_int_equal(4, RlistLen(list)); assert_string_equal(RlistScalarValue(list), "one"); assert_string_equal(RlistScalarValue(list->next), "two"); assert_string_equal(RlistScalarValue(list->next->next), "three"); assert_string_equal(RlistScalarValue(list->next->next->next), "four"); RlistDestroy(list); } static void test_regex_split_overlapping_delimiters() { Rlist *list = RlistFromRegexSplitNoOverflow("-one---two---three", "--", 3); assert_int_equal(3, RlistLen(list)); assert_string_equal(RlistScalarValue(list), "-one"); assert_string_equal(RlistScalarValue(list->next), "-two"); assert_string_equal(RlistScalarValue(list->next->next), "-three"); RlistDestroy(list); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_prepend_scalar_idempotent), unit_test(test_length), unit_test(test_copy), unit_test(test_rval_to_scalar), unit_test(test_rval_to_scalar2), unit_test(test_rval_to_list), unit_test(test_rval_to_list2), unit_test(test_rval_to_fncall), unit_test(test_rval_to_fncall2), unit_test(test_last), unit_test(test_filter), unit_test(test_filter_everything), unit_test(test_reverse), unit_test(test_split_escaped), unit_test(test_split_long), unit_test(test_split_long_escaped), unit_test(test_new_parser_success), unit_test(test_new_parser_failure), unit_test(test_regex_split), unit_test(test_regex_split_too_few_chunks), unit_test(test_regex_split_too_many_chunks), unit_test(test_regex_split_empty_chunks), unit_test(test_regex_split_no_match), unit_test(test_regex_split_adjacent_separators), unit_test(test_regex_split_real_regex), unit_test(test_regex_split_overlapping_delimiters) }; return run_tests(tests); } /* ===== Stub out functionality we don't really use. ===== */ /* Silence all "unused parameter" warnings. */ #pragma GCC diagnostic ignored "-Wunused-parameter" char CONTEXTID[32]; void __ProgrammingError(const char *file, int lineno, const char *format, ...) { mock_assert(0, "0", __FILE__, __LINE__); } int FullTextMatch(const char *regptr, const char *cmpptr) { fail(); } const void *EvalContextVariableGet(const EvalContext *ctx, const VarRef *lval, DataType *type_out) { fail(); } pthread_mutex_t *cft_lock; int ThreadLock(pthread_mutex_t *name) { return true; } int ThreadUnlock(pthread_mutex_t *name) { return true; } int IsNakedVar(const char *str, char vtype) { fail(); } void FnCallPrint(Writer *writer, const FnCall *fp) { fail(); } void GetNaked(char *s1, const char *s2) { fail(); } /* void Log(LogLevel level, const char *fmt, ...) { fail(); } */ DataType ScopeGetVariable(const char *scope, const char *lval, Rval *returnv) { fail(); } void DeleteAssoc(CfAssoc *ap) { fail(); } CfAssoc *CopyAssoc(CfAssoc *old) { fail(); } FnCall *FnCallCopy(const FnCall *f) { fail(); } void FnCallDestroy(FnCall *fp) { fail(); } int SubStrnCopyChr(char *to, const char *from, int len, char sep) { fail(); } int BlockTextMatch(const char *regexp, const char *teststring, int *s, int *e) { fail(); } JsonElement *FnCallToJson(const FnCall *fp) { fail(); } JsonElement *JsonObjectCreate(size_t initialCapacity) { fail(); } void JsonObjectAppendArray(JsonElement *object, const char *key, JsonElement *array) { fail(); } void JsonObjectAppendString(JsonElement *obj, const char *key, const char *value) { fail(); } JsonElement *JsonArrayCreate(size_t initialCapacity) { fail(); } void JsonArrayAppendString(JsonElement *array, const char *value) { fail(); } void JsonArrayAppendArray(JsonElement *array, JsonElement *childArray) { fail(); } void JsonArrayAppendObject(JsonElement *array, JsonElement *object) { fail(); } JsonElement *JsonStringCreate(const char *value) { fail(); } cfengine-3.6.2/tests/unit/matching_test.c0000664000175100017510000000271012400110676020131 0ustar00a10038a1003800000000000000#include #include #include #include void test_has_regex_meta_chars(void) { assert_false(HasRegexMetaChars("string")); assert_false(HasRegexMetaChars("ala ma kota a kot ma ale")); assert_true(HasRegexMetaChars("^string")); assert_true(HasRegexMetaChars("^(string)")); assert_true(HasRegexMetaChars("string$")); assert_true(HasRegexMetaChars("(string)$")); assert_true(HasRegexMetaChars("string.*")); assert_true(HasRegexMetaChars("string*")); assert_true(HasRegexMetaChars("string.")); assert_true(HasRegexMetaChars("a?")); assert_true(HasRegexMetaChars("a*")); assert_true(HasRegexMetaChars("a+")); assert_true(HasRegexMetaChars("a{3}")); assert_true(HasRegexMetaChars("a{3,6}")); assert_true(HasRegexMetaChars("(a|b)")); assert_true(HasRegexMetaChars("a(bcd)*")); assert_true(HasRegexMetaChars("c.+t")); assert_true(HasRegexMetaChars("a(bcd)?e")); assert_true(HasRegexMetaChars("a(bcd){2,3}e")); assert_true(HasRegexMetaChars("(yes)|(no)")); assert_true(HasRegexMetaChars("pro(b|n|r|l)ate")); assert_true(HasRegexMetaChars("c[aeiou]t")); assert_true(HasRegexMetaChars("^[a-zA-Z0-9_]+$")); assert_true(HasRegexMetaChars("\\d{5}")); assert_true(HasRegexMetaChars("\\d")); } int main() { const UnitTest tests[] = { unit_test(test_has_regex_meta_chars), }; PRINT_TEST_BANNER(); return run_tests(tests); } cfengine-3.6.2/tests/unit/mustache_test.c0000664000175100017510000000605212400110676020153 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ size_t TestSpecFile(const char *testfile) { char path[PATH_MAX]; xsnprintf(path, sizeof(path), "%s/mustache_%s.json", TESTDATADIR, testfile); Writer *w = FileRead(path, SIZE_MAX, NULL); if (w == NULL) { Log(LOG_LEVEL_ERR, "Error reading JSON input file '%s'", path); fail(); } JsonElement *spec = NULL; const char *data = StringWriterData(w); if (JsonParse(&data, &spec) != JSON_PARSE_OK) { Log(LOG_LEVEL_ERR, "Error parsing JSON input file '%s'", path); fail(); } WriterClose(w); JsonElement *tests = JsonObjectGetAsArray(spec, "tests"); size_t num_failures = 0; for (size_t i = 0; i < JsonLength(tests); i++) { JsonElement *test_obj = JsonAt(tests, i); fprintf(stdout, "Testing %s:%s ...", testfile, JsonObjectGetAsString(test_obj, "name")); Buffer *out = BufferNew(); const char *templ = JsonObjectGetAsString(test_obj, "template"); const char *expected = JsonObjectGetAsString(test_obj, "expected"); const JsonElement *data = JsonObjectGet(test_obj, "data"); if (!MustacheRender(out, templ, data) || strcmp(expected, BufferData(out)) != 0) { num_failures++; fprintf(stdout, "FAIL \n%s\n != \n%s\n", expected, BufferData(out)); } else { fprintf(stdout, "OK\n"); } BufferDestroy(out); } JsonDestroy(spec); return num_failures; } static void test_spec(void) { size_t num_failures = 0; size_t comments_fail = TestSpecFile("comments"); size_t interpolation_fail = TestSpecFile("interpolation"); size_t sections_fail = TestSpecFile("sections"); size_t delimiters_fail = TestSpecFile("delimiters"); size_t inverted_fail = TestSpecFile("inverted"); size_t extra_fail = TestSpecFile("extra"); num_failures = comments_fail + interpolation_fail + sections_fail + delimiters_fail + inverted_fail + extra_fail; if (num_failures > 0) { fprintf(stdout, "Failures in comments: %llu\n", (unsigned long long)comments_fail); fprintf(stdout, "Failures in interpolation: %llu\n", (unsigned long long)interpolation_fail); fprintf(stdout, "Failures in sections: %llu\n", (unsigned long long)sections_fail); fprintf(stdout, "Failures in delimiters: %llu\n", (unsigned long long)delimiters_fail); fprintf(stdout, "Failures in inverted: %llu\n", (unsigned long long)inverted_fail); fprintf(stdout, "Failures in extra: %llu\n", (unsigned long long)inverted_fail); fprintf(stdout, "TOTAL FAILURES: %llu\n", (unsigned long long)num_failures); fail(); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_spec), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/strlist_test.c0000664000175100017510000002567112400110676020056 0ustar00a10038a1003800000000000000#include #include #include static StrList *PATH_SL, *HOSTNAME_SL; /* Strings that will be inserted to strlist, listed here in sorted order. */ char *PATH_STRINGS[] = { " ", " ", "/", "/path", "/path/to/file.name", "blah", "waza", }; #define PATH_STRINGS_LEN (sizeof(PATH_STRINGS) / sizeof(PATH_STRINGS[0])) /* Ideally we need the numbers [0..PATH_STRINGS_LEN) in random order in order to * insert non-sorted. To make the test reproducible, here is one random * order. Feel free to experiment with changing this. */ size_t PATH_INSERT_ORDER[PATH_STRINGS_LEN] = { 5, 3, 1, 0, 4, 6, 2 }; /* Strings that will be inserted to strlist, listed here in special sorted * order in the way they should end up after calling * StrList_Sort(string_CompareFromEnd). */ char *HOSTNAME_STRINGS[] = { "*", /* Globs have no special meaning */ ".*", /* Should not match anything */ ".", /* Should not match as well */ "com", /* No match, nobody has "com" fqdn */ "cfengine.com", /* Match this hostname */ ".allowed.cfengine.com", /* Allow everything under this domain */ "www.cfengine.com", /* Match this hostname */ ".no", /* Allow all norwegian hostnames */ }; #define HOSTNAME_STRINGS_LEN (sizeof(HOSTNAME_STRINGS) / sizeof(HOSTNAME_STRINGS[0])) /* Ideally we need the numbers [0..PATH_STRINGS_LEN) in random order in order to * insert non-sorted. To make the test reproducible, here is one random * order. Feel free to experiment with changing this. */ size_t HOSTNAME_INSERT_ORDER[HOSTNAME_STRINGS_LEN] = { 5, 3, 1, 0, 4, 6, 2, 7 }; static StrList *init_strlist(char ** strings, size_t strings_len, size_t *insert_order) { StrList *sl = calloc(1, sizeof(*sl)); /* Insert in random order. */ for (size_t i = 0; i < strings_len; i++) { size_t ret = StrList_Append(&sl, strings[ insert_order[i] ]); assert_int_equal(ret, i); assert_string_equal(StrList_At(sl, i), strings[ insert_order[i] ]); } assert_int_equal(StrList_Len(sl), strings_len); StrList_Finalise(&sl); return sl; } static void test_init_SL() { PATH_SL = init_strlist(PATH_STRINGS, PATH_STRINGS_LEN, PATH_INSERT_ORDER); HOSTNAME_SL = init_strlist(HOSTNAME_STRINGS, HOSTNAME_STRINGS_LEN, HOSTNAME_INSERT_ORDER); } /* Sort PATH_STRLIST using the common way, and HOSTNAME_STRLIST in the order * of reading the strings backwards. */ static void test_StrList_Sort() { StrList_Sort(PATH_SL, string_Compare); assert_int_equal(StrList_Len(PATH_SL), PATH_STRINGS_LEN); for (size_t i = 0; i < PATH_STRINGS_LEN; i++) { assert_string_equal(StrList_At(PATH_SL, i), PATH_STRINGS[i]); } StrList_Sort(HOSTNAME_SL, string_CompareFromEnd); assert_int_equal(StrList_Len(HOSTNAME_SL), HOSTNAME_STRINGS_LEN); for (size_t i = 0; i < HOSTNAME_STRINGS_LEN; i++) { assert_string_equal(StrList_At(HOSTNAME_SL, i), HOSTNAME_STRINGS[i]); } } /* Only search in PATH_STRLIST which is sorted in the common way. */ static void test_StrList_BinarySearch() { size_t pos; bool found; /* Search for existing strings. */ for (size_t i = 0; i < PATH_STRINGS_LEN; i++) { found = StrList_BinarySearch(PATH_SL, PATH_STRINGS[i], &pos); assert_int_equal(found, true); assert_int_equal(pos, i); } /* Search for inexistent entries, check that the returned position is the * one they should be inserted into. */ found = StrList_BinarySearch(PATH_SL, "", &pos); assert_int_equal(found, false); assert_int_equal(pos, 0); /* empty string should always come first */ found = StrList_BinarySearch(PATH_SL, " ", &pos); assert_int_equal(found, false); assert_int_equal(pos, 2); found = StrList_BinarySearch(PATH_SL, "zzz", &pos); assert_int_equal(found, false); assert_int_equal(pos, PATH_STRINGS_LEN); found = StrList_BinarySearch(PATH_SL, "/path/", &pos); assert_int_equal(found, false); assert_int_equal(pos, 4); found = StrList_BinarySearch(PATH_SL, "/path/to", &pos); assert_int_equal(found, false); assert_int_equal(pos, 4); } /* Only search in PATH_STRLIST because it makes sense to search longest prefix * for paths. */ static void test_StrList_SearchLongestPrefix() { /* REMINDER: PATH_STRINGS[] = { " ", " ", "/", "/path", "/path/to/file.name", "blah", "waza" }; */ size_t ret, ret2, ret3; /* These searches all search for "/path", since length is the same. */ ret = StrList_SearchLongestPrefix(PATH_SL, "/path", 0, '/', true); ret2 = StrList_SearchLongestPrefix(PATH_SL, "/path/", 5, '/', true); ret3 = StrList_SearchLongestPrefix(PATH_SL, "/path/to/file.name", 5, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/path"); assert_string_equal(StrList_At(PATH_SL, ret2), "/path"); assert_string_equal(StrList_At(PATH_SL, ret3), "/path"); /* Searching for "/path/" does not bring up "/path", but "/", since * directories *must* have a trailing slash. */ ret = StrList_SearchLongestPrefix(PATH_SL, "/path/", 0, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/"); ret = StrList_SearchLongestPrefix(PATH_SL, "/path.json", 0, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/"); /* We insert a couple more directories and sort again. */ StrList_Append(&PATH_SL, "/path/to/file.namewhatever/whatever"); StrList_Append(&PATH_SL, "/path/to/file.name/whatever/"); StrList_Append(&PATH_SL, "/path/to/"); StrList_Sort(PATH_SL, string_Compare); ret = StrList_SearchLongestPrefix(PATH_SL, "/path/to/file.name", 0, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/path/to/file.name"); ret = StrList_SearchLongestPrefix(PATH_SL, "/path/to/file", 0, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/path/to/"); ret = StrList_SearchLongestPrefix(PATH_SL, "/path/to/file.name/whatever/blah", 0, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/path/to/file.name/whatever/"); ret = StrList_SearchLongestPrefix(PATH_SL, "/path/to/", 0, '/', true); assert_string_equal(StrList_At(PATH_SL, ret), "/path/to/"); } /* Only search in HOSTNAME_STRLIST because it only makes sense to search for * longest suffix with hostnames and subdomains. */ static void test_StrList_SearchLongestSuffix() { /* REMINDER: HOSTNAME_STRINGS[] = { "*", ".*", ".", "com", "cfengine.com", ".allowed.cfengine.com", "www.cfengine.com", ".no" }; */ size_t ret, ret2, ret3, ret4, ret5, ret6, ret7, ret8, ret9, ret10, ret11; ret = StrList_SearchLongestPrefix(HOSTNAME_SL, "cfengine.com", 0, '.', false); ret2 = StrList_SearchLongestPrefix(HOSTNAME_SL, "google.com", 0, '.', false); ret3 = StrList_SearchLongestPrefix(HOSTNAME_SL, "yr.no", 0, '.', false); ret4 = StrList_SearchLongestPrefix(HOSTNAME_SL, "ntua.gr", 0, '.', false); ret5 = StrList_SearchLongestPrefix(HOSTNAME_SL, "disallowed.cfengine.com", 0, '.', false); ret6 = StrList_SearchLongestPrefix(HOSTNAME_SL, "allowed.cfengine.com", 0, '.', false); ret7 = StrList_SearchLongestPrefix(HOSTNAME_SL, "blah.allowed.cfengine.com", 0, '.', false); ret8 = StrList_SearchLongestPrefix(HOSTNAME_SL, "www.cfengine.com", 0, '.', false); ret9 = StrList_SearchLongestPrefix(HOSTNAME_SL, "www1.cfengine.com", 0, '.', false); ret10 = StrList_SearchLongestPrefix(HOSTNAME_SL, "1www.cfengine.com", 0, '.', false); ret11 = StrList_SearchLongestPrefix(HOSTNAME_SL, "no", 0, '.', false); assert_string_equal(StrList_At(HOSTNAME_SL, ret), "cfengine.com"); assert_int_equal(ret2, (size_t) -1); assert_string_equal(StrList_At(HOSTNAME_SL, ret3), ".no"); assert_int_equal(ret4, (size_t) -1); assert_int_equal(ret5, (size_t) -1); assert_int_equal(ret6, (size_t) -1); assert_string_equal(StrList_At(HOSTNAME_SL, ret7), ".allowed.cfengine.com"); assert_string_equal(StrList_At(HOSTNAME_SL, ret8), "www.cfengine.com"); assert_int_equal(ret9, (size_t) -1); assert_int_equal(ret10, (size_t) -1); assert_int_equal(ret11, (size_t) -1); } static void test_StrList_SearchForSuffix() { /* REMINDER: HOSTNAME_STRINGS[] = { "*", ".*", ".", "com", "cfengine.com", ".allowed.cfengine.com", "www.cfengine.com", ".no" }; */ size_t ret, ret2, ret3, ret4, ret5, ret6, ret7, ret8, ret9, ret10, ret11; ret = StrList_SearchForPrefix(HOSTNAME_SL, "cfengine.com", 0, false); ret2 = StrList_SearchForPrefix(HOSTNAME_SL, "google.com", 0, false); ret3 = StrList_SearchForPrefix(HOSTNAME_SL, "yr.no", 0, false); ret4 = StrList_SearchForPrefix(HOSTNAME_SL, "ntua.gr", 0, false); ret5 = StrList_SearchForPrefix(HOSTNAME_SL, "disallowed.cfengine.com", 0, false); ret6 = StrList_SearchForPrefix(HOSTNAME_SL, "allowed.cfengine.com", 0, false); ret7 = StrList_SearchForPrefix(HOSTNAME_SL, "blah.allowed.cfengine.com", 0, false); ret8 = StrList_SearchForPrefix(HOSTNAME_SL, "www.cfengine.com", 0, false); ret9 = StrList_SearchForPrefix(HOSTNAME_SL, "www1.cfengine.com", 0, false); ret10 = StrList_SearchForPrefix(HOSTNAME_SL, "1www.cfengine.com", 0, false); ret11 = StrList_SearchForPrefix(HOSTNAME_SL, "no", 0, false); /* SearchForPrefix() does not guarantee which one of all the matches it * will return if there are many matches. */ /* E.g. the first search might return "cfengine.com" or "com" entry. */ LargestIntegralType set[] = {3, 4}; assert_in_set(ret, set, 2); assert_string_equal(StrList_At(HOSTNAME_SL, ret2), "com"); assert_string_equal(StrList_At(HOSTNAME_SL, ret3), ".no"); assert_int_equal(ret4, (size_t) -1); assert_in_set(ret5, set, 2); assert_in_set(ret6, set, 2); LargestIntegralType set2[] = {3, 4, 5}; assert_in_set(ret7, set2, 3); assert_in_set(ret8, set, 2); assert_in_set(ret9, set, 2); LargestIntegralType set3[] = {3, 4, 6}; assert_in_set(ret10, set3, 3); assert_int_equal(ret11, (size_t) -1); } static void test_StrList_Free() { StrList_Free(&PATH_SL); assert_int_equal(PATH_SL, NULL); StrList_Free(&HOSTNAME_SL); assert_int_equal(HOSTNAME_SL, NULL); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_init_SL), unit_test(test_StrList_Sort), unit_test(test_StrList_BinarySearch), unit_test(test_StrList_SearchLongestPrefix), unit_test(test_StrList_SearchLongestSuffix), unit_test(test_StrList_SearchForSuffix), unit_test(test_StrList_Free) }; int ret = run_tests(tests); return ret; } cfengine-3.6.2/tests/unit/assoc_test.c0000644000175100017510000000053712316547775017476 0ustar00a10038a1003800000000000000#include #include static void test_create_destroy(void) { CfAssoc *ap = NewAssoc("hello", (Rval) { "world", RVAL_TYPE_SCALAR }, CF_DATA_TYPE_STRING); DeleteAssoc(ap); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_create_destroy), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/misc_lib_test.c0000664000175100017510000000175612400110676020131 0ustar00a10038a1003800000000000000#include #include static void test_unsigned_modulus(void) { assert_int_equal(UnsignedModulus(0, 3), 0); assert_int_equal(UnsignedModulus(1, 3), 1); assert_int_equal(UnsignedModulus(2, 3), 2); assert_int_equal(UnsignedModulus(3, 3), 0); assert_int_equal(UnsignedModulus(4, 3), 1); assert_int_equal(UnsignedModulus(-1, 3), 2); assert_int_equal(UnsignedModulus(-2, 3), 1); assert_int_equal(UnsignedModulus(-3, 3), 0); assert_int_equal(UnsignedModulus(-4, 3), 2); } static void test_upper_power_of_two(void) { assert_int_equal(0, UpperPowerOfTwo(0)); assert_int_equal(1, UpperPowerOfTwo(1)); assert_int_equal(2, UpperPowerOfTwo(2)); assert_int_equal(4, UpperPowerOfTwo(3)); assert_int_equal(16, UpperPowerOfTwo(13)); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_unsigned_modulus), unit_test(test_upper_power_of_two), }; return run_tests(tests); } // STUBS cfengine-3.6.2/tests/unit/logging_test.c0000664000175100017510000000356712400110676020000 0ustar00a10038a1003800000000000000#include #include #include #include char VFQNAME[CF_MAXVARSIZE]; char VPREFIX[CF_MAXVARSIZE]; static struct sockaddr *got_address; #if SENDTO_RETURNS_SSIZE_T > 0 ssize_t sendto(ARG_UNUSED int sockfd, ARG_UNUSED const void *buf, size_t len, ARG_UNUSED int flags, const struct sockaddr *dest_addr, ARG_UNUSED socklen_t addrlen) { got_address = xmemdup(dest_addr, sizeof(struct sockaddr_in)); return len; } #else /* * We might be naives by thinking that size_t, socklen_t and such are the same size as int. * Given that we are not using them here, we can live with that assumption. */ ssize_t sendto(ARG_UNUSED int sockfd, ARG_UNUSED const void *buf, int len, ARG_UNUSED int flags, const void *dest_addr, ARG_UNUSED int addrlen) { got_address = xmemdup(dest_addr, sizeof(struct sockaddr_in)); return len; } #endif // SENDTO_RETURNS_SSIZE_T > 0 static void test_set_port(void) { SetSyslogPort(5678); RemoteSysLog(LOG_EMERG, "Test string"); if (got_address->sa_family == AF_INET) { assert_int_equal(ntohs(((struct sockaddr_in *) got_address)->sin_port), 5678); } else if (got_address->sa_family == AF_INET6) { assert_int_equal(ntohs(((struct sockaddr_in6 *) got_address)->sin6_port), 5678); } free(got_address); } static void test_set_host(void) { SetSyslogHost("127.0.0.55"); RemoteSysLog(LOG_EMERG, "Test string"); assert_int_equal(got_address->sa_family, AF_INET); assert_int_equal(ntohl(((struct sockaddr_in *) got_address)->sin_addr.s_addr), 0x7f000037); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_set_port), unit_test(test_set_host), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/xml_writer_test.c0000664000175100017510000000372412400110676020541 0ustar00a10038a1003800000000000000#include #include #include /* * FIXME: Those unit tests need to be ajusted (or completely changed) if * XmlWriter internals are changed, as the tests expect particular layout and * escaping of generated XML. */ void test_comment(void) { Writer *w = StringWriter(); XmlComment(w, "foobar"); assert_string_equal(StringWriterClose(w), "\n"); } void test_no_attr(void) { Writer *w = StringWriter(); XmlTag(w, "foobar", NULL, 0); assert_string_equal(StringWriterClose(w), "\n"); } void test_tag(void) { Writer *w = StringWriter(); XmlTag(w, "foobar", "some value", 1, (XmlAttribute) { "a", "b"}); assert_string_equal(StringWriterClose(w), "some value\n"); } void test_complex_tag(void) { Writer *w = StringWriter(); XmlStartTag(w, "complex-tag", 2, (XmlAttribute) { "attr1", "value1"}, (XmlAttribute) { "attr2", "value2"}); XmlContent(w, "Some content"); XmlEndTag(w, "complex-tag"); assert_string_equal(StringWriterClose(w), "\nSome content\n"); } void test_escape(void) { Writer *w = StringWriter(); XmlContent(w, "&>\"'<"); assert_string_equal(StringWriterClose(w), "&>"'<"); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_comment), unit_test(test_no_attr), unit_test(test_tag), unit_test(test_complex_tag), unit_test(test_escape), }; return run_tests(tests); } /* STUB OUT */ void __ProgrammingError(ARG_UNUSED const char *file, ARG_UNUSED int lineno, ARG_UNUSED const char *format, ...) { fail(); exit(42); } void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } cfengine-3.6.2/tests/unit/arg_split_test.c0000664000175100017510000001102212243421446020324 0ustar00a10038a1003800000000000000#include #include #include #include #include static void test_split_empty(void) { char **s = ArgSplitCommand(""); assert_true(s); assert_false(*s); ArgFree(s); } static void test_split_easy(void) { char **s = ArgSplitCommand("zero one two"); assert_string_equal(s[0], "zero"); assert_string_equal(s[1], "one"); assert_string_equal(s[2], "two"); assert_false(s[3]); ArgFree(s); } static void test_split_quoted_beginning(void) { char **s = ArgSplitCommand("\"quoted string\" atbeginning"); assert_string_equal(s[0], "quoted string"); assert_string_equal(s[1], "atbeginning"); assert_false(s[2]); ArgFree(s); } static void test_split_quoted_end(void) { char **s = ArgSplitCommand("atend 'quoted string'"); assert_string_equal(s[0], "atend"); assert_string_equal(s[1], "quoted string"); assert_false(s[2]); ArgFree(s); } static void test_split_quoted_middle(void) { char **s = ArgSplitCommand("at `quoted string` middle"); assert_string_equal(s[0], "at"); assert_string_equal(s[1], "quoted string"); assert_string_equal(s[2], "middle"); assert_false(s[3]); ArgFree(s); } static void test_complex_quoting(void) { char **s = ArgSplitCommand("\"foo`'bar\""); assert_string_equal(s[0], "foo`'bar"); assert_false(s[1]); ArgFree(s); } static void test_arguments_resize_for_null(void) { /* This test checks that extending returned argument list for NULL terminator * works correctly */ char **s = ArgSplitCommand("0 1 2 3 4 5 6 7"); assert_string_equal(s[7], "7"); assert_false(s[8]); ArgFree(s); } static void test_arguments_resize(void) { char **s = ArgSplitCommand("0 1 2 3 4 5 6 7 8"); assert_string_equal(s[7], "7"); assert_string_equal(s[8], "8"); assert_false(s[9]); ArgFree(s); } static void test_command_promiser(void) { char *t1 = "/bin/echo"; assert_string_equal(CommandArg0(t1), "/bin/echo"); char *t2 = "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; assert_string_equal(CommandArg0(t2), "/bin/rpm"); char *t3 = "/bin/mount -va"; assert_string_equal(CommandArg0(t3), "/bin/mount"); char *t4 = "\"/bin/echo\""; assert_string_equal(CommandArg0(t4), "/bin/echo"); char *t5 = "\"/bin/echo\" 123"; assert_string_equal(CommandArg0(t5), "/bin/echo"); char *t6 = "\"/bin/echo with space\" 123"; assert_string_equal(CommandArg0(t6), "/bin/echo with space"); char *t7 = "c:\\Windows\\System32\\cmd.exe"; assert_string_equal(CommandArg0(t7), "c:\\Windows\\System32\\cmd.exe"); char *t8 = "\"c:\\Windows\\System32\\cmd.exe\""; assert_string_equal(CommandArg0(t8), "c:\\Windows\\System32\\cmd.exe"); char *t9 = "\"c:\\Windows\\System32\\cmd.exe\" /some args here"; assert_string_equal(CommandArg0(t9), "c:\\Windows\\System32\\cmd.exe"); char *t10 = "\"c:\\Windows\\System32 with space\\cmd.exe\""; assert_string_equal(CommandArg0(t10), "c:\\Windows\\System32 with space\\cmd.exe"); char *t11 = "\"c:\\Windows\\System32 with space\\cmd.exe\" /some args here"; assert_string_equal(CommandArg0(t11), "c:\\Windows\\System32 with space\\cmd.exe"); char *t12 = "\"c:\\Windows\\System32 with space\\cmd.exe\" /some \"args here\""; assert_string_equal(CommandArg0(t12), "c:\\Windows\\System32 with space\\cmd.exe"); char *t13 = "\\\\mycommand"; assert_string_equal(CommandArg0(t13), "\\\\mycommand"); char *t14 = "\\\\myhost\\share\\command.exe"; assert_string_equal(CommandArg0(t14), "\\\\myhost\\share\\command.exe"); char *t15 = "\"\\\\myhost\\share\\command.exe\""; assert_string_equal(CommandArg0(t15), "\\\\myhost\\share\\command.exe"); /* bad input */ char *b1 = "\"/bin/echo 123"; assert_string_equal(CommandArg0(b1), "/bin/echo 123"); char *b2 = "/bin/echo\" 123"; assert_string_equal(CommandArg0(b2), "/bin/echo\""); char *b3 = ""; assert_string_equal(CommandArg0(b3), ""); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_split_empty), unit_test(test_split_easy), unit_test(test_split_quoted_beginning), unit_test(test_split_quoted_middle), unit_test(test_split_quoted_end), unit_test(test_complex_quoting), unit_test(test_arguments_resize_for_null), unit_test(test_arguments_resize), unit_test(test_command_promiser), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/lastseen_migration_test.c0000664000175100017510000001413312400110676022230 0ustar00a10038a1003800000000000000#include #include #include #include #include /* xsnprintf */ typedef struct { char address[128]; double q; double expect; double var; } KeyHostSeen0; char CFWORKDIR[CF_BUFSIZE]; void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/lastseen_migration_test.XXXXXX"); mkdtemp(CFWORKDIR); } /* * Provides empty lastseen DB */ static DBHandle *setup(bool clean) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'/*", CFWORKDIR); system(cmd); DBHandle *db; OpenDB(&db, dbid_lastseen); if (clean) { /* There is no way to disable hook in OpenDB yet, so just undo * everything */ DBCursor *cursor; if (!NewDBCursor(db, &cursor)) { return NULL; } char *key; void *value; int ksize, vsize; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { DBCursorDeleteEntry(cursor); } if (!DeleteDBCursor(cursor)) { return NULL; } } return db; } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } static void test_no_migration(void) { DBHandle *db = setup(true); CloseDB(db); /* Migration on empty DB should produce single "version" key */ assert_int_equal(OpenDB(&db, dbid_lastseen), true); DBCursor *cursor; assert_int_equal(NewDBCursor(db, &cursor), true); char *key; void *value; int ksize, vsize; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { assert_int_equal(ksize, strlen("version") + 1); assert_string_equal(key, "version"); assert_int_equal(vsize, 2); assert_string_equal(value, "1"); } assert_int_equal(DeleteDBCursor(cursor), true); CloseDB(db); } static void test_up_to_date(void) { /* Test that upgrade is not performed if there is already a version * marker */ DBHandle *db = setup(false); const char *value = "+"; assert_int_equal(WriteDB(db, "+++", value, 2), true); CloseDB(db); /* Test that manually inserted key which matches the format of old-style * keys is still present next time database is open, which is an indicator * of database not being upgraded */ assert_int_equal(OpenDB(&db, dbid_lastseen), true); char read_value[CF_BUFSIZE]; assert_int_equal(ReadDB(db, "+++", &read_value, sizeof(read_value)), true); assert_string_equal(read_value, "+"); CloseDB(db); } #define KEYHASH \ "SHA=f7b335bef201230c7bf573b8dedf299fa745efe71e34a9002369248ff8519089" #define KEYHASH_KEY "k" KEYHASH #define KEYHASH_IN "-" KEYHASH #define QUALITY_IN "qi" KEYHASH #define KEYHASH_OUT "+" KEYHASH #define QUALITY_OUT "qo" KEYHASH void test_migrate_single(const char *expected_old_key, const char *expected_quality_key) { /* Test migration of single entry */ DBHandle *db = setup(true); KeyHostSeen0 khs0 = { .q = 666777.0, .expect = 12345.0, .var = 6543210.0, }; strcpy(khs0.address, "1.2.3.4"); assert_int_equal(WriteDB(db, expected_old_key, &khs0, sizeof(khs0)), true); CloseDB(db); assert_int_equal(OpenDB(&db, dbid_lastseen), true); /* Old entry migrated */ assert_int_equal(HasKeyDB(db, expected_old_key, strlen(expected_old_key) + 1), false); /* Version marker */ assert_int_equal(HasKeyDB(db, "version", strlen("version") + 1), true); /* Incoming connection quality */ KeyHostSeen khs; assert_int_equal(ReadDB(db, expected_quality_key, &khs, sizeof(khs)), true); assert_int_equal(khs.lastseen, 666777); assert_double_close(khs.Q.q, 12345.0); assert_double_close(khs.Q.expect, 12345.0); assert_double_close(khs.Q.var, 6543210.0); /* Address mapping */ char address[CF_BUFSIZE]; assert_int_equal(ReadDB(db, KEYHASH_KEY, address, sizeof(address)), true); assert_string_equal(address, "1.2.3.4"); /* Reverse mapping */ char keyhash[CF_BUFSIZE]; assert_int_equal(ReadDB(db, "a1.2.3.4", keyhash, sizeof(keyhash)), true); assert_string_equal(keyhash, KEYHASH); CloseDB(db); } void test_migrate_incoming(void) { test_migrate_single(KEYHASH_IN, QUALITY_IN); } void test_migrate_outgoing(void) { test_migrate_single(KEYHASH_OUT, QUALITY_OUT); } void test_ignore_wrong_sized(void) { /* Test that malformed values are discarded */ DBHandle *db = setup(true); const char *value = "+"; assert_int_equal(WriteDB(db, "+++", value, 2), true); CloseDB(db); assert_int_equal(OpenDB(&db, dbid_lastseen), true); assert_int_equal(HasKeyDB(db, "+++", 4), false); assert_int_equal(HasKeyDB(db, "k++", 4), false); assert_int_equal(HasKeyDB(db, "qi++", 5), false); assert_int_equal(HasKeyDB(db, "qo++", 5), false); assert_int_equal(HasKeyDB(db, "a+", 3), false); CloseDB(db); } int main() { #ifdef LMDB return 0; #else tests_setup(); const UnitTest tests[] = { unit_test(test_no_migration), unit_test(test_up_to_date), unit_test(test_migrate_incoming), unit_test(test_migrate_outgoing), unit_test(test_ignore_wrong_sized), }; PRINT_TEST_BANNER(); int ret = run_tests(tests); tests_teardown(); return ret; #endif } /* STUBS */ void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } HashMethod CF_DEFAULT_DIGEST; pthread_mutex_t *cft_output; char VIPADDRESS[CF_MAX_IP_LEN]; RSA *PUBKEY; bool MINUSF; char *MapAddress(ARG_UNUSED char *addr) { fail(); } char *HashPrintSafe(ARG_UNUSED char *dst, ARG_UNUSED size_t dst_size, ARG_UNUSED const unsigned char *digest, ARG_UNUSED HashMethod type, ARG_UNUSED bool use_prefix) { fail(); } void HashPubKey(ARG_UNUSED RSA *key, ARG_UNUSED unsigned char digest[EVP_MAX_MD_SIZE + 1], ARG_UNUSED HashMethod type) { fail(); } cfengine-3.6.2/tests/unit/mon_cpu_test.c0000664000175100017510000000342012243421446020003 0ustar00a10038a1003800000000000000#include "test.h" #include "generic_agent.h" #include "mon.h" static double GetCpuStat() { double q, dq = -1.0; long total_time = 1; FILE *fp; long userticks = 0, niceticks = 0, systemticks = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; char cpuname[CF_MAXVARSIZE], buf[CF_BUFSIZE]; if ((fp = fopen("/proc/stat", "r")) == NULL) { return -1.0; } while (!feof(fp)) { if (fgets(buf, sizeof(buf), fp) == NULL) { break; } if (sscanf(buf, "%s%ld%ld%ld%ld%ld%ld%ld", cpuname, &userticks, &niceticks, &systemticks, &idle, &iowait, &irq, &softirq) != 8) { continue; } total_time = (userticks + niceticks + systemticks + idle); q = 100.0 * (double) (total_time - idle); if (strcmp(cpuname, "cpu") == 0) { dq = q / (double) total_time; if ((dq > 100) || (dq < 0)) { dq = 50; } } } fclose(fp); return dq; } void test_cpu_monitor(void) { double cf_this[100]; double dq1 = GetCpuStat(); if (dq1 == -1.0) { assert_true(1); return; } MonCPUGatherData(cf_this); double dq2 = GetCpuStat(); if (dq2 == -1.0) { assert_true(1); return; } double min = (double) (dq2=lower && cf_this[ob_cpuall]<=upper); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_cpu_monitor), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/regex_test.c0000644000175100017510000000261512316547775017477 0ustar00a10038a1003800000000000000#include #include #include #include #include static void test_full_text_match(void) { EvalContext *ctx = EvalContextNew(); assert_int_equal(FullTextMatch(ctx, "[a-z]*", "1234abcd6789"), 0); EvalContextDestroy(ctx); } static void test_full_text_match2(void) { EvalContext *ctx = EvalContextNew(); assert_int_not_equal(FullTextMatch(ctx, "[1-4]*[a-z]*.*", "1234abcd6789"), 0); EvalContextDestroy(ctx); } static void test_block_text_match(void) { EvalContext *ctx = EvalContextNew(); int start, end; assert_int_not_equal(BlockTextMatch(ctx, "#[^\n]*", "line 1:\nline2: # comment to end\nline 3: blablab", &start, &end), 0); assert_int_equal(start, 15); assert_int_equal(end, 31); EvalContextDestroy(ctx); } static void test_block_text_match2(void) { EvalContext *ctx = EvalContextNew(); int start, end; assert_int_not_equal(BlockTextMatch(ctx, "[a-z]+", "1234abcd6789", &start, &end), 0); assert_int_equal(start, 4); assert_int_equal(end, 8); EvalContextDestroy(ctx); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_full_text_match), unit_test(test_full_text_match2), unit_test(test_block_text_match), unit_test(test_block_text_match2), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/exec-config-test.c0000664000175100017510000001416012400110676020446 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include /* xsnprintf */ static Policy *TestParsePolicy(const char *filename) { char path[PATH_MAX]; xsnprintf(path, sizeof(path), "%s/%s", TESTDATADIR, filename); return ParserParseFile(AGENT_TYPE_COMMON, path, PARSER_WARNING_ALL, PARSER_WARNING_ALL); } typedef void (*TestFn)(const EvalContext *ctx, const Policy *policy); static void run_test_in_policy(const char *policy_filename, TestFn fn) { GenericAgentConfig *agent_config = GenericAgentConfigNewDefault( AGENT_TYPE_EXECUTOR); EvalContext *ctx = EvalContextNew(); Policy *policy = TestParsePolicy(policy_filename); PolicyResolve(ctx, policy, agent_config); /* Setup global environment */ strcpy(VFQNAME, "localhost.localdomain"); strcpy(VIPADDRESS, "127.0.0.100"); EvalContextAddIpAddress(ctx, "127.0.0.100"); EvalContextAddIpAddress(ctx, "127.0.0.101"); fn(ctx, policy); PolicyDestroy(policy); GenericAgentFinalize(ctx, agent_config); } static void execd_config_empty_cb(const EvalContext *ctx, const Policy *policy) { ExecdConfig *config = ExecdConfigNew(ctx, policy); assert_int_equal(12, StringSetSize(config->schedule)); assert_int_equal(true, StringSetContains(config->schedule, "Min00")); assert_int_equal(true, StringSetContains(config->schedule, "Min05")); assert_int_equal(true, StringSetContains(config->schedule, "Min10")); assert_int_equal(true, StringSetContains(config->schedule, "Min15")); assert_int_equal(true, StringSetContains(config->schedule, "Min20")); assert_int_equal(true, StringSetContains(config->schedule, "Min25")); assert_int_equal(true, StringSetContains(config->schedule, "Min30")); assert_int_equal(true, StringSetContains(config->schedule, "Min35")); assert_int_equal(true, StringSetContains(config->schedule, "Min40")); assert_int_equal(true, StringSetContains(config->schedule, "Min45")); assert_int_equal(true, StringSetContains(config->schedule, "Min50")); assert_int_equal(true, StringSetContains(config->schedule, "Min55")); assert_int_equal(0, config->splay_time); assert_string_equal("LOG_USER", config->log_facility); ExecdConfigDestroy(config); } static void test_execd_config_empty(void) { run_test_in_policy("body_executor_control_empty.cf", &execd_config_empty_cb); } static void execd_config_full_cb(const EvalContext *ctx, const Policy *policy) { ExecdConfig *config = ExecdConfigNew(ctx, policy); assert_int_equal(2, StringSetSize(config->schedule)); assert_int_equal(true, StringSetContains(config->schedule, "Min00_05")); assert_int_equal(true, StringSetContains(config->schedule, "Min05_10")); /* Splay calculation uses FQNAME and getuid(), so can't predict actual splay value */ assert_int_equal(true, config->splay_time>=0 && config->splay_time<60); assert_string_equal("LOG_LOCAL6", config->log_facility); ExecdConfigDestroy(config); } static void test_execd_config_full(void) { run_test_in_policy("body_executor_control_full.cf", &execd_config_full_cb); } #define THREE_HOURS (3*60*60) static void exec_config_empty_cb(const EvalContext *ctx, const Policy *policy) { ExecConfig *config = ExecConfigNew(false, ctx, policy); assert_int_equal(false, config->scheduled_run); /* FIXME: exec-config should provide default exec_command */ assert_string_equal("", config->exec_command); assert_int_equal(THREE_HOURS, config->agent_expireafter); assert_string_equal("", config->mail_server); /* FIXME: exec-config should provide default from address */ assert_string_equal("", config->mail_from_address); assert_string_equal("", config->mail_to_address); /* FIXME: exec-config should provide default subject */ assert_string_equal("", config->mail_subject); assert_int_equal(30, config->mail_max_lines); assert_string_equal("localhost.localdomain", config->fq_name); assert_string_equal("127.0.0.100", config->ip_address); assert_string_equal("127.0.0.100 127.0.0.101", config->ip_addresses); ExecConfigDestroy(config); } static void test_exec_config_empty(void) { run_test_in_policy("body_executor_control_empty.cf", &exec_config_empty_cb); } static void CheckFullExecConfig(const ExecConfig *config) { assert_int_equal(true, config->scheduled_run); assert_string_equal("/bin/echo", config->exec_command); assert_int_equal(120, config->agent_expireafter); assert_string_equal("localhost", config->mail_server); assert_string_equal("cfengine@example.org", config->mail_from_address); assert_string_equal("cfengine_mail@example.org", config->mail_to_address); assert_string_equal("Test [localhost/127.0.0.1]", config->mail_subject); assert_int_equal(50, config->mail_max_lines); assert_string_equal("localhost.localdomain", config->fq_name); assert_string_equal("127.0.0.100", config->ip_address); assert_string_equal("127.0.0.100 127.0.0.101", config->ip_addresses); } static void exec_config_full_cb(const EvalContext *ctx, const Policy *policy) { ExecConfig *config = ExecConfigNew(true, ctx, policy); CheckFullExecConfig(config); ExecConfigDestroy(config); } static void test_exec_config_full(void) { run_test_in_policy("body_executor_control_full.cf", &exec_config_full_cb); } static void exec_config_copy_cb(const EvalContext *ctx, const Policy *policy) { ExecConfig *config = ExecConfigNew(true, ctx, policy); ExecConfig *config2 = ExecConfigCopy(config); ExecConfigDestroy(config); CheckFullExecConfig(config2); ExecConfigDestroy(config2); } static void test_exec_config_copy(void) { run_test_in_policy("body_executor_control_full.cf", &exec_config_copy_cb); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_execd_config_empty), unit_test(test_execd_config_full), unit_test(test_exec_config_empty), unit_test(test_exec_config_full), unit_test(test_exec_config_copy), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/map_test.c0000664000175100017510000001267112400110676017123 0ustar00a10038a1003800000000000000#include #include #include #include #include #include static unsigned int ConstHash(ARG_UNUSED const void *key, ARG_UNUSED unsigned int seed, ARG_UNUSED unsigned int max) { return 0; } static void test_new_destroy(void) { Map *map = MapNew(NULL, NULL, NULL, NULL); assert_int_equal(MapSize(map), 0); MapDestroy(map); } static void test_insert(void) { StringMap *map = StringMapNew(); assert_false(StringMapHasKey(map, "one")); StringMapInsert(map, xstrdup("one"), xstrdup("first")); assert_true(StringMapHasKey(map, "one")); assert_int_equal(StringMapSize(map), 1); StringMapInsert(map, xstrdup("one"), xstrdup("duplicate")); assert_int_equal(StringMapSize(map), 1); assert_false(StringMapHasKey(map, "two")); StringMapInsert(map, xstrdup("two"), xstrdup("second")); assert_true(StringMapHasKey(map, "two")); assert_int_equal(StringMapSize(map), 2); assert_false(StringMapHasKey(map, "third")); StringMapInsert(map, xstrdup("third"), xstrdup("first")); assert_true(StringMapHasKey(map, "third")); StringMapInsert(map, xstrdup("third"), xstrdup("stuff")); assert_true(StringMapHasKey(map, "third")); assert_int_equal(StringMapSize(map), 3); StringMapDestroy(map); } static char *CharTimes(char c, size_t times) { char *res = xmalloc(times + 1); memset(res, c, times); res[times] = '\0'; return res; } static StringMap *jumbo_map; static void test_insert_jumbo(void) { jumbo_map = StringMapNew(); for (int i = 0; i < 10000; i++) { /* char *s = CharTimes('a', i); */ char s[i+1]; memset(s, 'a', i); s[i] = '\0'; assert_false(StringMapHasKey(jumbo_map, s)); StringMapInsert(jumbo_map, xstrdup(s), xstrdup(s)); assert_true(StringMapHasKey(jumbo_map, s)); /* free(s); */ } StringMapPrintStats(jumbo_map, stdout); } static void test_remove(void) { HashMap *hashmap = HashMapNew(ConstHash, (MapKeyEqualFn)StringSafeEqual, free, free); HashMapInsert(hashmap, xstrdup("a"), xstrdup("b")); MapKeyValue *item = HashMapGet(hashmap, "a"); assert_string_equal(item->key, "a"); assert_string_equal(item->value, "b"); assert_true(HashMapRemove(hashmap, "a")); assert_int_equal(HashMapGet(hashmap, "a"), NULL); HashMapDestroy(hashmap); } static void test_get(void) { StringMap *map = StringMapNew(); StringMapInsert(map, xstrdup("one"), xstrdup("first")); assert_string_equal(StringMapGet(map, "one"), "first"); assert_int_equal(StringMapGet(map, "two"), NULL); StringMapDestroy(map); } static void test_has_key(void) { StringMap *map = StringMapNew(); StringMapInsert(map, xstrdup("one"), xstrdup("first")); assert_true(StringMapHasKey(map, "one")); assert_false(StringMapHasKey(map, NULL)); StringMapInsert(map, NULL, xstrdup("null")); assert_true(StringMapHasKey(map, NULL)); StringMapDestroy(map); } static void test_clear(void) { StringMap *map = StringMapNew(); StringMapInsert(map, xstrdup("one"), xstrdup("first")); assert_true(StringMapHasKey(map, "one")); StringMapClear(map); assert_false(StringMapHasKey(map, "one")); StringMapDestroy(map); } static void test_soft_destroy(void) { StringMap *map = StringMapNew(); char *key = xstrdup("one"); char *value = xstrdup("first"); StringMapInsert(map, key, value); assert_true(StringMapHasKey(map, "one")); assert_string_equal(StringMapGet(map, "one"),"first"); StringMapSoftDestroy(map); assert_string_equal("first", value); free(value); } static void test_iterate_jumbo(void) { size_t size = StringMapSize(jumbo_map); MapIterator it = MapIteratorInit(jumbo_map->impl); MapKeyValue *item = NULL; int count = 0; int sum_len = 0; while ((item = MapIteratorNext(&it))) { int key_len = strlen(item->key); int value_len = strlen(item->value); assert_int_equal(key_len, value_len); sum_len += key_len; count++; } assert_int_equal(count, 10000); assert_int_equal(count, size); assert_int_equal(sum_len, 10000*9999/2); StringMapDestroy(jumbo_map); } static void test_hashmap_new_destroy(void) { HashMap *hashmap = HashMapNew(NULL, NULL, NULL, NULL); HashMapDestroy(hashmap); } static void test_hashmap_degenerate_hash_fn(void) { HashMap *hashmap = HashMapNew(ConstHash, (MapKeyEqualFn)StringSafeEqual, free, free); for (int i = 0; i < 100; i++) { HashMapInsert(hashmap, CharTimes('a', i), CharTimes('a', i)); } MapKeyValue *item = HashMapGet(hashmap, "aaaa"); assert_string_equal(item->key, "aaaa"); assert_string_equal(item->value, "aaaa"); HashMapRemove(hashmap, "aaaa"); assert_int_equal(HashMapGet(hashmap, "aaaa"), NULL); HashMapDestroy(hashmap); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_new_destroy), unit_test(test_insert), unit_test(test_insert_jumbo), unit_test(test_remove), unit_test(test_get), unit_test(test_has_key), unit_test(test_clear), unit_test(test_soft_destroy), unit_test(test_iterate_jumbo), unit_test(test_hashmap_new_destroy), unit_test(test_hashmap_degenerate_hash_fn), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/str_test.c0000664000175100017510000003611212400110676017152 0ustar00a10038a1003800000000000000#include #include #include #include #include #include static const char *lo_alphabet = "abcdefghijklmnopqrstuvwxyz"; static const char *hi_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static void test_get_token(void) { { const char *str = " abc def ,efg "; size_t len = strlen(str); assert_int_equal(3, StringCountTokens(str, len, ", ")); { StringRef ref = StringGetToken(str, len, 0, ", "); assert_int_equal(3, ref.len); assert_memory_equal("abc", ref.data, 3); } { StringRef ref = StringGetToken(str, len, 1, ", "); assert_int_equal(3, ref.len); assert_memory_equal("def", ref.data, 3); } { StringRef ref = StringGetToken(str, len, 2, ", "); assert_int_equal(3, ref.len); assert_memory_equal("efg", ref.data, 3); } } { const char *str = "abc"; size_t len = strlen(str); assert_int_equal(1, StringCountTokens(str, len, ", ")); { StringRef ref = StringGetToken(str, len, 0, ", "); assert_int_equal(3, ref.len); assert_memory_equal("abc", ref.data, 3); } } { const char *str = "abc "; size_t len = strlen(str); assert_int_equal(1, StringCountTokens(str, len, ", ")); { StringRef ref = StringGetToken(str, len, 0, ", "); assert_int_equal(3, ref.len); assert_memory_equal("abc", ref.data, 3); } } } static void test_mix_case_tolower(void) { char str[] = "aBcD"; ToLowerStrInplace(str); assert_string_equal(str, "abcd"); } static void test_empty_tolower(void) { char str[] = ""; ToLowerStrInplace(str); assert_string_equal(str, ""); } static void test_weird_chars_tolower(void) { static const char *weirdstuff = "1345\0xff%$#@!"; char weirdstuff_copy_lowercased[CF_MAXVARSIZE]; strlcpy(weirdstuff_copy_lowercased, weirdstuff, CF_MAXVARSIZE); ToLowerStrInplace(weirdstuff_copy_lowercased); assert_string_equal(weirdstuff_copy_lowercased, weirdstuff); } static void test_alphabet_tolower(void) { char lo_alphabet_lowercased[CF_MAXVARSIZE]; strlcpy(lo_alphabet_lowercased, lo_alphabet, CF_MAXVARSIZE); ToLowerStrInplace(lo_alphabet_lowercased); assert_string_equal(lo_alphabet_lowercased, lo_alphabet); } static void test_hi_alphabet_tolower(void) { char hi_alphabet_lowercased[CF_MAXVARSIZE]; strlcpy(hi_alphabet_lowercased, hi_alphabet, CF_MAXVARSIZE); ToLowerStrInplace(hi_alphabet_lowercased); assert_string_equal(hi_alphabet_lowercased, lo_alphabet); } static void test_inplace_tolower(void) { char abc[] = "abc"; char def[] = "def"; ToLowerStrInplace(abc); ToLowerStrInplace(def); assert_string_equal(abc, "abc"); assert_string_equal(def, "def"); } static void test_mix_case_toupper(void) { char str[] = "aBcD"; ToUpperStrInplace(str); assert_string_equal(str, "ABCD"); } static void test_empty_toupper(void) { char str[] = ""; ToUpperStrInplace(str); assert_string_equal(str, ""); } static void test_weird_chars_toupper(void) { static const char *weirdstuff = "1345\0xff%$#@!"; char weirdstuff_copy_uppercased[CF_MAXVARSIZE]; strlcpy(weirdstuff_copy_uppercased, weirdstuff, CF_MAXVARSIZE); ToUpperStrInplace(weirdstuff_copy_uppercased); assert_string_equal(weirdstuff_copy_uppercased, weirdstuff); } static void test_alphabet_toupper(void) { char lo_alphabet_uppercased[CF_MAXVARSIZE]; strlcpy(lo_alphabet_uppercased, lo_alphabet, CF_MAXVARSIZE); ToUpperStrInplace(lo_alphabet_uppercased); assert_string_equal(lo_alphabet_uppercased, hi_alphabet); } static void test_hi_alphabet_toupper(void) { char hi_alphabet_uppercased[CF_MAXVARSIZE]; strlcpy(hi_alphabet_uppercased, hi_alphabet, CF_MAXVARSIZE); ToUpperStrInplace(hi_alphabet_uppercased); assert_string_equal(hi_alphabet_uppercased, hi_alphabet); } static void test_inplace_toupper(void) { char abc[] = "abc"; char def[] = "def"; ToUpperStrInplace(abc); ToUpperStrInplace(def); assert_string_equal(abc, "ABC"); assert_string_equal(def, "DEF"); } static void test_long_search(void) { char *ns = SearchAndReplace("abc", "abcabc", "test"); assert_string_equal(ns, "abc"); free(ns); } static void test_replace_empty_pattern(void) { char *ns = SearchAndReplace("foobarbaz", "", "abc"); assert_string_equal(ns, "foobarbaz"); free(ns); } static void test_replace_empty_replacement(void) { char *ns = SearchAndReplace("foobarbaz", "a", ""); assert_string_equal(ns, "foobrbz"); free(ns); } static void test_replace_eq_size(void) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "sz", "xx"); assert_string_equal(new_string, "saxxa xxedl sucha xxosa"); free(new_string); } static void test_replace_more_size(void) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "sz", "xxx"); assert_string_equal(new_string, "saxxxa xxxedl sucha xxxosa"); free(new_string); } static void test_replace_less_size(void) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "sz", "x"); assert_string_equal(new_string, "saxa xedl sucha xosa"); free(new_string); } static void test_no_replace(void) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "no_such_pattern", "x"); assert_string_equal(new_string, "sasza szedl sucha szosa"); free(new_string); } static void test_concatenate(void) { char *new_string = StringConcatenate(2, "snookie", "sitch"); assert_string_equal(new_string, "snookiesitch"); free(new_string); new_string = StringConcatenate(4, "a", NULL, "c", "d"); assert_string_equal(new_string, "acd"); free(new_string); new_string = StringConcatenate(3, "a", "b", "c", "d"); assert_string_equal(new_string, "abc"); free(new_string); new_string = StringConcatenate(1, "stuff"); assert_string_equal(new_string, "stuff"); free(new_string); new_string = StringConcatenate(0, NULL); assert_false(new_string); } static void test_substring_overshoot(void) { char *new_string = StringSubstring("abcdef", 6, 0, 10); assert_string_equal(new_string, "abcdef"); free(new_string); } static void test_substring_positive(void) { char *new_string = StringSubstring("abcdef", 6, 2, 3); assert_string_equal(new_string, "cde"); free(new_string); } static void test_substring_negative_length(void) { char *new_string = StringSubstring("abcdef", 6, 2, -1); assert_string_equal(new_string, "cde"); free(new_string); } static void test_substring_negative(void) { char *new_string = StringSubstring("abcdef", 6, -3, -1); assert_string_equal(new_string, "de"); free(new_string); } static void test_substring_evil(void) { char *new_string = StringSubstring("abcdef", 6, 4, -4); assert_int_equal(new_string, NULL); } static void test_string_to_long(void) { assert_int_equal(1234567, StringToLong("1234567")); } static void test_string_from_long(void) { assert_string_equal("123456789", StringFromLong(123456789)); assert_string_equal("-123456789", StringFromLong(-123456789)); } static void test_string_to_double(void) { assert_true(1234.1234 == StringToDouble("1234.1234")); } static void test_string_from_double(void) { assert_string_equal("1234.12", StringFromDouble(1234.1234)); } static void test_safe_compare(void) { assert_true(StringSafeCompare(NULL, NULL) == 0); assert_true(StringSafeCompare(NULL, "a") != 0); assert_true(StringSafeCompare("a", NULL) != 0); assert_true(StringSafeCompare("a", "a") == 0); assert_true(StringSafeCompare("a", "b") != 0); } static void test_safe_equal(void) { assert_true(StringSafeEqual(NULL, NULL)); assert_false(StringSafeEqual("a", NULL)); assert_false(StringSafeEqual(NULL, "a")); assert_false(StringSafeEqual("a", "b")); assert_true(StringSafeEqual("a", "a")); } static void test_match(void) { assert_true(StringMatch("^a.*$", "abc", NULL, NULL)); assert_true(StringMatch("a", "a", NULL, NULL)); assert_true(StringMatch("a", "ab", NULL, NULL)); assert_false(StringMatch("^a.*$", "bac", NULL, NULL)); } static void test_match_full(void) { assert_true(StringMatchFull("^a.*$", "abc")); assert_true(StringMatchFull("a", "a")); assert_false(StringMatchFull("a", "ab")); assert_false(StringMatchFull("^a.*$", "bac")); } static void test_encode_base64(void) { { char *res = StringEncodeBase64("", 0); assert_string_equal("", res); free(res); } { char *res = StringEncodeBase64("a", 1); assert_string_equal("YQ==", res); free(res); } { char *res = StringEncodeBase64("aa", 2); assert_string_equal("YWE=", res); free(res); } { char *res = StringEncodeBase64("aaa", 3); assert_string_equal("YWFh", res); free(res); } { char *res = StringEncodeBase64("aaaa", 4); assert_string_equal("YWFhYQ==", res); free(res); } { char *res = StringEncodeBase64("snookie", 7); assert_string_equal("c25vb2tpZQ==", res); free(res); } { char *res = StringEncodeBase64("test", 4); assert_string_equal("dGVzdA==", res); free(res); } // valgrind leaks should be due to crypto one-time allocations } static void test_escape_char_copy(void) { char *in1 = "my test with no escape"; char *out1 = EscapeCharCopy(in1, '7', '\\'); assert_string_equal(out1, in1); free(out1); char *in2 = "my test with 'some' escape"; char *out2 = EscapeCharCopy(in2, '\'', '\\'); assert_string_equal(out2, "my test with \\'some\\' escape"); free(out2); char *in3 = "my test with 7some7"; char *out3 = EscapeCharCopy(in3, '7', '\\'); assert_string_equal(out3, "my test with \\7some\\7"); free(out3); char *in4 = "\"my\" test with 7some7"; char *out4 = EscapeCharCopy(in4, '\"', '\\'); assert_string_equal(out4, "\\\"my\\\" test with 7some7"); free(out4); char *in5 = "\"my test with 7some7\""; char *out5 = EscapeCharCopy(in5, '\"', '\\'); assert_string_equal(out5, "\\\"my test with 7some7\\\""); free(out5); } static void test_chop_no_spaces(void) { char s[] = "abc"; Chop(s, CF_EXPANDSIZE); assert_string_equal("abc", s); } static void test_chop_single_space(void) { char s[] = "abc "; Chop(s, CF_EXPANDSIZE); assert_string_equal("abc", s); } static void test_chop_two_spaces(void) { char s[] = "abc "; Chop(s, CF_EXPANDSIZE); assert_string_equal("abc", s); } static void test_chop_empty(void) { char s[] = ""; Chop(s, CF_EXPANDSIZE); assert_string_equal("", s); } static void test_chop_empty_single_space(void) { char s[] = " "; Chop(s, CF_EXPANDSIZE); assert_string_equal("", s); } static void test_chop_empty_two_spaces(void) { char s[] = " "; Chop(s, CF_EXPANDSIZE); assert_string_equal("", s); } static void test_ends_with(void) { assert_true(StringEndsWith("file.json", ".json")); assert_true(StringEndsWith("file.json", "file.json")); assert_false(StringEndsWith(".json", "file")); assert_false(StringEndsWith("a", "aa")); } char *test_stringvformat_sup(const char *s, ...) { va_list ap; va_start(ap, s); char *fmted = StringVFormat(s, ap); va_end(ap); return fmted; } static void test_stringvformat(void) { char *s = test_stringvformat_sup("%s%d", "abc", 42); assert_string_equal(s, "abc42"); free(s); } static void test_stringformat(void) { char *s = StringFormat("%d%s%d", 1, "a", 2); assert_string_equal(s, "1a2"); free(s); } static void test_stringscanfcapped(void) { char buf[20]; char sp[30]; strcpy(sp,""); StringNotMatchingSetCapped(sp,20,"\n",buf); assert_string_equal(buf, ""); strcpy(sp,"\n"); StringNotMatchingSetCapped(sp,20,"\n",buf); assert_string_equal(buf, ""); strcpy(sp,"\n2345678901234567890abcdefghi"); StringNotMatchingSetCapped(sp,20,"\n",buf); assert_string_equal(buf, ""); strcpy(sp,"12345678901234567890abcdefghi"); StringNotMatchingSetCapped(sp,20,"\n",buf); assert_string_equal(buf, "1234567890123456789"); strcpy(sp,"12345678901234567890abcde\nghi"); StringNotMatchingSetCapped(sp,20,"\n",buf); assert_string_equal(buf, "1234567890123456789"); strcpy(sp,"123456789012345\n7890abcdefghi"); StringNotMatchingSetCapped(sp,20,"\n",buf); assert_string_equal(buf, "123456789012345"); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_get_token), unit_test(test_mix_case_tolower), unit_test(test_empty_tolower), unit_test(test_weird_chars_tolower), unit_test(test_alphabet_tolower), unit_test(test_hi_alphabet_tolower), unit_test(test_inplace_tolower), unit_test(test_mix_case_toupper), unit_test(test_empty_toupper), unit_test(test_weird_chars_toupper), unit_test(test_alphabet_toupper), unit_test(test_hi_alphabet_toupper), unit_test(test_inplace_toupper), unit_test(test_replace_empty_pattern), unit_test(test_replace_empty_replacement), unit_test(test_long_search), unit_test(test_replace_eq_size), unit_test(test_replace_more_size), unit_test(test_replace_less_size), unit_test(test_no_replace), unit_test(test_concatenate), unit_test(test_substring_overshoot), unit_test(test_substring_positive), unit_test(test_substring_negative_length), unit_test(test_substring_negative), unit_test(test_substring_evil), unit_test(test_string_to_long), unit_test(test_string_from_long), unit_test(test_string_to_double), unit_test(test_string_from_double), unit_test(test_safe_compare), unit_test(test_safe_equal), unit_test(test_match), unit_test(test_match_full), unit_test(test_encode_base64), unit_test(test_escape_char_copy), unit_test(test_chop_no_spaces), unit_test(test_chop_single_space), unit_test(test_chop_two_spaces), unit_test(test_chop_empty), unit_test(test_chop_empty_single_space), unit_test(test_chop_empty_two_spaces), unit_test(test_ends_with), unit_test(test_stringformat), unit_test(test_stringvformat), unit_test(test_stringscanfcapped), }; return run_tests(tests); } /* LCOV_EXCL_START */ /* Stub out functions we do not use in test */ void __ProgrammingError(ARG_UNUSED const char *file, ARG_UNUSED int lineno, ARG_UNUSED const char *format, ...) { fail(); exit(42); } void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } void Log(ARG_UNUSED LogLevel level, ARG_UNUSED const char *fmt, ...) { fail(); } /* LCOV_EXCL_STOP */ cfengine-3.6.2/tests/unit/ring_buffer_test.c0000644000175100017510000000431312316547775020652 0ustar00a10038a1003800000000000000#include #include #include #include static void test_excess(void) { static const size_t CAPACITY = 5; static const size_t FILL = 8; RingBuffer *buf = RingBufferNew(CAPACITY, NULL, free); assert_int_equal(0, RingBufferLength(buf)); assert_false(RingBufferHead(buf)); for (size_t i = 0; i < FILL; i++) { char *s = StringFromLong(i); RingBufferAppend(buf, s); if (i >= CAPACITY) { assert_true(RingBufferIsFull(buf)); assert_int_equal(CAPACITY, RingBufferLength(buf)); } else { assert_int_equal(i + 1, RingBufferLength(buf)); } assert_string_equal(s, RingBufferHead(buf)); } RingBufferIterator *iter = RingBufferIteratorNew(buf); const char *s = NULL; int i = FILL - CAPACITY; while ((s = RingBufferIteratorNext(iter))) { assert_int_equal(i, StringToLong(s)); i++; } assert_false(RingBufferIteratorNext(iter)); RingBufferIteratorDestroy(iter); RingBufferClear(buf); assert_int_equal(0, RingBufferLength(buf)); assert_false(RingBufferHead(buf)); RingBufferDestroy(buf); } static void test_shortage(void) { static const size_t CAPACITY = 5; RingBuffer *buf = RingBufferNew(CAPACITY, NULL, free); assert_false(RingBufferHead(buf)); RingBufferAppend(buf, xstrdup("hello")); assert_string_equal("hello", RingBufferHead(buf)); RingBufferAppend(buf, xstrdup("world")); assert_string_equal("world", RingBufferHead(buf)); assert_int_equal(2, RingBufferLength(buf)); RingBufferIterator *iter = RingBufferIteratorNew(buf); assert_string_equal("hello", RingBufferIteratorNext(iter)); assert_string_equal("world", RingBufferIteratorNext(iter)); assert_false(RingBufferIteratorNext(iter)); RingBufferIteratorDestroy(iter); RingBufferClear(buf); assert_int_equal(0, RingBufferLength(buf)); assert_false(RingBufferHead(buf)); RingBufferDestroy(buf); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_excess), unit_test(test_shortage) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/refcount_test.c0000644000175100017510000001500112316547775020203 0ustar00a10038a1003800000000000000#include #include // Simple initialization test static void test_init_destroy_RefCount(void) { RefCount *refCount = NULL; RefCountNew(&refCount); assert_int_equal(0, refCount->user_count); assert_true(refCount->last == NULL); assert_true(refCount->users == NULL); // Now we destroy the refcount. RefCountDestroy(&refCount); assert_true(refCount == NULL); // Try to destroy a NULL refCount RefCountDestroy(&refCount); } static void test_attach_detach_RefCount(void) { /* * This test does not check for NULL pointers, otherwise asserts will * be triggered. Neither does it check for non-existent owners. */ int data1 = 0xdeadbeef; int data2 = 0xbad00bad; int data3 = 0x55aaaa55; RefCount *refCount = NULL; // initialize the refcount RefCountNew(&refCount); assert_int_equal(0, refCount->user_count); assert_true(refCount->last == NULL); assert_true(refCount->users == NULL); // attach it to the first data RefCountAttach(refCount, &data1); // Check the result assert_int_equal(1, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous == NULL); assert_true(refCount->last->user == (void *)&data1); // Attach the second data RefCountAttach(refCount, &data2); // Check the result assert_int_equal(2, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous != NULL); assert_true(refCount->last->user == (void *)&data2); // Detach the first data RefCountDetach(refCount, &data1); // Check the result assert_int_equal(1, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous == NULL); assert_true(refCount->last->user == (void *)&data2); // Attach the third data RefCountAttach(refCount, &data3); // Check the result assert_int_equal(2, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous != NULL); assert_true(refCount->last->user == (void *)&data3); // Attach the first data RefCountAttach(refCount, &data1); // Check the result assert_int_equal(3, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous != NULL); assert_true(refCount->last->user == (void *)&data1); // Detach the third data RefCountDetach(refCount, &data3); // Check the result assert_int_equal(2, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous != NULL); assert_true(refCount->last->user == (void *)&data1); // Detach the first data RefCountDetach(refCount, &data1); // Check the result assert_int_equal(1, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous == NULL); assert_true(refCount->last->user == (void *)&data2); /* * We cannot detach the last element because that will assert. * Whenever there is only one element the only thing is to destroy * the refcount. */ // Destroy the refcount RefCountDestroy(&refCount); } static void test_isSharedRefCount(void) { int data1 = 0xdeadbeef; int data2 = 0xbad00bad; RefCount *refCount = NULL; // initialize the refcount RefCountNew(&refCount); assert_int_equal(0, refCount->user_count); assert_true(refCount->last == NULL); assert_true(refCount->users == NULL); // isShared should return false assert_false(RefCountIsShared(refCount)); // attach it to the first data RefCountAttach(refCount, &data1); // Check the result assert_int_equal(1, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous == NULL); assert_true(refCount->last->user == (void *)&data1); // isShared should return false assert_false(RefCountIsShared(refCount)); // Attach the second data RefCountAttach(refCount, &data2); // Check the result assert_int_equal(2, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous != NULL); assert_true(refCount->last->user == (void *)&data2); // isShared should return true assert_true(RefCountIsShared(refCount)); // Detach and try again RefCountDetach(refCount, &data1); // Check the result assert_int_equal(1, refCount->user_count); assert_true(refCount->last->next == NULL); assert_true(refCount->last->previous == NULL); assert_true(refCount->last->user == (void *)&data2); // isShared should return false assert_false(RefCountIsShared(refCount)); // Try isShared with a NULL refCount assert_false(RefCountIsShared(NULL)); // Destroy the refcount RefCountDestroy(&refCount); } static void test_isEqualRefCount(void) { int data2 = 0xbad00bad; RefCount *refCount1 = NULL; RefCount *refCount2 = NULL; // initialize refcount1 RefCountNew(&refCount1); assert_int_equal(0, refCount1->user_count); assert_true(refCount1->last == NULL); assert_true(refCount1->users == NULL); // initialize refcount2 as a copy of refcount1 refCount2 = refCount1; // isEqual should return true assert_true(RefCountIsEqual(refCount1, refCount2)); /* Initialize refcount2 on its own */ RefCountNew(&refCount2); assert_int_equal(0, refCount2->user_count); assert_true(refCount2->last == NULL); assert_true(refCount2->users == NULL); // isEqual should return false assert_false(RefCountIsEqual(refCount1, refCount2)); // Add one to refcount1 RefCountAttach(refCount1, &data2); // isEqual should return false assert_false(RefCountIsEqual(refCount1, refCount2)); // Add the same to refcount2 RefCountAttach(refCount2, &data2); // isEqual should return false assert_false(RefCountIsEqual(refCount1, refCount2)); // Try one NULL assert_false(RefCountIsEqual(refCount1, NULL)); assert_false(RefCountIsEqual(NULL, refCount2)); // Both NULL assert_false(RefCountIsEqual(NULL, NULL)); // Destroy both refcounts RefCountDestroy(&refCount1); RefCountDestroy(&refCount2); } int main() { const UnitTest tests[] = { unit_test(test_init_destroy_RefCount) , unit_test(test_attach_detach_RefCount) , unit_test(test_isSharedRefCount) , unit_test(test_isEqualRefCount) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/gcov-stub.c0000644000175100017510000000152112316547775017232 0ustar00a10038a1003800000000000000#include /* * Stubs which allow CFEngine compiled with gcov support to link against unit * test code which has gcov disabled. */ void __gcov_init(ARG_UNUSED void *p) { } void __gcov_merge_add(ARG_UNUSED void *p, ARG_UNUSED unsigned n_counters) { } int __gcov_execv(const char *path, char *const argv[]) { return execv(path, argv); } int __gcov_execl(const char *path, char *arg, ...) { va_list ap, aq; unsigned i, length; char **args; va_start(ap, arg); va_copy(aq, ap); length = 2; while (va_arg(ap, char *)) length++; va_end(ap); args = (char **) xmalloc(length * sizeof(void *)); args[0] = arg; for (i = 1; i < length; i++) args[i] = va_arg(aq, char *); va_end(aq); return execv(path, args); } pid_t __gcov_fork(void) { return fork(); } cfengine-3.6.2/tests/unit/aix_process_test.c0000664000175100017510000000667712400110676020676 0ustar00a10038a1003800000000000000#include #include #include #include #include /* * AIX 5.3 is missing this declaration */ #ifndef GETPROCS64 int getprocs64(struct procentry64 *, int, struct fdsinfo64 *, int, pid_t *, int); int getprocs64(struct procentry64* pe, int process_size, struct fdsinfo64 *fi, int files_size, pid_t* pid, int count) { assert_int_equal(count, 1); assert_true(fi == NULL); switch (*pid) { /* Normal process, running, started 1 jan 2000 00:00:00 */ case 1: memset(pe, 0, sizeof(struct procentry64)); pe->pi_pid = 1; pe->pi_start = 946681200; pe->pi_state = SACTIVE; *pid = 2; return 1; /* Normal process, stopped, started 31 dec 1980 23:59:59 */ case 2: memset(pe, 0, sizeof(struct procentry64)); pe->pi_pid = 2; pe->pi_start = 347151599; pe->pi_state = SSTOP; *pid = 3; return 1; /* Permission denied, getprocs64 returns EINVAL */ case 666: errno = EINVAL; return -1; /* Non-existing process, getprocs64 returns another process' info */ case 1000: memset(pe, 0, sizeof(struct procentry64)); pe->pi_pid = 1001; pe->pi_start = 312312313; pe->pi_state = SACTIVE; *pid = 1002; return 1; /* Non-existing process, table sentinel. getprocs64 return 0 */ case 1000000: return 0; } } #endif static void test_get_start_time_process1(void) { time_t t = GetProcessStartTime(1); assert_int_equal(t, 946681200); } static void test_get_start_time_process2(void) { time_t t2 = GetProcessStartTime(2); assert_int_equal(t2, 347151599); } static void test_get_start_time_process666(void) { time_t t = GetProcessStartTime(666); assert_int_equal(t, PROCESS_START_TIME_UNKNOWN); } static void test_get_start_time_process1000(void) { time_t t = GetProcessStartTime(1000); assert_int_equal(t, PROCESS_START_TIME_UNKNOWN); } static void test_get_start_time_process1000000(void) { time_t t = GetProcessStartTime(1000000); assert_int_equal(t, PROCESS_START_TIME_UNKNOWN); } static void test_get_state_process1(void) { ProcessState s = GetProcessState(1); assert_int_equal(s, PROCESS_STATE_RUNNING); } static void test_get_state_process2(void) { ProcessState s = GetProcessState(2); assert_int_equal(s, PROCESS_STATE_STOPPED); } static void test_get_state_process666(void) { ProcessState s = GetProcessState(666); assert_int_equal(s, PROCESS_STATE_DOES_NOT_EXIST); } static void test_get_state_process1000(void) { ProcessState s = GetProcessState(1000); assert_int_equal(s, PROCESS_STATE_DOES_NOT_EXIST); } static void test_get_state_process1000000(void) { ProcessState s = GetProcessState(1000000); assert_int_equal(s, PROCESS_STATE_DOES_NOT_EXIST); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_get_start_time_process1), unit_test(test_get_start_time_process2), unit_test(test_get_start_time_process666), unit_test(test_get_start_time_process1000), unit_test(test_get_start_time_process1000000), unit_test(test_get_state_process1), unit_test(test_get_state_process2), unit_test(test_get_state_process666), unit_test(test_get_state_process1000), unit_test(test_get_state_process1000000), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/syntax_test.c0000664000175100017510000001047312400110676017672 0ustar00a10038a1003800000000000000#include #include #include /* StringMatchFull */ static void test_lookup_promise_type_agent_vars(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("agent", "vars"); assert_true(s); assert_string_equal("vars", s->promise_type); } static void test_lookup_promise_type_common_vars(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("common", "vars"); assert_true(s); assert_string_equal("vars", s->promise_type); } static void test_lookup_promise_type_edit_xml_build_xpath(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("edit_xml", "build_xpath"); assert_true(s); assert_string_equal("build_xpath", s->promise_type); } static void test_lookup_promise_type_edit_line_delete_lines(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("edit_line", "delete_lines"); assert_true(s); assert_string_equal("delete_lines", s->promise_type); } static void test_lookup_promise_type_edit_xml_commons(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("edit_xml", "*"); assert_true(s); assert_string_equal("edit_xml", s->bundle_type); assert_string_equal("*", s->promise_type); } static void test_lookup_promise_type_global_commons(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("*", "*"); assert_true(s); assert_string_equal("*", s->bundle_type); assert_string_equal("*", s->promise_type); } static void test_lookup_constraint_edit_xml_set_attribute_attribute_value(void) { const PromiseTypeSyntax *s = PromiseTypeSyntaxGet("edit_xml", "set_attribute"); assert_true(s); assert_string_equal("set_attribute", s->promise_type); const ConstraintSyntax *x = PromiseTypeSyntaxGetConstraintSyntax(s, "attribute_value"); assert_true(x); assert_string_equal("attribute_value", x->lval); } static void test_lookup_body_classes(void) { const BodySyntax *x = BodySyntaxGet("classes"); assert_true(x); const ConstraintSyntax *y = BodySyntaxGetConstraintSyntax(x->constraints, "promise_repaired"); assert_true(y); assert_string_equal("promise_repaired", y->lval); } static void test_lookup_body_process_count(void) { const BodySyntax *x = BodySyntaxGet("process_count"); assert_true(x); const ConstraintSyntax *y = BodySyntaxGetConstraintSyntax(x->constraints, "match_range"); assert_true(y); assert_string_equal("match_range", y->lval); } static void test_lookup_body_delete_select(void) { const BodySyntax *x = BodySyntaxGet("delete_select"); assert_true(x); const ConstraintSyntax *y = BodySyntaxGetConstraintSyntax(x->constraints, "delete_if_startwith_from_list"); assert_true(y); assert_string_equal("delete_if_startwith_from_list", y->lval); } static void test_copy_from_servers(void) { const BodySyntax *x = BodySyntaxGet("copy_from"); assert_true(x); const ConstraintSyntax *y = BodySyntaxGetConstraintSyntax(x->constraints, "servers"); assert_true(y); assert_true(StringMatchFull(y->range.validation_string, "127.0.0.1")); assert_true(StringMatchFull(y->range.validation_string, "www-dashed.stuff.com")); assert_true(StringMatchFull(y->range.validation_string, "2604:2000:8441:e300:224:d7ff:fec5:338")); } static void test_typecheck_null_rval(void) { SyntaxTypeMatch err = CheckConstraintTypeMatch("whatever", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, CF_DATA_TYPE_STRING, "abc", 0); assert_int_equal(SYNTAX_TYPE_MATCH_ERROR_GOT_NULL, err); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_lookup_promise_type_agent_vars), unit_test(test_lookup_promise_type_common_vars), unit_test(test_lookup_promise_type_edit_xml_build_xpath), unit_test(test_lookup_promise_type_edit_line_delete_lines), unit_test(test_lookup_promise_type_edit_xml_commons), unit_test(test_lookup_promise_type_global_commons), unit_test(test_lookup_body_classes), unit_test(test_lookup_body_process_count), unit_test(test_lookup_body_delete_select), unit_test(test_lookup_constraint_edit_xml_set_attribute_attribute_value), unit_test(test_copy_from_servers), unit_test(test_typecheck_null_rval), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/cf_upgrade_test.c0000664000175100017510000001106412400110676020440 0ustar00a10038a1003800000000000000#include #include #include #include #include static void test_parse(void) { Configuration *configuration = NULL; char *empty_command_line[] = { "this" }; assert_int_equal (-1, parse(1, empty_command_line, &configuration)); assert_true (configuration == NULL); char *common_command_line[] = { "this", "-b", "backup.sh", "-s", "backup.tar.gz", "-i", "rpm", "-ivh", "package.rpm"}; assert_int_equal(0, parse(9, common_command_line, &configuration)); assert_true(configuration != NULL); assert_string_equal("backup.sh", ConfigurationBackupTool(configuration)); assert_string_equal("backup.tar.gz", ConfigurationBackupPath(configuration)); assert_string_equal("rpm", ConfigurationCommand(configuration)); assert_int_equal(3, ConfigurationNumberOfArguments(configuration)); ConfigurationDestroy(&configuration); assert_true(configuration == NULL); char *full_command_line[] = { "this", "-b", "backup.sh", "-s", "backup.tar.gz", "-c", "copy", "-f", "/opt/cfengine", "-i", "dpkg", "--install", "package.deb" }; assert_int_equal(0, parse(13, full_command_line, &configuration)); assert_true(configuration != NULL); assert_string_equal("backup.sh", ConfigurationBackupTool(configuration)); assert_string_equal("backup.tar.gz", ConfigurationBackupPath(configuration)); assert_string_equal("copy", ConfigurationCopy(configuration)); assert_string_equal("/opt/cfengine", ConfigurationCFEnginePath(configuration)); assert_string_equal("this", ConfigurationCFUpgrade(configuration)); assert_string_equal("dpkg", ConfigurationCommand(configuration)); assert_int_equal(3, ConfigurationNumberOfArguments(configuration)); ConfigurationDestroy(&configuration); assert_true(configuration == NULL); } static void test_configuration(void) { Configuration *configuration = ConfigurationNew(); assert_true(configuration != NULL); assert_true(ConfigurationBackupTool(configuration) == NULL); assert_true(ConfigurationBackupPath(configuration) == NULL); assert_string_equal("/tmp/cf-upgrade", ConfigurationCopy(configuration)); assert_string_equal("/var/cfengine/", ConfigurationCFEnginePath(configuration)); assert_true(ConfigurationCommand(configuration) == NULL); assert_true(ConfigurationCFUpgrade(configuration) == NULL); assert_int_equal(0, ConfigurationNumberOfArguments(configuration)); assert_false(ConfigurationPerformUpdate(configuration)); ConfigurationDestroy(&configuration); assert_true(configuration == NULL); configuration = ConfigurationNew(); char backup_tool[] = "backup.sh"; char backup_path[] = "backup.tar.gz"; char cfupgrade_copy[] = "/tmp/copy"; char cfupgrade[] = "cf-upgrade"; char command[] = "dpkg"; char argument[] = "-ivh"; char cfengine[] = "/opt/cfengine"; ConfigurationSetBackupTool(configuration, backup_tool); assert_string_equal(ConfigurationBackupTool(configuration), backup_tool); ConfigurationSetBackupPath(configuration, backup_path); assert_string_equal(ConfigurationBackupPath(configuration), backup_path); ConfigurationSetCopy(configuration, cfupgrade_copy); assert_string_equal(ConfigurationCopy(configuration), cfupgrade_copy); ConfigurationSetCFUpgrade(configuration, cfupgrade); assert_string_equal(ConfigurationCFUpgrade(configuration), cfupgrade); ConfigurationAddArgument(configuration, command); assert_string_equal(ConfigurationCommand(configuration), command); assert_string_equal(ConfigurationArgument(configuration, 0), command); assert_int_equal(1, ConfigurationNumberOfArguments(configuration)); ConfigurationAddArgument(configuration, argument); assert_string_equal(ConfigurationArgument(configuration, 0), command); assert_string_equal(ConfigurationArgument(configuration, 1), argument); assert_int_equal(2, ConfigurationNumberOfArguments(configuration)); ConfigurationSetCFEnginePath(configuration, cfengine); assert_string_equal(ConfigurationCFEnginePath(configuration), cfengine); assert_int_equal(2, ConfigurationNumberOfArguments(configuration)); ConfigurationDestroy(&configuration); assert_true(configuration == NULL); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_parse), unit_test(test_configuration) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/protocol_test.c0000664000175100017510000003404412411001073020175 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include /* GetCommandClassic */ /* * The protocol consists of the following commands: * "EXEC", * "AUTH", * "GET", * "OPENDIR", * "SYNCH", * "CLASSES", * "MD5", * "SMD5", * "CAUTH", * "SAUTH", * "SSYNCH", * "SGET", * "VERSION", * "SOPENDIR", * "VAR", * "SVAR", * "CONTEXT", * "SCONTEXT", * "SQUERY", * "SCALLBACK", */ static void test_command_parser(void) { ProtocolCommandClassic parsed = PROTOCOL_COMMAND_BAD; ProtocolCommandClassic expected = PROTOCOL_COMMAND_BAD; /* * Test all the commands, one by one. */ // EXEC expected = PROTOCOL_COMMAND_EXEC; parsed = GetCommandClassic("EXEC"); assert_int_equal(expected, parsed); // AUTH expected = PROTOCOL_COMMAND_AUTH; parsed = GetCommandClassic("AUTH"); assert_int_equal(expected, parsed); // GET expected = PROTOCOL_COMMAND_GET; parsed = GetCommandClassic("GET"); assert_int_equal(expected, parsed); // OPENDIR expected = PROTOCOL_COMMAND_OPENDIR; parsed = GetCommandClassic("OPENDIR"); assert_int_equal(expected, parsed); // SYNCH expected = PROTOCOL_COMMAND_SYNC; parsed = GetCommandClassic("SYNCH"); assert_int_equal(expected, parsed); // CLASSES expected = PROTOCOL_COMMAND_CONTEXTS; parsed = GetCommandClassic("CLASSES"); assert_int_equal(expected, parsed); // MD5 expected = PROTOCOL_COMMAND_MD5; parsed = GetCommandClassic("MD5"); assert_int_equal(expected, parsed); // SMD5 expected = PROTOCOL_COMMAND_MD5_SECURE; parsed = GetCommandClassic("SMD5"); assert_int_equal(expected, parsed); // CAUTH expected = PROTOCOL_COMMAND_AUTH_PLAIN; parsed = GetCommandClassic("CAUTH"); assert_int_equal(expected, parsed); // SAUTH expected = PROTOCOL_COMMAND_AUTH_SECURE; parsed = GetCommandClassic("SAUTH"); assert_int_equal(expected, parsed); // SSYNCH expected = PROTOCOL_COMMAND_SYNC_SECURE; parsed = GetCommandClassic("SSYNCH"); assert_int_equal(expected, parsed); // SGET expected = PROTOCOL_COMMAND_GET_SECURE; parsed = GetCommandClassic("SGET"); assert_int_equal(expected, parsed); // VERSION expected = PROTOCOL_COMMAND_VERSION; parsed = GetCommandClassic("VERSION"); assert_int_equal(expected, parsed); // SOPENDIR expected = PROTOCOL_COMMAND_OPENDIR_SECURE; parsed = GetCommandClassic("SOPENDIR"); assert_int_equal(expected, parsed); // VAR expected = PROTOCOL_COMMAND_VAR; parsed = GetCommandClassic("VAR"); assert_int_equal(expected, parsed); // SVAR expected = PROTOCOL_COMMAND_VAR_SECURE; parsed = GetCommandClassic("SVAR"); assert_int_equal(expected, parsed); // CONTEXT expected = PROTOCOL_COMMAND_CONTEXT; parsed = GetCommandClassic("CONTEXT"); assert_int_equal(expected, parsed); // SCONTEXT expected = PROTOCOL_COMMAND_CONTEXT_SECURE; parsed = GetCommandClassic("SCONTEXT"); assert_int_equal(expected, parsed); // SQUERY expected = PROTOCOL_COMMAND_QUERY_SECURE; parsed = GetCommandClassic("SQUERY"); assert_int_equal(expected, parsed); // SCALLBACK expected = PROTOCOL_COMMAND_CALL_ME_BACK; parsed = GetCommandClassic("SCALLBACK"); assert_int_equal(expected, parsed); /* * Try using lowercase */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("exec"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("auth"); assert_int_equal(expected, parsed); // GET parsed = GetCommandClassic("get"); assert_int_equal(expected, parsed); // OPENDIR parsed = GetCommandClassic("opendir"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("synch"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("classes"); assert_int_equal(expected, parsed); // MD5 parsed = GetCommandClassic("md5"); assert_int_equal(expected, parsed); // SMD5 parsed = GetCommandClassic("smd5"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("cauth"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("sauth"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("synch"); assert_int_equal(expected, parsed); // SGET parsed = GetCommandClassic("sget"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("version"); assert_int_equal(expected, parsed); // SOPENDIR parsed = GetCommandClassic("sopendir"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("var"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("svar"); assert_int_equal(expected, parsed); // CONTEXT parsed = GetCommandClassic("context"); assert_int_equal(expected, parsed); // SCONTEXT parsed = GetCommandClassic("scontext"); assert_int_equal(expected, parsed); // SQUERY parsed = GetCommandClassic("squery"); assert_int_equal(expected, parsed); // SCALLBACK parsed = GetCommandClassic("scallback"); assert_int_equal(expected, parsed); /* * Try the commands with something in front */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("eEXEC"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("aAUTH"); assert_int_equal(expected, parsed); // GET parsed = GetCommandClassic("gGET"); assert_int_equal(expected, parsed); // OPENDIR parsed = GetCommandClassic("oOPENDIR"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("sSYNCH"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("cCLASSES"); assert_int_equal(expected, parsed); // MD5 parsed = GetCommandClassic("mMD5"); assert_int_equal(expected, parsed); // SMD5 parsed = GetCommandClassic("sMD5"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("cCAUTH"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("sSAUTH"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("sSSYNCH"); assert_int_equal(expected, parsed); // SGET parsed = GetCommandClassic("sSGET"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("vVERSION"); assert_int_equal(expected, parsed); // SOPENDIR parsed = GetCommandClassic("sSOPENDIR"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("vVAR"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("sSVAR"); assert_int_equal(expected, parsed); // CONTEXT parsed = GetCommandClassic("cCONTEXT"); assert_int_equal(expected, parsed); // SCONTEXT parsed = GetCommandClassic("sSCONTEXT"); assert_int_equal(expected, parsed); // SQUERY parsed = GetCommandClassic("sSQUERY"); assert_int_equal(expected, parsed); // SCALLBACK parsed = GetCommandClassic("sSCALLBACK"); assert_int_equal(expected, parsed); /* * Try the commands with something after them */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("EXECx"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("AUTHx"); assert_int_equal(expected, parsed); // GET parsed = GetCommandClassic("GETx"); assert_int_equal(expected, parsed); // OPENDIR parsed = GetCommandClassic("OPENDIRx"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("SYNCHx"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("CLASSESx"); assert_int_equal(expected, parsed); // MD5 parsed = GetCommandClassic("MD5x"); assert_int_equal(expected, parsed); // SMD5 parsed = GetCommandClassic("SMD5x"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("CAUTHx"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("SAUTHx"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("SSYNCHx"); assert_int_equal(expected, parsed); // SGET parsed = GetCommandClassic("SGETx"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("VERSIONx"); assert_int_equal(expected, parsed); // SOPENDIR parsed = GetCommandClassic("SOPENDIRx"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("VARx"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("SVARx"); assert_int_equal(expected, parsed); // CONTEXT parsed = GetCommandClassic("CONTEXTx"); assert_int_equal(expected, parsed); // SCONTEXT parsed = GetCommandClassic("SCONTEXTx"); assert_int_equal(expected, parsed); // SQUERY parsed = GetCommandClassic("SQUERYx"); assert_int_equal(expected, parsed); // SCALLBACK parsed = GetCommandClassic("SCALLBACKx"); assert_int_equal(expected, parsed); /* * Try some common mispellings. */ // EXEC expected = PROTOCOL_COMMAND_BAD; parsed = GetCommandClassic("EXE"); assert_int_equal(expected, parsed); parsed = GetCommandClassic("EXECUTE"); assert_int_equal(expected, parsed); // AUTH parsed = GetCommandClassic("AUTHORIZATION"); assert_int_equal(expected, parsed); // SYNCH parsed = GetCommandClassic("SYNC"); assert_int_equal(expected, parsed); parsed = GetCommandClassic("SYNCHRONIZE"); assert_int_equal(expected, parsed); // CLASSES parsed = GetCommandClassic("CLASS"); assert_int_equal(expected, parsed); // CAUTH parsed = GetCommandClassic("CAUTHORIZATION"); assert_int_equal(expected, parsed); // SAUTH parsed = GetCommandClassic("SAUTHORIZATION"); assert_int_equal(expected, parsed); // SSYNCH parsed = GetCommandClassic("SSYNCHRONIZE"); assert_int_equal(expected, parsed); parsed = GetCommandClassic("SSYNC"); assert_int_equal(expected, parsed); // VERSION parsed = GetCommandClassic("V"); assert_int_equal(expected, parsed); // VAR parsed = GetCommandClassic("VARIABLE"); assert_int_equal(expected, parsed); // SVAR parsed = GetCommandClassic("SVARIABLE"); assert_int_equal(expected, parsed); /* * Finally, try the commands with a space and something else, they should be recognized" */ // EXEC expected = PROTOCOL_COMMAND_EXEC; parsed = GetCommandClassic("EXEC 123"); assert_int_equal(expected, parsed); // AUTH expected = PROTOCOL_COMMAND_AUTH; parsed = GetCommandClassic("AUTH 123"); assert_int_equal(expected, parsed); // GET expected = PROTOCOL_COMMAND_GET; parsed = GetCommandClassic("GET 123"); assert_int_equal(expected, parsed); // OPENDIR expected = PROTOCOL_COMMAND_OPENDIR; parsed = GetCommandClassic("OPENDIR 123"); assert_int_equal(expected, parsed); // SYNCH expected = PROTOCOL_COMMAND_SYNC; parsed = GetCommandClassic("SYNCH 123"); assert_int_equal(expected, parsed); // CLASSES expected = PROTOCOL_COMMAND_CONTEXTS; parsed = GetCommandClassic("CLASSES 123"); assert_int_equal(expected, parsed); // MD5 expected = PROTOCOL_COMMAND_MD5; parsed = GetCommandClassic("MD5 123"); assert_int_equal(expected, parsed); // SMD5 expected = PROTOCOL_COMMAND_MD5_SECURE; parsed = GetCommandClassic("SMD5 123"); assert_int_equal(expected, parsed); // CAUTH expected = PROTOCOL_COMMAND_AUTH_PLAIN; parsed = GetCommandClassic("CAUTH 123"); assert_int_equal(expected, parsed); // SAUTH expected = PROTOCOL_COMMAND_AUTH_SECURE; parsed = GetCommandClassic("SAUTH 123"); assert_int_equal(expected, parsed); // SSYNCH expected = PROTOCOL_COMMAND_SYNC_SECURE; parsed = GetCommandClassic("SSYNCH 123"); assert_int_equal(expected, parsed); // SGET expected = PROTOCOL_COMMAND_GET_SECURE; parsed = GetCommandClassic("SGET 123"); assert_int_equal(expected, parsed); // VERSION expected = PROTOCOL_COMMAND_VERSION; parsed = GetCommandClassic("VERSION 123"); assert_int_equal(expected, parsed); // SOPENDIR expected = PROTOCOL_COMMAND_OPENDIR_SECURE; parsed = GetCommandClassic("SOPENDIR 123"); assert_int_equal(expected, parsed); // VAR expected = PROTOCOL_COMMAND_VAR; parsed = GetCommandClassic("VAR 123"); assert_int_equal(expected, parsed); // SVAR expected = PROTOCOL_COMMAND_VAR_SECURE; parsed = GetCommandClassic("SVAR 123"); assert_int_equal(expected, parsed); // CONTEXT expected = PROTOCOL_COMMAND_CONTEXT; parsed = GetCommandClassic("CONTEXT 123"); assert_int_equal(expected, parsed); // SCONTEXT expected = PROTOCOL_COMMAND_CONTEXT_SECURE; parsed = GetCommandClassic("SCONTEXT 123"); assert_int_equal(expected, parsed); // SQUERY expected = PROTOCOL_COMMAND_QUERY_SECURE; parsed = GetCommandClassic("SQUERY 123"); assert_int_equal(expected, parsed); // SCALLBACK expected = PROTOCOL_COMMAND_CALL_ME_BACK; parsed = GetCommandClassic("SCALLBACK 123"); assert_int_equal(expected, parsed); } static void test_user_name(void) { const char *invalid_user_name = "user\\"; const char *invalid_user_name2 = "user//"; const char *invalid_user_name3 = "//\\"; const char *valid_user_name = "valid_user"; assert_false(IsUserNameValid(invalid_user_name)); assert_false(IsUserNameValid(invalid_user_name2)); assert_false(IsUserNameValid(invalid_user_name3)); assert_true(IsUserNameValid(valid_user_name)); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_command_parser), unit_test(test_user_name) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/Makefile.in0000664000175100017510000103045412412324465017216 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @HPUX_TRUE@am__append_1 = ../../libpromises/cf3globals.c check_PROGRAMS = arg_split_test$(EXEEXT) assoc_test$(EXEEXT) \ atexit_test$(EXEEXT) csv_writer_test$(EXEEXT) \ item_test$(EXEEXT) rlist_test$(EXEEXT) \ domainname_test$(EXEEXT) set_test$(EXEEXT) \ set_domainname_test$(EXEEXT) str_test$(EXEEXT) \ json_test$(EXEEXT) csv_parser_test$(EXEEXT) \ evalfunction_test$(EXEEXT) eval_context_test$(EXEEXT) \ regex_test$(EXEEXT) alloc_test$(EXEEXT) \ string_writer_test$(EXEEXT) file_writer_test$(EXEEXT) \ xml_writer_test$(EXEEXT) sequence_test$(EXEEXT) \ lastseen_test$(EXEEXT) lastseen_migration_test$(EXEEXT) \ changes_migration_test$(EXEEXT) db_test$(EXEEXT) \ db_concurrent_test$(EXEEXT) \ dbm_migration_bundles_test$(EXEEXT) misc_lib_test$(EXEEXT) \ item_lib_test$(EXEEXT) crypto_symmetric_test$(EXEEXT) \ persistent_lock_test$(EXEEXT) thread_test$(EXEEXT) \ package_versions_compare_test$(EXEEXT) files_lib_test$(EXEEXT) \ file_lib_test$(EXEEXT) map_test$(EXEEXT) \ parsemode_test$(EXEEXT) parser_test$(EXEEXT) \ policy_test$(EXEEXT) sort_test$(EXEEXT) \ file_name_test$(EXEEXT) logging_test$(EXEEXT) \ logging_timestamp_test$(EXEEXT) granules_test$(EXEEXT) \ scope_test$(EXEEXT) conversion_test$(EXEEXT) \ files_interfaces_test$(EXEEXT) refcount_test$(EXEEXT) \ list_test$(EXEEXT) buffer_test$(EXEEXT) \ cf_key_functions_test$(EXEEXT) \ connection_management_test$(EXEEXT) expand_test$(EXEEXT) \ string_expressions_test$(EXEEXT) var_expressions_test$(EXEEXT) \ process_terminate_unix_test$(EXEEXT) exec-config-test$(EXEEXT) \ generic_agent_test$(EXEEXT) syntax_test$(EXEEXT) \ sysinfo_test$(EXEEXT) ipaddress_test$(EXEEXT) \ hashes_test$(EXEEXT) rb-tree-test$(EXEEXT) \ variable_test$(EXEEXT) protocol_test$(EXEEXT) \ mon_cpu_test$(EXEEXT) mon_load_test$(EXEEXT) \ mon_processes_test$(EXEEXT) mustache_test$(EXEEXT) \ class_test$(EXEEXT) version_test$(EXEEXT) hash_test$(EXEEXT) \ key_test$(EXEEXT) cf_upgrade_test$(EXEEXT) queue_test$(EXEEXT) \ matching_test$(EXEEXT) ring_buffer_test$(EXEEXT) \ strlist_test$(EXEEXT) addr_lib_test$(EXEEXT) \ libcompat_test$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \ $(am__EXEEXT_3) $(am__EXEEXT_4) $(am__EXEEXT_5) \ $(am__EXEEXT_6) @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@am__append_2 = \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ findhub_test \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ avahi_config_test @BUILTIN_EXTENSIONS_FALSE@am__append_3 = enterprise_extension_test @BUILTIN_EXTENSIONS_FALSE@am__append_4 = cfengine-enterprise.la @LINUX_TRUE@am__append_5 = linux_process_test @AIX_TRUE@am__append_6 = aix_process_test @SOLARIS_TRUE@am__append_7 = solaris_process_test # tls_generic_test uses stub functions interposition which does not work (yet) # under OS X. Another way of stubbing functions from libpromises is needed. @XNU_FALSE@am__append_8 = tls_generic_test subdir = tests/unit DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = cfengine_enterprise_la_LIBADD = am__cfengine_enterprise_la_SOURCES_DIST = \ enterprise_extension_test_lib.c @BUILTIN_EXTENSIONS_FALSE@am_cfengine_enterprise_la_OBJECTS = \ @BUILTIN_EXTENSIONS_FALSE@ enterprise_extension_test_lib.lo cfengine_enterprise_la_OBJECTS = $(am_cfengine_enterprise_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = cfengine_enterprise_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(cfengine_enterprise_la_LDFLAGS) \ $(LDFLAGS) -o $@ @BUILTIN_EXTENSIONS_FALSE@am_cfengine_enterprise_la_rpath = libdb_la_DEPENDENCIES = libstr.la ../../libutils/libutils.la am__libdb_la_SOURCES_DIST = ../../libpromises/dbm_api.c \ ../../libpromises/mutex.c ../../libpromises/dbm_quick.c \ ../../libpromises/dbm_tokyocab.c ../../libpromises/dbm_lmdb.c \ ../../libpromises/dbm_migration.c \ ../../libpromises/dbm_migration_lastseen.c \ ../../libpromises/dbm_migration_bundles.c \ ../../libutils/logging.c ../../libutils/atexit.c \ ../../libpromises/cf3globals.c @HPUX_TRUE@am__objects_1 = libdb_la-cf3globals.lo am_libdb_la_OBJECTS = libdb_la-dbm_api.lo libdb_la-mutex.lo \ libdb_la-dbm_quick.lo libdb_la-dbm_tokyocab.lo \ libdb_la-dbm_lmdb.lo libdb_la-dbm_migration.lo \ libdb_la-dbm_migration_lastseen.lo \ libdb_la-dbm_migration_bundles.lo libdb_la-logging.lo \ libdb_la-atexit.lo $(am__objects_1) libdb_la_OBJECTS = $(am_libdb_la_OBJECTS) libdb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libdb_la_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ libstr_la_DEPENDENCIES = libtest.la am_libstr_la_OBJECTS = string_lib.lo regex.lo encode.lo writer.lo \ sequence.lo libstr_la_OBJECTS = $(am_libstr_la_OBJECTS) libtest_la_DEPENDENCIES = ../../libcompat/libcompat.la am_libtest_la_OBJECTS = cmockery.lo test.lo alloc.lo patches.lo \ constants.lo known_dirs.lo map.lo array_map.lo hash.lo \ hash_map.lo libtest_la_OBJECTS = $(am_libtest_la_OBJECTS) @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@am__EXEEXT_1 = findhub_test$(EXEEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ avahi_config_test$(EXEEXT) @BUILTIN_EXTENSIONS_FALSE@am__EXEEXT_2 = \ @BUILTIN_EXTENSIONS_FALSE@ enterprise_extension_test$(EXEEXT) @LINUX_TRUE@am__EXEEXT_3 = linux_process_test$(EXEEXT) @AIX_TRUE@am__EXEEXT_4 = aix_process_test$(EXEEXT) @SOLARIS_TRUE@am__EXEEXT_5 = solaris_process_test$(EXEEXT) @XNU_FALSE@am__EXEEXT_6 = tls_generic_test$(EXEEXT) addr_lib_test_SOURCES = addr_lib_test.c addr_lib_test_OBJECTS = addr_lib_test.$(OBJEXT) addr_lib_test_LDADD = $(LDADD) addr_lib_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am__aix_process_test_SOURCES_DIST = aix_process_test.c \ ../../libpromises/process_unix.c \ ../../libpromises/process_aix.c ../../libutils/file_lib.c @AIX_TRUE@am_aix_process_test_OBJECTS = aix_process_test.$(OBJEXT) \ @AIX_TRUE@ process_unix.$(OBJEXT) process_aix.$(OBJEXT) \ @AIX_TRUE@ file_lib.$(OBJEXT) aix_process_test_OBJECTS = $(am_aix_process_test_OBJECTS) @AIX_TRUE@aix_process_test_DEPENDENCIES = libtest.la \ @AIX_TRUE@ ../../libutils/libutils.la alloc_test_SOURCES = alloc_test.c alloc_test_OBJECTS = alloc_test.$(OBJEXT) alloc_test_LDADD = $(LDADD) alloc_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la arg_split_test_SOURCES = arg_split_test.c arg_split_test_OBJECTS = arg_split_test.$(OBJEXT) arg_split_test_LDADD = $(LDADD) arg_split_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la assoc_test_SOURCES = assoc_test.c assoc_test_OBJECTS = assoc_test.$(OBJEXT) assoc_test_LDADD = $(LDADD) assoc_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_atexit_test_OBJECTS = atexit_test.$(OBJEXT) atexit_test_OBJECTS = $(am_atexit_test_OBJECTS) atexit_test_DEPENDENCIES = libtest.la libdb.la am__avahi_config_test_SOURCES_DIST = avahi_config_test.c \ ../../cf-serverd/server_common.c ../../cf-serverd/server_tls.c \ ../../cf-serverd/server.c ../../cf-serverd/server_transform.c \ ../../cf-serverd/cf-serverd-enterprise-stubs.c \ ../../cf-serverd/server_access.c \ ../../cf-serverd/server_classic.c ../../cf-serverd/strlist.c @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@am_avahi_config_test_OBJECTS = avahi_config_test.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ server_common.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ server_tls.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ server.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ server_transform.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ cf-serverd-enterprise-stubs.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ server_access.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ server_classic.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ strlist.$(OBJEXT) avahi_config_test_OBJECTS = $(am_avahi_config_test_OBJECTS) @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@avahi_config_test_DEPENDENCIES = ../../libpromises/libpromises.la \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ libtest.la am_buffer_test_OBJECTS = buffer_test.$(OBJEXT) buffer.$(OBJEXT) buffer_test_OBJECTS = $(am_buffer_test_OBJECTS) buffer_test_LDADD = $(LDADD) buffer_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_cf_key_functions_test_OBJECTS = cf_key_functions_test.$(OBJEXT) \ cf-key-functions.$(OBJEXT) cf_key_functions_test_OBJECTS = $(am_cf_key_functions_test_OBJECTS) cf_key_functions_test_LDADD = $(LDADD) cf_key_functions_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_cf_upgrade_test_OBJECTS = \ cf_upgrade_test-cf_upgrade_test.$(OBJEXT) \ cf_upgrade_test-alloc-mini.$(OBJEXT) \ cf_upgrade_test-command_line.$(OBJEXT) \ cf_upgrade_test-configuration.$(OBJEXT) \ cf_upgrade_test-log.$(OBJEXT) \ cf_upgrade_test-process.$(OBJEXT) \ cf_upgrade_test-update.$(OBJEXT) cf_upgrade_test_OBJECTS = $(am_cf_upgrade_test_OBJECTS) cf_upgrade_test_LDADD = $(LDADD) cf_upgrade_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la cf_upgrade_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(cf_upgrade_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ changes_migration_test_SOURCES = changes_migration_test.c changes_migration_test_OBJECTS = changes_migration_test.$(OBJEXT) changes_migration_test_LDADD = $(LDADD) changes_migration_test_DEPENDENCIES = \ ../../libpromises/libpromises.la libtest.la class_test_SOURCES = class_test.c class_test_OBJECTS = class_test.$(OBJEXT) class_test_LDADD = $(LDADD) class_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_connection_management_test_OBJECTS = \ connection_management_test.$(OBJEXT) server_common.$(OBJEXT) \ server_tls.$(OBJEXT) connection_management_test_OBJECTS = \ $(am_connection_management_test_OBJECTS) connection_management_test_DEPENDENCIES = \ ../../libpromises/libpromises.la libtest.la \ ../../cf-serverd/libcf-serverd.la am_conversion_test_OBJECTS = conversion_test.$(OBJEXT) \ conversion.$(OBJEXT) conversion_test_OBJECTS = $(am_conversion_test_OBJECTS) conversion_test_LDADD = $(LDADD) conversion_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la crypto_symmetric_test_SOURCES = crypto_symmetric_test.c crypto_symmetric_test_OBJECTS = crypto_symmetric_test.$(OBJEXT) crypto_symmetric_test_LDADD = $(LDADD) crypto_symmetric_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_csv_parser_test_OBJECTS = csv_parser_test.$(OBJEXT) \ csv_parser.$(OBJEXT) csv_parser_test_OBJECTS = $(am_csv_parser_test_OBJECTS) csv_parser_test_DEPENDENCIES = libtest.la ../../libutils/libutils.la am_csv_writer_test_OBJECTS = csv_writer_test.$(OBJEXT) \ csv_writer.$(OBJEXT) csv_writer_test_OBJECTS = $(am_csv_writer_test_OBJECTS) csv_writer_test_DEPENDENCIES = libtest.la libstr.la am_db_concurrent_test_OBJECTS = db_concurrent_test.$(OBJEXT) db_concurrent_test_OBJECTS = $(am_db_concurrent_test_OBJECTS) db_concurrent_test_DEPENDENCIES = libdb.la am_db_test_OBJECTS = db_test.$(OBJEXT) db_test_OBJECTS = $(am_db_test_OBJECTS) db_test_DEPENDENCIES = libdb.la am_dbm_migration_bundles_test_OBJECTS = \ dbm_migration_bundles_test.$(OBJEXT) dbm_migration_bundles_test_OBJECTS = \ $(am_dbm_migration_bundles_test_OBJECTS) dbm_migration_bundles_test_DEPENDENCIES = libdb.la domainname_test_SOURCES = domainname_test.c domainname_test_OBJECTS = domainname_test.$(OBJEXT) domainname_test_LDADD = $(LDADD) domainname_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am__enterprise_extension_test_SOURCES_DIST = \ enterprise_extension_test.c @BUILTIN_EXTENSIONS_FALSE@am_enterprise_extension_test_OBJECTS = \ @BUILTIN_EXTENSIONS_FALSE@ enterprise_extension_test.$(OBJEXT) enterprise_extension_test_OBJECTS = \ $(am_enterprise_extension_test_OBJECTS) enterprise_extension_test_LDADD = $(LDADD) enterprise_extension_test_DEPENDENCIES = \ ../../libpromises/libpromises.la libtest.la eval_context_test_SOURCES = eval_context_test.c eval_context_test_OBJECTS = eval_context_test.$(OBJEXT) eval_context_test_LDADD = $(LDADD) eval_context_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la evalfunction_test_SOURCES = evalfunction_test.c evalfunction_test_OBJECTS = evalfunction_test.$(OBJEXT) evalfunction_test_LDADD = $(LDADD) evalfunction_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_exec_config_test_OBJECTS = exec-config-test.$(OBJEXT) \ exec-config.$(OBJEXT) execd-config.$(OBJEXT) exec_config_test_OBJECTS = $(am_exec_config_test_OBJECTS) exec_config_test_DEPENDENCIES = libtest.la \ ../../libpromises/libpromises.la expand_test_SOURCES = expand_test.c expand_test_OBJECTS = expand_test.$(OBJEXT) expand_test_LDADD = $(LDADD) expand_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_file_lib_test_OBJECTS = file_lib_test-file_lib_test.$(OBJEXT) \ file_lib_test-file_lib.$(OBJEXT) \ file_lib_test-logging.$(OBJEXT) \ file_lib_test-misc_lib.$(OBJEXT) \ file_lib_test-string_lib.$(OBJEXT) \ file_lib_test-sequence.$(OBJEXT) \ file_lib_test-unix_dir.$(OBJEXT) \ file_lib_test-writer.$(OBJEXT) file_lib_test_OBJECTS = $(am_file_lib_test_OBJECTS) file_lib_test_DEPENDENCIES = libtest.la file_name_test_SOURCES = file_name_test.c file_name_test_OBJECTS = file_name_test.$(OBJEXT) file_name_test_LDADD = $(LDADD) file_name_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_file_writer_test_OBJECTS = file_writer_test.$(OBJEXT) \ gcov-stub.$(OBJEXT) file_writer_test_OBJECTS = $(am_file_writer_test_OBJECTS) file_writer_test_LDADD = $(LDADD) file_writer_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la files_interfaces_test_SOURCES = files_interfaces_test.c files_interfaces_test_OBJECTS = files_interfaces_test.$(OBJEXT) files_interfaces_test_LDADD = $(LDADD) files_interfaces_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la files_lib_test_SOURCES = files_lib_test.c files_lib_test_OBJECTS = files_lib_test.$(OBJEXT) files_lib_test_LDADD = $(LDADD) files_lib_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am__findhub_test_SOURCES_DIST = findhub_test.c \ ../../cf-agent/findhub.c ../../cf-agent/load_avahi.c @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@am_findhub_test_OBJECTS = findhub_test.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ findhub.$(OBJEXT) \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ load_avahi.$(OBJEXT) findhub_test_OBJECTS = $(am_findhub_test_OBJECTS) findhub_test_LDADD = $(LDADD) findhub_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la generic_agent_test_SOURCES = generic_agent_test.c generic_agent_test_OBJECTS = generic_agent_test.$(OBJEXT) generic_agent_test_LDADD = $(LDADD) generic_agent_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la granules_test_SOURCES = granules_test.c granules_test_OBJECTS = granules_test.$(OBJEXT) granules_test_LDADD = $(LDADD) granules_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_hash_test_OBJECTS = hash_test.$(OBJEXT) hash_test_OBJECTS = $(am_hash_test_OBJECTS) hash_test_DEPENDENCIES = ../../libutils/libutils.la libtest.la hashes_test_SOURCES = hashes_test.c hashes_test_OBJECTS = hashes_test.$(OBJEXT) hashes_test_LDADD = $(LDADD) hashes_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_ipaddress_test_OBJECTS = ipaddress_test.$(OBJEXT) ipaddress_test_OBJECTS = $(am_ipaddress_test_OBJECTS) ipaddress_test_LDADD = $(LDADD) ipaddress_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la item_lib_test_SOURCES = item_lib_test.c item_lib_test_OBJECTS = item_lib_test.$(OBJEXT) item_lib_test_LDADD = $(LDADD) item_lib_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la item_test_SOURCES = item_test.c item_test_OBJECTS = item_test.$(OBJEXT) item_test_LDADD = $(LDADD) item_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la json_test_SOURCES = json_test.c json_test_OBJECTS = json_test.$(OBJEXT) json_test_LDADD = $(LDADD) json_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_key_test_OBJECTS = key_test.$(OBJEXT) key_test_OBJECTS = $(am_key_test_OBJECTS) key_test_DEPENDENCIES = ../../libpromises/libpromises.la \ ../../libutils/libutils.la libtest.la am_lastseen_migration_test_OBJECTS = \ lastseen_migration_test.$(OBJEXT) lastseen.$(OBJEXT) \ statistics.$(OBJEXT) item_lib.$(OBJEXT) lastseen_migration_test_OBJECTS = \ $(am_lastseen_migration_test_OBJECTS) lastseen_migration_test_DEPENDENCIES = libdb.la \ ../../libpromises/libpromises.la am_lastseen_test_OBJECTS = lastseen_test.$(OBJEXT) item_lib.$(OBJEXT) \ lastseen.$(OBJEXT) statistics.$(OBJEXT) lastseen_test_OBJECTS = $(am_lastseen_test_OBJECTS) lastseen_test_DEPENDENCIES = libdb.la ../../libpromises/libpromises.la am_libcompat_test_OBJECTS = libcompat_test-libcompat_test.$(OBJEXT) libcompat_test_OBJECTS = $(am_libcompat_test_OBJECTS) libcompat_test_LDADD = $(LDADD) libcompat_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am__linux_process_test_SOURCES_DIST = linux_process_test.c \ ../../libpromises/process_unix.c \ ../../libpromises/process_linux.c ../../libutils/file_lib.c @LINUX_TRUE@am_linux_process_test_OBJECTS = \ @LINUX_TRUE@ linux_process_test.$(OBJEXT) \ @LINUX_TRUE@ process_unix.$(OBJEXT) process_linux.$(OBJEXT) \ @LINUX_TRUE@ file_lib.$(OBJEXT) linux_process_test_OBJECTS = $(am_linux_process_test_OBJECTS) @LINUX_TRUE@linux_process_test_DEPENDENCIES = libtest.la \ @LINUX_TRUE@ ../../libutils/libutils.la am_list_test_OBJECTS = list_test.$(OBJEXT) list_test_OBJECTS = $(am_list_test_OBJECTS) list_test_LDADD = $(LDADD) list_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_logging_test_OBJECTS = logging_test.$(OBJEXT) \ syslog_client.$(OBJEXT) logging_test_OBJECTS = $(am_logging_test_OBJECTS) logging_test_DEPENDENCIES = libtest.la ../../libutils/libutils.la am_logging_timestamp_test_OBJECTS = logging_timestamp_test.$(OBJEXT) logging_timestamp_test_OBJECTS = $(am_logging_timestamp_test_OBJECTS) logging_timestamp_test_DEPENDENCIES = libtest.la \ ../../libutils/libutils.la map_test_SOURCES = map_test.c map_test_OBJECTS = map_test.$(OBJEXT) map_test_LDADD = $(LDADD) map_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la matching_test_SOURCES = matching_test.c matching_test_OBJECTS = matching_test.$(OBJEXT) matching_test_LDADD = $(LDADD) matching_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la misc_lib_test_SOURCES = misc_lib_test.c misc_lib_test_OBJECTS = misc_lib_test.$(OBJEXT) misc_lib_test_LDADD = $(LDADD) misc_lib_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_mon_cpu_test_OBJECTS = mon_cpu_test.$(OBJEXT) mon_cpu.$(OBJEXT) mon_cpu_test_OBJECTS = $(am_mon_cpu_test_OBJECTS) mon_cpu_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_mon_load_test_OBJECTS = mon_load_test.$(OBJEXT) mon_load.$(OBJEXT) mon_load_test_OBJECTS = $(am_mon_load_test_OBJECTS) mon_load_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_mon_processes_test_OBJECTS = mon_processes_test.$(OBJEXT) \ mon_processes.$(OBJEXT) mon_processes_test_OBJECTS = $(am_mon_processes_test_OBJECTS) mon_processes_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la mustache_test_SOURCES = mustache_test.c mustache_test_OBJECTS = mustache_test.$(OBJEXT) mustache_test_LDADD = $(LDADD) mustache_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_package_versions_compare_test_OBJECTS = \ package_versions_compare_test.$(OBJEXT) \ verify_packages.$(OBJEXT) vercmp.$(OBJEXT) \ vercmp_internal.$(OBJEXT) retcode.$(OBJEXT) \ match_scope.$(OBJEXT) package_versions_compare_test_OBJECTS = \ $(am_package_versions_compare_test_OBJECTS) package_versions_compare_test_DEPENDENCIES = \ ../../libpromises/libpromises.la libtest.la parsemode_test_SOURCES = parsemode_test.c parsemode_test_OBJECTS = parsemode_test.$(OBJEXT) parsemode_test_LDADD = $(LDADD) parsemode_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la parser_test_SOURCES = parser_test.c parser_test_OBJECTS = parser_test.$(OBJEXT) parser_test_LDADD = $(LDADD) parser_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la persistent_lock_test_SOURCES = persistent_lock_test.c persistent_lock_test_OBJECTS = persistent_lock_test.$(OBJEXT) persistent_lock_test_LDADD = $(LDADD) persistent_lock_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la policy_test_SOURCES = policy_test.c policy_test_OBJECTS = policy_test.$(OBJEXT) policy_test_LDADD = $(LDADD) policy_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am_process_terminate_unix_test_OBJECTS = \ process_terminate_unix_test.$(OBJEXT) process_unix.$(OBJEXT) process_terminate_unix_test_OBJECTS = \ $(am_process_terminate_unix_test_OBJECTS) process_terminate_unix_test_DEPENDENCIES = libtest.la \ ../../libutils/libutils.la am_protocol_test_OBJECTS = protocol_test.$(OBJEXT) \ server_common.$(OBJEXT) server_tls.$(OBJEXT) server.$(OBJEXT) \ cf-serverd-enterprise-stubs.$(OBJEXT) \ server_transform.$(OBJEXT) cf-serverd-functions.$(OBJEXT) \ server_access.$(OBJEXT) strlist.$(OBJEXT) protocol_test_OBJECTS = $(am_protocol_test_OBJECTS) protocol_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_queue_test_OBJECTS = queue_test.$(OBJEXT) queue_test_OBJECTS = $(am_queue_test_OBJECTS) queue_test_LDADD = $(LDADD) queue_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la rb_tree_test_SOURCES = rb-tree-test.c rb_tree_test_OBJECTS = rb-tree-test.$(OBJEXT) rb_tree_test_LDADD = $(LDADD) rb_tree_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_refcount_test_OBJECTS = refcount_test.$(OBJEXT) refcount.$(OBJEXT) refcount_test_OBJECTS = $(am_refcount_test_OBJECTS) refcount_test_LDADD = $(LDADD) refcount_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_regex_test_OBJECTS = regex_test.$(OBJEXT) match_scope.$(OBJEXT) regex_test_OBJECTS = $(am_regex_test_OBJECTS) regex_test_LDADD = $(LDADD) regex_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la ring_buffer_test_SOURCES = ring_buffer_test.c ring_buffer_test_OBJECTS = ring_buffer_test.$(OBJEXT) ring_buffer_test_LDADD = $(LDADD) ring_buffer_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_rlist_test_OBJECTS = rlist_test.$(OBJEXT) rlist.$(OBJEXT) \ logging.$(OBJEXT) rlist_test_OBJECTS = $(am_rlist_test_OBJECTS) rlist_test_DEPENDENCIES = libtest.la libstr.la \ ../../libpromises/libpromises.la scope_test_SOURCES = scope_test.c scope_test_OBJECTS = scope_test.$(OBJEXT) scope_test_LDADD = $(LDADD) scope_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la sequence_test_SOURCES = sequence_test.c sequence_test_OBJECTS = sequence_test.$(OBJEXT) sequence_test_LDADD = $(LDADD) sequence_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_set_domainname_test_OBJECTS = set_domainname_test.$(OBJEXT) set_domainname_test_OBJECTS = $(am_set_domainname_test_OBJECTS) set_domainname_test_DEPENDENCIES = libstr.la \ ../../libpromises/libpromises.la set_test_SOURCES = set_test.c set_test_OBJECTS = set_test.$(OBJEXT) set_test_LDADD = $(LDADD) set_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am__solaris_process_test_SOURCES_DIST = solaris_process_test.c \ ../../libpromises/process_unix.c \ ../../libpromises/process_solaris.c ../../libutils/file_lib.c @SOLARIS_TRUE@am_solaris_process_test_OBJECTS = \ @SOLARIS_TRUE@ solaris_process_test.$(OBJEXT) \ @SOLARIS_TRUE@ process_unix.$(OBJEXT) process_solaris.$(OBJEXT) \ @SOLARIS_TRUE@ file_lib.$(OBJEXT) solaris_process_test_OBJECTS = $(am_solaris_process_test_OBJECTS) @SOLARIS_TRUE@solaris_process_test_DEPENDENCIES = libtest.la \ @SOLARIS_TRUE@ ../../libutils/libutils.la am_sort_test_OBJECTS = sort_test.$(OBJEXT) sort_test_OBJECTS = $(am_sort_test_OBJECTS) sort_test_DEPENDENCIES = libtest.la ../../libpromises/libpromises.la am_str_test_OBJECTS = str_test.$(OBJEXT) str_test_OBJECTS = $(am_str_test_OBJECTS) str_test_DEPENDENCIES = libstr.la string_expressions_test_SOURCES = string_expressions_test.c string_expressions_test_OBJECTS = string_expressions_test.$(OBJEXT) string_expressions_test_LDADD = $(LDADD) string_expressions_test_DEPENDENCIES = \ ../../libpromises/libpromises.la libtest.la string_writer_test_SOURCES = string_writer_test.c string_writer_test_OBJECTS = string_writer_test.$(OBJEXT) string_writer_test_LDADD = $(LDADD) string_writer_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_strlist_test_OBJECTS = strlist_test.$(OBJEXT) strlist.$(OBJEXT) strlist_test_OBJECTS = $(am_strlist_test_OBJECTS) strlist_test_LDADD = $(LDADD) strlist_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la syntax_test_SOURCES = syntax_test.c syntax_test_OBJECTS = syntax_test.$(OBJEXT) syntax_test_LDADD = $(LDADD) syntax_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la sysinfo_test_SOURCES = sysinfo_test.c sysinfo_test_OBJECTS = sysinfo_test.$(OBJEXT) sysinfo_test_DEPENDENCIES = libtest.la ../../libenv/libenv.la \ ../../libpromises/libpromises.la thread_test_SOURCES = thread_test.c thread_test_OBJECTS = thread_test.$(OBJEXT) thread_test_LDADD = $(LDADD) thread_test_DEPENDENCIES = ../../libpromises/libpromises.la libtest.la am__tls_generic_test_SOURCES_DIST = tls_generic_test.c @XNU_FALSE@am_tls_generic_test_OBJECTS = tls_generic_test.$(OBJEXT) tls_generic_test_OBJECTS = $(am_tls_generic_test_OBJECTS) @XNU_FALSE@tls_generic_test_DEPENDENCIES = libtest.la \ @XNU_FALSE@ ../../libutils/libutils.la \ @XNU_FALSE@ ../../libpromises/libpromises.la \ @XNU_FALSE@ ../../libcfnet/libcfnet.la \ @XNU_FALSE@ ../../cf-serverd/libcf-serverd.la var_expressions_test_SOURCES = var_expressions_test.c var_expressions_test_OBJECTS = var_expressions_test.$(OBJEXT) var_expressions_test_LDADD = $(LDADD) var_expressions_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la variable_test_SOURCES = variable_test.c variable_test_OBJECTS = variable_test.$(OBJEXT) variable_test_LDADD = $(LDADD) variable_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_version_test_OBJECTS = version_test.$(OBJEXT) version_test_OBJECTS = $(am_version_test_OBJECTS) version_test_LDADD = $(LDADD) version_test_DEPENDENCIES = ../../libpromises/libpromises.la \ libtest.la am_xml_writer_test_OBJECTS = xml_writer_test.$(OBJEXT) \ xml_writer.$(OBJEXT) xml_writer_test_OBJECTS = $(am_xml_writer_test_OBJECTS) xml_writer_test_DEPENDENCIES = libtest.la libstr.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(cfengine_enterprise_la_SOURCES) $(libdb_la_SOURCES) \ $(libstr_la_SOURCES) $(libtest_la_SOURCES) addr_lib_test.c \ $(aix_process_test_SOURCES) alloc_test.c arg_split_test.c \ assoc_test.c $(atexit_test_SOURCES) \ $(avahi_config_test_SOURCES) $(buffer_test_SOURCES) \ $(cf_key_functions_test_SOURCES) $(cf_upgrade_test_SOURCES) \ changes_migration_test.c class_test.c \ $(connection_management_test_SOURCES) \ $(conversion_test_SOURCES) crypto_symmetric_test.c \ $(csv_parser_test_SOURCES) $(csv_writer_test_SOURCES) \ $(db_concurrent_test_SOURCES) $(db_test_SOURCES) \ $(dbm_migration_bundles_test_SOURCES) domainname_test.c \ $(enterprise_extension_test_SOURCES) eval_context_test.c \ evalfunction_test.c $(exec_config_test_SOURCES) expand_test.c \ $(file_lib_test_SOURCES) file_name_test.c \ $(file_writer_test_SOURCES) files_interfaces_test.c \ files_lib_test.c $(findhub_test_SOURCES) generic_agent_test.c \ granules_test.c $(hash_test_SOURCES) hashes_test.c \ $(ipaddress_test_SOURCES) item_lib_test.c item_test.c \ json_test.c $(key_test_SOURCES) \ $(lastseen_migration_test_SOURCES) $(lastseen_test_SOURCES) \ $(libcompat_test_SOURCES) $(linux_process_test_SOURCES) \ $(list_test_SOURCES) $(logging_test_SOURCES) \ $(logging_timestamp_test_SOURCES) map_test.c matching_test.c \ misc_lib_test.c $(mon_cpu_test_SOURCES) \ $(mon_load_test_SOURCES) $(mon_processes_test_SOURCES) \ mustache_test.c $(package_versions_compare_test_SOURCES) \ parsemode_test.c parser_test.c persistent_lock_test.c \ policy_test.c $(process_terminate_unix_test_SOURCES) \ $(protocol_test_SOURCES) $(queue_test_SOURCES) rb-tree-test.c \ $(refcount_test_SOURCES) $(regex_test_SOURCES) \ ring_buffer_test.c $(rlist_test_SOURCES) scope_test.c \ sequence_test.c $(set_domainname_test_SOURCES) set_test.c \ $(solaris_process_test_SOURCES) $(sort_test_SOURCES) \ $(str_test_SOURCES) string_expressions_test.c \ string_writer_test.c $(strlist_test_SOURCES) syntax_test.c \ sysinfo_test.c thread_test.c $(tls_generic_test_SOURCES) \ var_expressions_test.c variable_test.c $(version_test_SOURCES) \ $(xml_writer_test_SOURCES) DIST_SOURCES = $(am__cfengine_enterprise_la_SOURCES_DIST) \ $(am__libdb_la_SOURCES_DIST) $(libstr_la_SOURCES) \ $(libtest_la_SOURCES) addr_lib_test.c \ $(am__aix_process_test_SOURCES_DIST) alloc_test.c \ arg_split_test.c assoc_test.c $(atexit_test_SOURCES) \ $(am__avahi_config_test_SOURCES_DIST) $(buffer_test_SOURCES) \ $(cf_key_functions_test_SOURCES) $(cf_upgrade_test_SOURCES) \ changes_migration_test.c class_test.c \ $(connection_management_test_SOURCES) \ $(conversion_test_SOURCES) crypto_symmetric_test.c \ $(csv_parser_test_SOURCES) $(csv_writer_test_SOURCES) \ $(db_concurrent_test_SOURCES) $(db_test_SOURCES) \ $(dbm_migration_bundles_test_SOURCES) domainname_test.c \ $(am__enterprise_extension_test_SOURCES_DIST) \ eval_context_test.c evalfunction_test.c \ $(exec_config_test_SOURCES) expand_test.c \ $(file_lib_test_SOURCES) file_name_test.c \ $(file_writer_test_SOURCES) files_interfaces_test.c \ files_lib_test.c $(am__findhub_test_SOURCES_DIST) \ generic_agent_test.c granules_test.c $(hash_test_SOURCES) \ hashes_test.c $(ipaddress_test_SOURCES) item_lib_test.c \ item_test.c json_test.c $(key_test_SOURCES) \ $(lastseen_migration_test_SOURCES) $(lastseen_test_SOURCES) \ $(libcompat_test_SOURCES) \ $(am__linux_process_test_SOURCES_DIST) $(list_test_SOURCES) \ $(logging_test_SOURCES) $(logging_timestamp_test_SOURCES) \ map_test.c matching_test.c misc_lib_test.c \ $(mon_cpu_test_SOURCES) $(mon_load_test_SOURCES) \ $(mon_processes_test_SOURCES) mustache_test.c \ $(package_versions_compare_test_SOURCES) parsemode_test.c \ parser_test.c persistent_lock_test.c policy_test.c \ $(process_terminate_unix_test_SOURCES) \ $(protocol_test_SOURCES) $(queue_test_SOURCES) rb-tree-test.c \ $(refcount_test_SOURCES) $(regex_test_SOURCES) \ ring_buffer_test.c $(rlist_test_SOURCES) scope_test.c \ sequence_test.c $(set_domainname_test_SOURCES) set_test.c \ $(am__solaris_process_test_SOURCES_DIST) $(sort_test_SOURCES) \ $(str_test_SOURCES) string_expressions_test.c \ string_writer_test.c $(strlist_test_SOURCES) syntax_test.c \ sysinfo_test.c thread_test.c \ $(am__tls_generic_test_SOURCES_DIST) var_expressions_test.c \ variable_test.c $(version_test_SOURCES) \ $(xml_writer_test_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ # automake does not support "maude_LIBS" variables. We can only alter # the generic LIBS one. In case the functions are mocked in the test # implementation, then we are pretty sure that they will be overriden by # our local implementation. So we include *everything*... LIBS = $(CORE_LIBS) LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ # Just recursively include in dist tarball all data we need for unit tests EXTRA_DIST = data dynamic_dependency_test.sh AM_CPPFLAGS = $(CORE_CPPFLAGS) \ $(ENTERPRISE_CFLAGS) \ -I$(srcdir)/../../libcfnet \ -I$(srcdir)/../../libenv \ -I$(srcdir)/../../libpromises \ -I$(srcdir)/../../libutils \ -I$(srcdir)/../../cf-monitord \ -I$(srcdir)/../../cf-serverd \ -I$(srcdir)/../../cf-agent \ -I$(srcdir)/../../cf-execd \ -I$(srcdir)/../../cf-key \ -DTESTDATADIR='"$(srcdir)/data"' LDADD = ../../libpromises/libpromises.la libtest.la AM_LDFLAGS = $(CORE_LDFLAGS) check_LTLIBRARIES = libtest.la libstr.la libdb.la $(am__append_4) libtest_la_SOURCES = cmockery.c cmockery.h schema.h test.c test.h \ ../../libutils/alloc.c \ ../../libpromises/patches.c \ ../../libpromises/constants.c \ ../../libpromises/known_dirs.c \ ../../libutils/map.c \ ../../libutils/array_map.c \ ../../libutils/hash.c \ ../../libutils/hash_map.c libtest_la_LIBADD = ../../libcompat/libcompat.la libstr_la_SOURCES = ../../libutils/string_lib.c ../../libutils/regex.c \ ../../libutils/encode.c ../../libutils/writer.c \ ../../libutils/sequence.c libstr_la_LIBADD = libtest.la libdb_la_SOURCES = ../../libpromises/dbm_api.c \ ../../libpromises/mutex.c ../../libpromises/dbm_quick.c \ ../../libpromises/dbm_tokyocab.c ../../libpromises/dbm_lmdb.c \ ../../libpromises/dbm_migration.c \ ../../libpromises/dbm_migration_lastseen.c \ ../../libpromises/dbm_migration_bundles.c \ ../../libutils/logging.c ../../libutils/atexit.c \ $(am__append_1) libdb_la_LIBADD = libstr.la ../../libutils/libutils.la #libdb_la_CPPFLAGS = $(LMDB_CPPFLAGS) $(TOKYOCABINET_CPPFLAGS) $(QDBM_CPPFLAGS) # Make sure that source files are compiled to separate object files libdb_la-file.o libdb_la_CFLAGS = $(AM_CFLAGS) check_SCRIPTS = dynamic_dependency_test.sh TESTS = $(check_PROGRAMS) $(check_SCRIPTS) # # OS X uses real system calls instead of our stubs unless this option is used # TESTS_ENVIRONMENT = DYLD_FORCE_FLAT_NAMESPACE=yes atexit_test_SOURCES = atexit_test.c atexit_test_LDADD = libtest.la libdb.la csv_writer_test_SOURCES = csv_writer_test.c ../../libutils/csv_writer.c csv_writer_test_LDADD = libtest.la libstr.la conversion_test_SOURCES = conversion_test.c ../../libpromises/conversion.c @BUILTIN_EXTENSIONS_FALSE@enterprise_extension_test_SOURCES = enterprise_extension_test.c @BUILTIN_EXTENSIONS_FALSE@cfengine_enterprise_la_SOURCES = enterprise_extension_test_lib.c @BUILTIN_EXTENSIONS_FALSE@cfengine_enterprise_la_LDFLAGS = $(AM_LDFLAGS) \ @BUILTIN_EXTENSIONS_FALSE@ -avoid-version -module -shared -export-dynamic -rpath / @BUILTIN_EXTENSIONS_FALSE@EXTRA_enterprise_extension_test_DEPENDENCIES = cfengine-enterprise.la set_domainname_test_SOURCES = set_domainname_test.c set_domainname_test_LDADD = libstr.la ../../libpromises/libpromises.la str_test_SOURCES = str_test.c str_test_LDADD = libstr.la xml_writer_test_SOURCES = xml_writer_test.c ../../libutils/xml_writer.c xml_writer_test_LDADD = libtest.la libstr.la list_test_SOURCES = list_test.c refcount_test_SOURCES = refcount_test.c ../../libutils/refcount.c buffer_test_SOURCES = buffer_test.c ../../libutils/buffer.c csv_parser_test_SOURCES = csv_parser_test.c ../../libutils/csv_parser.c csv_parser_test_LDADD = libtest.la ../../libutils/libutils.la regex_test_SOURCES = regex_test.c ../../cf-agent/match_scope.c cf_key_functions_test_SOURCES = cf_key_functions_test.c ../../cf-key/cf-key-functions.c ipaddress_test_SOURCES = ipaddress_test.c protocol_test_SOURCES = protocol_test.c \ ../../cf-serverd/server_common.c \ ../../cf-serverd/server_tls.c \ ../../cf-serverd/server.c \ ../../cf-serverd/cf-serverd-enterprise-stubs.c \ ../../cf-serverd/server_transform.c \ ../../cf-serverd/cf-serverd-functions.c \ ../../cf-serverd/server_access.c \ ../../cf-serverd/strlist.c protocol_test_LDADD = ../../libpromises/libpromises.la libtest.la @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@findhub_test_SOURCES = findhub_test.c ../../cf-agent/findhub.c ../../cf-agent/load_avahi.c @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@avahi_config_test_SOURCES = avahi_config_test.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/server_common.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/server_tls.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/server.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/server_transform.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/cf-serverd-enterprise-stubs.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/server_access.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/server_classic.c \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ ../../cf-serverd/strlist.c @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@avahi_config_test_LDADD = ../../libpromises/libpromises.la libtest.la #file_writer_test_CPPFLAGS = -I$(top_srcdir)/libutils file_writer_test_SOURCES = file_writer_test.c gcov-stub.c db_test_SOURCES = db_test.c db_test_LDADD = libdb.la db_concurrent_test_SOURCES = db_concurrent_test.c #db_concurrent_test_CPPFLAGS = $(libdb_la_CPPFLAGS) db_concurrent_test_LDADD = libdb.la lastseen_test_SOURCES = lastseen_test.c \ ../../libpromises/item_lib.c ../../libpromises/lastseen.c ../../libutils/statistics.c #lastseen_test_CPPFLAGS = $(libdb_la_CPPFLAGS) lastseen_test_LDADD = libdb.la ../../libpromises/libpromises.la lastseen_migration_test_SOURCES = lastseen_migration_test.c \ ../../libpromises/lastseen.c ../../libutils/statistics.c ../../libpromises/item_lib.c #lastseen_migration_test_CPPFLAGS = $(libdb_la_CPPFLAGS) lastseen_migration_test_LDADD = libdb.la ../../libpromises/libpromises.la dbm_migration_bundles_test_SOURCES = dbm_migration_bundles_test.c dbm_migration_bundles_test_LDADD = libdb.la #dbm_migration_bundles_test_CPPFLAGS = $(libdb_la_CPPFLAGS) CLEANFILES = *.gcno *.gcda cfengine-enterprise.so package_versions_compare_test_SOURCES = package_versions_compare_test.c ../../cf-agent/verify_packages.c ../../cf-agent/vercmp.c ../../cf-agent/vercmp_internal.c ../../cf-agent/retcode.c ../../cf-agent/match_scope.c #package_versions_compare_test_CPPFLAGS = $(AM_CPPFLAGS) package_versions_compare_test_LDADD = ../../libpromises/libpromises.la libtest.la file_lib_test_SOURCES = file_lib_test.c \ ../../libutils/file_lib.c \ ../../libutils/logging.c \ ../../libutils/misc_lib.c \ ../../libutils/string_lib.c \ ../../libutils/sequence.c \ ../../libutils/unix_dir.c \ ../../libutils/writer.c file_lib_test_LDADD = libtest.la file_lib_test_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_SYMLINK_ATOMICITY sort_test_SOURCES = sort_test.c sort_test_LDADD = libtest.la ../../libpromises/libpromises.la logging_test_SOURCES = logging_test.c ../../libpromises/syslog_client.c logging_test_LDADD = libtest.la ../../libutils/libutils.la logging_timestamp_test_SOURCES = logging_timestamp_test.c ../../libutils/logging.h logging_timestamp_test_LDADD = libtest.la ../../libutils/libutils.la connection_management_test_SOURCES = connection_management_test.c ../../cf-serverd/server_common.c ../../cf-serverd/server_tls.c connection_management_test_LDADD = ../../libpromises/libpromises.la libtest.la ../../cf-serverd/libcf-serverd.la rlist_test_SOURCES = rlist_test.c \ ../../libpromises/rlist.c ../../libutils/logging.c rlist_test_LDADD = libtest.la libstr.la ../../libpromises/libpromises.la @LINUX_TRUE@linux_process_test_SOURCES = linux_process_test.c \ @LINUX_TRUE@ ../../libpromises/process_unix.c \ @LINUX_TRUE@ ../../libpromises/process_linux.c \ @LINUX_TRUE@ ../../libutils/file_lib.c @LINUX_TRUE@linux_process_test_LDADD = libtest.la ../../libutils/libutils.la @AIX_TRUE@aix_process_test_SOURCES = aix_process_test.c \ @AIX_TRUE@ ../../libpromises/process_unix.c \ @AIX_TRUE@ ../../libpromises/process_aix.c \ @AIX_TRUE@ ../../libutils/file_lib.c @AIX_TRUE@aix_process_test_LDADD = libtest.la ../../libutils/libutils.la @SOLARIS_TRUE@solaris_process_test_SOURCES = solaris_process_test.c \ @SOLARIS_TRUE@ ../../libpromises/process_unix.c \ @SOLARIS_TRUE@ ../../libpromises/process_solaris.c \ @SOLARIS_TRUE@ ../../libutils/file_lib.c @SOLARIS_TRUE@solaris_process_test_LDADD = libtest.la ../../libutils/libutils.la process_terminate_unix_test_SOURCES = process_terminate_unix_test.c \ ../../libpromises/process_unix.c process_terminate_unix_test_LDADD = libtest.la ../../libutils/libutils.la exec_config_test_SOURCES = exec-config-test.c \ ../../cf-execd/exec-config.c ../../cf-execd/execd-config.c exec_config_test_LDADD = libtest.la ../../libpromises/libpromises.la sysinfo_test_LDADD = libtest.la \ ../../libenv/libenv.la \ ../../libpromises/libpromises.la mon_cpu_test_SOURCES = mon_cpu_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_cpu.c mon_cpu_test_LDADD = ../../libpromises/libpromises.la libtest.la mon_load_test_SOURCES = mon_load_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_load.c mon_load_test_LDADD = ../../libpromises/libpromises.la libtest.la mon_processes_test_SOURCES = mon_processes_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_processes.c mon_processes_test_LDADD = ../../libpromises/libpromises.la libtest.la @XNU_FALSE@tls_generic_test_SOURCES = tls_generic_test.c @XNU_FALSE@tls_generic_test_LDADD = libtest.la \ @XNU_FALSE@ ../../libutils/libutils.la \ @XNU_FALSE@ ../../libpromises/libpromises.la \ @XNU_FALSE@ ../../libcfnet/libcfnet.la \ @XNU_FALSE@ ../../cf-serverd/libcf-serverd.la version_test_SOURCES = version_test.c hash_test_SOURCES = hash_test.c hash_test_LDADD = ../../libutils/libutils.la libtest.la key_test_SOURCES = key_test.c key_test_LDADD = ../../libpromises/libpromises.la ../../libutils/libutils.la libtest.la strlist_test_SOURCES = strlist_test.c ../../cf-serverd/strlist.c ../../cf-serverd/strlist.h libcompat_test_CPPFLAGS = -I$(top_srcdir)/libcompat libcompat_test_SOURCES = libcompat_test.c CFUPGRADE = ../../cf-upgrade cf_upgrade_test_SOURCES = cf_upgrade_test.c $(CFUPGRADE)/alloc-mini.c $(CFUPGRADE)/alloc-mini.h $(CFUPGRADE)/command_line.c \ $(CFUPGRADE)/command_line.h $(CFUPGRADE)/configuration.c $(CFUPGRADE)/configuration.h $(CFUPGRADE)/log.c $(CFUPGRADE)/log.h \ $(CFUPGRADE)/process.c $(CFUPGRADE)/process.h $(CFUPGRADE)/update.c $(CFUPGRADE)/update.h cf_upgrade_test_CFLAGS = -I$(CFUPGRADE) queue_test_SOURCES = queue_test.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(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) --foreign tests/unit/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/unit/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-checkLTLIBRARIES: -test -z "$(check_LTLIBRARIES)" || rm -f $(check_LTLIBRARIES) @list='$(check_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}; \ } cfengine-enterprise.la: $(cfengine_enterprise_la_OBJECTS) $(cfengine_enterprise_la_DEPENDENCIES) $(EXTRA_cfengine_enterprise_la_DEPENDENCIES) $(AM_V_CCLD)$(cfengine_enterprise_la_LINK) $(am_cfengine_enterprise_la_rpath) $(cfengine_enterprise_la_OBJECTS) $(cfengine_enterprise_la_LIBADD) $(LIBS) libdb.la: $(libdb_la_OBJECTS) $(libdb_la_DEPENDENCIES) $(EXTRA_libdb_la_DEPENDENCIES) $(AM_V_CCLD)$(libdb_la_LINK) $(libdb_la_OBJECTS) $(libdb_la_LIBADD) $(LIBS) libstr.la: $(libstr_la_OBJECTS) $(libstr_la_DEPENDENCIES) $(EXTRA_libstr_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libstr_la_OBJECTS) $(libstr_la_LIBADD) $(LIBS) libtest.la: $(libtest_la_OBJECTS) $(libtest_la_DEPENDENCIES) $(EXTRA_libtest_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtest_la_OBJECTS) $(libtest_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list addr_lib_test$(EXEEXT): $(addr_lib_test_OBJECTS) $(addr_lib_test_DEPENDENCIES) $(EXTRA_addr_lib_test_DEPENDENCIES) @rm -f addr_lib_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(addr_lib_test_OBJECTS) $(addr_lib_test_LDADD) $(LIBS) aix_process_test$(EXEEXT): $(aix_process_test_OBJECTS) $(aix_process_test_DEPENDENCIES) $(EXTRA_aix_process_test_DEPENDENCIES) @rm -f aix_process_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(aix_process_test_OBJECTS) $(aix_process_test_LDADD) $(LIBS) alloc_test$(EXEEXT): $(alloc_test_OBJECTS) $(alloc_test_DEPENDENCIES) $(EXTRA_alloc_test_DEPENDENCIES) @rm -f alloc_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(alloc_test_OBJECTS) $(alloc_test_LDADD) $(LIBS) arg_split_test$(EXEEXT): $(arg_split_test_OBJECTS) $(arg_split_test_DEPENDENCIES) $(EXTRA_arg_split_test_DEPENDENCIES) @rm -f arg_split_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(arg_split_test_OBJECTS) $(arg_split_test_LDADD) $(LIBS) assoc_test$(EXEEXT): $(assoc_test_OBJECTS) $(assoc_test_DEPENDENCIES) $(EXTRA_assoc_test_DEPENDENCIES) @rm -f assoc_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(assoc_test_OBJECTS) $(assoc_test_LDADD) $(LIBS) atexit_test$(EXEEXT): $(atexit_test_OBJECTS) $(atexit_test_DEPENDENCIES) $(EXTRA_atexit_test_DEPENDENCIES) @rm -f atexit_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(atexit_test_OBJECTS) $(atexit_test_LDADD) $(LIBS) avahi_config_test$(EXEEXT): $(avahi_config_test_OBJECTS) $(avahi_config_test_DEPENDENCIES) $(EXTRA_avahi_config_test_DEPENDENCIES) @rm -f avahi_config_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(avahi_config_test_OBJECTS) $(avahi_config_test_LDADD) $(LIBS) buffer_test$(EXEEXT): $(buffer_test_OBJECTS) $(buffer_test_DEPENDENCIES) $(EXTRA_buffer_test_DEPENDENCIES) @rm -f buffer_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(buffer_test_OBJECTS) $(buffer_test_LDADD) $(LIBS) cf_key_functions_test$(EXEEXT): $(cf_key_functions_test_OBJECTS) $(cf_key_functions_test_DEPENDENCIES) $(EXTRA_cf_key_functions_test_DEPENDENCIES) @rm -f cf_key_functions_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(cf_key_functions_test_OBJECTS) $(cf_key_functions_test_LDADD) $(LIBS) cf_upgrade_test$(EXEEXT): $(cf_upgrade_test_OBJECTS) $(cf_upgrade_test_DEPENDENCIES) $(EXTRA_cf_upgrade_test_DEPENDENCIES) @rm -f cf_upgrade_test$(EXEEXT) $(AM_V_CCLD)$(cf_upgrade_test_LINK) $(cf_upgrade_test_OBJECTS) $(cf_upgrade_test_LDADD) $(LIBS) changes_migration_test$(EXEEXT): $(changes_migration_test_OBJECTS) $(changes_migration_test_DEPENDENCIES) $(EXTRA_changes_migration_test_DEPENDENCIES) @rm -f changes_migration_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(changes_migration_test_OBJECTS) $(changes_migration_test_LDADD) $(LIBS) class_test$(EXEEXT): $(class_test_OBJECTS) $(class_test_DEPENDENCIES) $(EXTRA_class_test_DEPENDENCIES) @rm -f class_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(class_test_OBJECTS) $(class_test_LDADD) $(LIBS) connection_management_test$(EXEEXT): $(connection_management_test_OBJECTS) $(connection_management_test_DEPENDENCIES) $(EXTRA_connection_management_test_DEPENDENCIES) @rm -f connection_management_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(connection_management_test_OBJECTS) $(connection_management_test_LDADD) $(LIBS) conversion_test$(EXEEXT): $(conversion_test_OBJECTS) $(conversion_test_DEPENDENCIES) $(EXTRA_conversion_test_DEPENDENCIES) @rm -f conversion_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(conversion_test_OBJECTS) $(conversion_test_LDADD) $(LIBS) crypto_symmetric_test$(EXEEXT): $(crypto_symmetric_test_OBJECTS) $(crypto_symmetric_test_DEPENDENCIES) $(EXTRA_crypto_symmetric_test_DEPENDENCIES) @rm -f crypto_symmetric_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(crypto_symmetric_test_OBJECTS) $(crypto_symmetric_test_LDADD) $(LIBS) csv_parser_test$(EXEEXT): $(csv_parser_test_OBJECTS) $(csv_parser_test_DEPENDENCIES) $(EXTRA_csv_parser_test_DEPENDENCIES) @rm -f csv_parser_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(csv_parser_test_OBJECTS) $(csv_parser_test_LDADD) $(LIBS) csv_writer_test$(EXEEXT): $(csv_writer_test_OBJECTS) $(csv_writer_test_DEPENDENCIES) $(EXTRA_csv_writer_test_DEPENDENCIES) @rm -f csv_writer_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(csv_writer_test_OBJECTS) $(csv_writer_test_LDADD) $(LIBS) db_concurrent_test$(EXEEXT): $(db_concurrent_test_OBJECTS) $(db_concurrent_test_DEPENDENCIES) $(EXTRA_db_concurrent_test_DEPENDENCIES) @rm -f db_concurrent_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(db_concurrent_test_OBJECTS) $(db_concurrent_test_LDADD) $(LIBS) db_test$(EXEEXT): $(db_test_OBJECTS) $(db_test_DEPENDENCIES) $(EXTRA_db_test_DEPENDENCIES) @rm -f db_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(db_test_OBJECTS) $(db_test_LDADD) $(LIBS) dbm_migration_bundles_test$(EXEEXT): $(dbm_migration_bundles_test_OBJECTS) $(dbm_migration_bundles_test_DEPENDENCIES) $(EXTRA_dbm_migration_bundles_test_DEPENDENCIES) @rm -f dbm_migration_bundles_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(dbm_migration_bundles_test_OBJECTS) $(dbm_migration_bundles_test_LDADD) $(LIBS) domainname_test$(EXEEXT): $(domainname_test_OBJECTS) $(domainname_test_DEPENDENCIES) $(EXTRA_domainname_test_DEPENDENCIES) @rm -f domainname_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(domainname_test_OBJECTS) $(domainname_test_LDADD) $(LIBS) enterprise_extension_test$(EXEEXT): $(enterprise_extension_test_OBJECTS) $(enterprise_extension_test_DEPENDENCIES) $(EXTRA_enterprise_extension_test_DEPENDENCIES) @rm -f enterprise_extension_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(enterprise_extension_test_OBJECTS) $(enterprise_extension_test_LDADD) $(LIBS) eval_context_test$(EXEEXT): $(eval_context_test_OBJECTS) $(eval_context_test_DEPENDENCIES) $(EXTRA_eval_context_test_DEPENDENCIES) @rm -f eval_context_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(eval_context_test_OBJECTS) $(eval_context_test_LDADD) $(LIBS) evalfunction_test$(EXEEXT): $(evalfunction_test_OBJECTS) $(evalfunction_test_DEPENDENCIES) $(EXTRA_evalfunction_test_DEPENDENCIES) @rm -f evalfunction_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(evalfunction_test_OBJECTS) $(evalfunction_test_LDADD) $(LIBS) exec-config-test$(EXEEXT): $(exec_config_test_OBJECTS) $(exec_config_test_DEPENDENCIES) $(EXTRA_exec_config_test_DEPENDENCIES) @rm -f exec-config-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(exec_config_test_OBJECTS) $(exec_config_test_LDADD) $(LIBS) expand_test$(EXEEXT): $(expand_test_OBJECTS) $(expand_test_DEPENDENCIES) $(EXTRA_expand_test_DEPENDENCIES) @rm -f expand_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(expand_test_OBJECTS) $(expand_test_LDADD) $(LIBS) file_lib_test$(EXEEXT): $(file_lib_test_OBJECTS) $(file_lib_test_DEPENDENCIES) $(EXTRA_file_lib_test_DEPENDENCIES) @rm -f file_lib_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(file_lib_test_OBJECTS) $(file_lib_test_LDADD) $(LIBS) file_name_test$(EXEEXT): $(file_name_test_OBJECTS) $(file_name_test_DEPENDENCIES) $(EXTRA_file_name_test_DEPENDENCIES) @rm -f file_name_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(file_name_test_OBJECTS) $(file_name_test_LDADD) $(LIBS) file_writer_test$(EXEEXT): $(file_writer_test_OBJECTS) $(file_writer_test_DEPENDENCIES) $(EXTRA_file_writer_test_DEPENDENCIES) @rm -f file_writer_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(file_writer_test_OBJECTS) $(file_writer_test_LDADD) $(LIBS) files_interfaces_test$(EXEEXT): $(files_interfaces_test_OBJECTS) $(files_interfaces_test_DEPENDENCIES) $(EXTRA_files_interfaces_test_DEPENDENCIES) @rm -f files_interfaces_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(files_interfaces_test_OBJECTS) $(files_interfaces_test_LDADD) $(LIBS) files_lib_test$(EXEEXT): $(files_lib_test_OBJECTS) $(files_lib_test_DEPENDENCIES) $(EXTRA_files_lib_test_DEPENDENCIES) @rm -f files_lib_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(files_lib_test_OBJECTS) $(files_lib_test_LDADD) $(LIBS) findhub_test$(EXEEXT): $(findhub_test_OBJECTS) $(findhub_test_DEPENDENCIES) $(EXTRA_findhub_test_DEPENDENCIES) @rm -f findhub_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(findhub_test_OBJECTS) $(findhub_test_LDADD) $(LIBS) generic_agent_test$(EXEEXT): $(generic_agent_test_OBJECTS) $(generic_agent_test_DEPENDENCIES) $(EXTRA_generic_agent_test_DEPENDENCIES) @rm -f generic_agent_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(generic_agent_test_OBJECTS) $(generic_agent_test_LDADD) $(LIBS) granules_test$(EXEEXT): $(granules_test_OBJECTS) $(granules_test_DEPENDENCIES) $(EXTRA_granules_test_DEPENDENCIES) @rm -f granules_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(granules_test_OBJECTS) $(granules_test_LDADD) $(LIBS) hash_test$(EXEEXT): $(hash_test_OBJECTS) $(hash_test_DEPENDENCIES) $(EXTRA_hash_test_DEPENDENCIES) @rm -f hash_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(hash_test_OBJECTS) $(hash_test_LDADD) $(LIBS) hashes_test$(EXEEXT): $(hashes_test_OBJECTS) $(hashes_test_DEPENDENCIES) $(EXTRA_hashes_test_DEPENDENCIES) @rm -f hashes_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(hashes_test_OBJECTS) $(hashes_test_LDADD) $(LIBS) ipaddress_test$(EXEEXT): $(ipaddress_test_OBJECTS) $(ipaddress_test_DEPENDENCIES) $(EXTRA_ipaddress_test_DEPENDENCIES) @rm -f ipaddress_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ipaddress_test_OBJECTS) $(ipaddress_test_LDADD) $(LIBS) item_lib_test$(EXEEXT): $(item_lib_test_OBJECTS) $(item_lib_test_DEPENDENCIES) $(EXTRA_item_lib_test_DEPENDENCIES) @rm -f item_lib_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(item_lib_test_OBJECTS) $(item_lib_test_LDADD) $(LIBS) item_test$(EXEEXT): $(item_test_OBJECTS) $(item_test_DEPENDENCIES) $(EXTRA_item_test_DEPENDENCIES) @rm -f item_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(item_test_OBJECTS) $(item_test_LDADD) $(LIBS) json_test$(EXEEXT): $(json_test_OBJECTS) $(json_test_DEPENDENCIES) $(EXTRA_json_test_DEPENDENCIES) @rm -f json_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(json_test_OBJECTS) $(json_test_LDADD) $(LIBS) key_test$(EXEEXT): $(key_test_OBJECTS) $(key_test_DEPENDENCIES) $(EXTRA_key_test_DEPENDENCIES) @rm -f key_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(key_test_OBJECTS) $(key_test_LDADD) $(LIBS) lastseen_migration_test$(EXEEXT): $(lastseen_migration_test_OBJECTS) $(lastseen_migration_test_DEPENDENCIES) $(EXTRA_lastseen_migration_test_DEPENDENCIES) @rm -f lastseen_migration_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lastseen_migration_test_OBJECTS) $(lastseen_migration_test_LDADD) $(LIBS) lastseen_test$(EXEEXT): $(lastseen_test_OBJECTS) $(lastseen_test_DEPENDENCIES) $(EXTRA_lastseen_test_DEPENDENCIES) @rm -f lastseen_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lastseen_test_OBJECTS) $(lastseen_test_LDADD) $(LIBS) libcompat_test$(EXEEXT): $(libcompat_test_OBJECTS) $(libcompat_test_DEPENDENCIES) $(EXTRA_libcompat_test_DEPENDENCIES) @rm -f libcompat_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(libcompat_test_OBJECTS) $(libcompat_test_LDADD) $(LIBS) linux_process_test$(EXEEXT): $(linux_process_test_OBJECTS) $(linux_process_test_DEPENDENCIES) $(EXTRA_linux_process_test_DEPENDENCIES) @rm -f linux_process_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(linux_process_test_OBJECTS) $(linux_process_test_LDADD) $(LIBS) list_test$(EXEEXT): $(list_test_OBJECTS) $(list_test_DEPENDENCIES) $(EXTRA_list_test_DEPENDENCIES) @rm -f list_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(list_test_OBJECTS) $(list_test_LDADD) $(LIBS) logging_test$(EXEEXT): $(logging_test_OBJECTS) $(logging_test_DEPENDENCIES) $(EXTRA_logging_test_DEPENDENCIES) @rm -f logging_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(logging_test_OBJECTS) $(logging_test_LDADD) $(LIBS) logging_timestamp_test$(EXEEXT): $(logging_timestamp_test_OBJECTS) $(logging_timestamp_test_DEPENDENCIES) $(EXTRA_logging_timestamp_test_DEPENDENCIES) @rm -f logging_timestamp_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(logging_timestamp_test_OBJECTS) $(logging_timestamp_test_LDADD) $(LIBS) map_test$(EXEEXT): $(map_test_OBJECTS) $(map_test_DEPENDENCIES) $(EXTRA_map_test_DEPENDENCIES) @rm -f map_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(map_test_OBJECTS) $(map_test_LDADD) $(LIBS) matching_test$(EXEEXT): $(matching_test_OBJECTS) $(matching_test_DEPENDENCIES) $(EXTRA_matching_test_DEPENDENCIES) @rm -f matching_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(matching_test_OBJECTS) $(matching_test_LDADD) $(LIBS) misc_lib_test$(EXEEXT): $(misc_lib_test_OBJECTS) $(misc_lib_test_DEPENDENCIES) $(EXTRA_misc_lib_test_DEPENDENCIES) @rm -f misc_lib_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(misc_lib_test_OBJECTS) $(misc_lib_test_LDADD) $(LIBS) mon_cpu_test$(EXEEXT): $(mon_cpu_test_OBJECTS) $(mon_cpu_test_DEPENDENCIES) $(EXTRA_mon_cpu_test_DEPENDENCIES) @rm -f mon_cpu_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mon_cpu_test_OBJECTS) $(mon_cpu_test_LDADD) $(LIBS) mon_load_test$(EXEEXT): $(mon_load_test_OBJECTS) $(mon_load_test_DEPENDENCIES) $(EXTRA_mon_load_test_DEPENDENCIES) @rm -f mon_load_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mon_load_test_OBJECTS) $(mon_load_test_LDADD) $(LIBS) mon_processes_test$(EXEEXT): $(mon_processes_test_OBJECTS) $(mon_processes_test_DEPENDENCIES) $(EXTRA_mon_processes_test_DEPENDENCIES) @rm -f mon_processes_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mon_processes_test_OBJECTS) $(mon_processes_test_LDADD) $(LIBS) mustache_test$(EXEEXT): $(mustache_test_OBJECTS) $(mustache_test_DEPENDENCIES) $(EXTRA_mustache_test_DEPENDENCIES) @rm -f mustache_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mustache_test_OBJECTS) $(mustache_test_LDADD) $(LIBS) package_versions_compare_test$(EXEEXT): $(package_versions_compare_test_OBJECTS) $(package_versions_compare_test_DEPENDENCIES) $(EXTRA_package_versions_compare_test_DEPENDENCIES) @rm -f package_versions_compare_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(package_versions_compare_test_OBJECTS) $(package_versions_compare_test_LDADD) $(LIBS) parsemode_test$(EXEEXT): $(parsemode_test_OBJECTS) $(parsemode_test_DEPENDENCIES) $(EXTRA_parsemode_test_DEPENDENCIES) @rm -f parsemode_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(parsemode_test_OBJECTS) $(parsemode_test_LDADD) $(LIBS) parser_test$(EXEEXT): $(parser_test_OBJECTS) $(parser_test_DEPENDENCIES) $(EXTRA_parser_test_DEPENDENCIES) @rm -f parser_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(parser_test_OBJECTS) $(parser_test_LDADD) $(LIBS) persistent_lock_test$(EXEEXT): $(persistent_lock_test_OBJECTS) $(persistent_lock_test_DEPENDENCIES) $(EXTRA_persistent_lock_test_DEPENDENCIES) @rm -f persistent_lock_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(persistent_lock_test_OBJECTS) $(persistent_lock_test_LDADD) $(LIBS) policy_test$(EXEEXT): $(policy_test_OBJECTS) $(policy_test_DEPENDENCIES) $(EXTRA_policy_test_DEPENDENCIES) @rm -f policy_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(policy_test_OBJECTS) $(policy_test_LDADD) $(LIBS) process_terminate_unix_test$(EXEEXT): $(process_terminate_unix_test_OBJECTS) $(process_terminate_unix_test_DEPENDENCIES) $(EXTRA_process_terminate_unix_test_DEPENDENCIES) @rm -f process_terminate_unix_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(process_terminate_unix_test_OBJECTS) $(process_terminate_unix_test_LDADD) $(LIBS) protocol_test$(EXEEXT): $(protocol_test_OBJECTS) $(protocol_test_DEPENDENCIES) $(EXTRA_protocol_test_DEPENDENCIES) @rm -f protocol_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(protocol_test_OBJECTS) $(protocol_test_LDADD) $(LIBS) queue_test$(EXEEXT): $(queue_test_OBJECTS) $(queue_test_DEPENDENCIES) $(EXTRA_queue_test_DEPENDENCIES) @rm -f queue_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(queue_test_OBJECTS) $(queue_test_LDADD) $(LIBS) rb-tree-test$(EXEEXT): $(rb_tree_test_OBJECTS) $(rb_tree_test_DEPENDENCIES) $(EXTRA_rb_tree_test_DEPENDENCIES) @rm -f rb-tree-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(rb_tree_test_OBJECTS) $(rb_tree_test_LDADD) $(LIBS) refcount_test$(EXEEXT): $(refcount_test_OBJECTS) $(refcount_test_DEPENDENCIES) $(EXTRA_refcount_test_DEPENDENCIES) @rm -f refcount_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(refcount_test_OBJECTS) $(refcount_test_LDADD) $(LIBS) regex_test$(EXEEXT): $(regex_test_OBJECTS) $(regex_test_DEPENDENCIES) $(EXTRA_regex_test_DEPENDENCIES) @rm -f regex_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(regex_test_OBJECTS) $(regex_test_LDADD) $(LIBS) ring_buffer_test$(EXEEXT): $(ring_buffer_test_OBJECTS) $(ring_buffer_test_DEPENDENCIES) $(EXTRA_ring_buffer_test_DEPENDENCIES) @rm -f ring_buffer_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ring_buffer_test_OBJECTS) $(ring_buffer_test_LDADD) $(LIBS) rlist_test$(EXEEXT): $(rlist_test_OBJECTS) $(rlist_test_DEPENDENCIES) $(EXTRA_rlist_test_DEPENDENCIES) @rm -f rlist_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(rlist_test_OBJECTS) $(rlist_test_LDADD) $(LIBS) scope_test$(EXEEXT): $(scope_test_OBJECTS) $(scope_test_DEPENDENCIES) $(EXTRA_scope_test_DEPENDENCIES) @rm -f scope_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(scope_test_OBJECTS) $(scope_test_LDADD) $(LIBS) sequence_test$(EXEEXT): $(sequence_test_OBJECTS) $(sequence_test_DEPENDENCIES) $(EXTRA_sequence_test_DEPENDENCIES) @rm -f sequence_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sequence_test_OBJECTS) $(sequence_test_LDADD) $(LIBS) set_domainname_test$(EXEEXT): $(set_domainname_test_OBJECTS) $(set_domainname_test_DEPENDENCIES) $(EXTRA_set_domainname_test_DEPENDENCIES) @rm -f set_domainname_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(set_domainname_test_OBJECTS) $(set_domainname_test_LDADD) $(LIBS) set_test$(EXEEXT): $(set_test_OBJECTS) $(set_test_DEPENDENCIES) $(EXTRA_set_test_DEPENDENCIES) @rm -f set_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(set_test_OBJECTS) $(set_test_LDADD) $(LIBS) solaris_process_test$(EXEEXT): $(solaris_process_test_OBJECTS) $(solaris_process_test_DEPENDENCIES) $(EXTRA_solaris_process_test_DEPENDENCIES) @rm -f solaris_process_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(solaris_process_test_OBJECTS) $(solaris_process_test_LDADD) $(LIBS) sort_test$(EXEEXT): $(sort_test_OBJECTS) $(sort_test_DEPENDENCIES) $(EXTRA_sort_test_DEPENDENCIES) @rm -f sort_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sort_test_OBJECTS) $(sort_test_LDADD) $(LIBS) str_test$(EXEEXT): $(str_test_OBJECTS) $(str_test_DEPENDENCIES) $(EXTRA_str_test_DEPENDENCIES) @rm -f str_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(str_test_OBJECTS) $(str_test_LDADD) $(LIBS) string_expressions_test$(EXEEXT): $(string_expressions_test_OBJECTS) $(string_expressions_test_DEPENDENCIES) $(EXTRA_string_expressions_test_DEPENDENCIES) @rm -f string_expressions_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(string_expressions_test_OBJECTS) $(string_expressions_test_LDADD) $(LIBS) string_writer_test$(EXEEXT): $(string_writer_test_OBJECTS) $(string_writer_test_DEPENDENCIES) $(EXTRA_string_writer_test_DEPENDENCIES) @rm -f string_writer_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(string_writer_test_OBJECTS) $(string_writer_test_LDADD) $(LIBS) strlist_test$(EXEEXT): $(strlist_test_OBJECTS) $(strlist_test_DEPENDENCIES) $(EXTRA_strlist_test_DEPENDENCIES) @rm -f strlist_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(strlist_test_OBJECTS) $(strlist_test_LDADD) $(LIBS) syntax_test$(EXEEXT): $(syntax_test_OBJECTS) $(syntax_test_DEPENDENCIES) $(EXTRA_syntax_test_DEPENDENCIES) @rm -f syntax_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(syntax_test_OBJECTS) $(syntax_test_LDADD) $(LIBS) sysinfo_test$(EXEEXT): $(sysinfo_test_OBJECTS) $(sysinfo_test_DEPENDENCIES) $(EXTRA_sysinfo_test_DEPENDENCIES) @rm -f sysinfo_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(sysinfo_test_OBJECTS) $(sysinfo_test_LDADD) $(LIBS) thread_test$(EXEEXT): $(thread_test_OBJECTS) $(thread_test_DEPENDENCIES) $(EXTRA_thread_test_DEPENDENCIES) @rm -f thread_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(thread_test_OBJECTS) $(thread_test_LDADD) $(LIBS) tls_generic_test$(EXEEXT): $(tls_generic_test_OBJECTS) $(tls_generic_test_DEPENDENCIES) $(EXTRA_tls_generic_test_DEPENDENCIES) @rm -f tls_generic_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tls_generic_test_OBJECTS) $(tls_generic_test_LDADD) $(LIBS) var_expressions_test$(EXEEXT): $(var_expressions_test_OBJECTS) $(var_expressions_test_DEPENDENCIES) $(EXTRA_var_expressions_test_DEPENDENCIES) @rm -f var_expressions_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(var_expressions_test_OBJECTS) $(var_expressions_test_LDADD) $(LIBS) variable_test$(EXEEXT): $(variable_test_OBJECTS) $(variable_test_DEPENDENCIES) $(EXTRA_variable_test_DEPENDENCIES) @rm -f variable_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(variable_test_OBJECTS) $(variable_test_LDADD) $(LIBS) version_test$(EXEEXT): $(version_test_OBJECTS) $(version_test_DEPENDENCIES) $(EXTRA_version_test_DEPENDENCIES) @rm -f version_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(version_test_OBJECTS) $(version_test_LDADD) $(LIBS) xml_writer_test$(EXEEXT): $(xml_writer_test_OBJECTS) $(xml_writer_test_DEPENDENCIES) $(EXTRA_xml_writer_test_DEPENDENCIES) @rm -f xml_writer_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(xml_writer_test_OBJECTS) $(xml_writer_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addr_lib_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aix_process_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arg_split_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array_map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assoc_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atexit_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/avahi_config_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-key-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-serverd-enterprise-stubs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-serverd-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_key_functions_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-alloc-mini.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-command_line.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-process.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_upgrade_test-update.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/changes_migration_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/class_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmockery.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection_management_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conversion.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conversion_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_symmetric_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_parser_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_writer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_writer_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_concurrent_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_migration_bundles_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/domainname_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enterprise_extension_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enterprise_extension_test_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval_context_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evalfunction_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec-config-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec-config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execd-config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expand_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-file_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-file_lib_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-logging.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-misc_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-sequence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-string_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-unix_dir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib_test-writer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_name_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_writer_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_interfaces_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_lib_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findhub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findhub_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcov-stub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic_agent_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/granules_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashes_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipaddress_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/item_lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/item_lib_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/item_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/known_dirs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen_migration_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcompat_test-libcompat_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-atexit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-cf3globals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_lmdb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_migration.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_migration_bundles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_migration_lastseen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_quick.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-dbm_tokyocab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libdb_la-mutex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linux_process_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_avahi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging_timestamp_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_scope.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matching_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc_lib_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_cpu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_cpu_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_load_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_processes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_processes_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mustache_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/package_versions_compare_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parsemode_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patches.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/persistent_lock_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policy_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_aix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_linux.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_solaris.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_terminate_unix_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_unix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rb-tree-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refcount.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refcount_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retcode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ring_buffer_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rlist_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scope_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sequence.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sequence_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_access.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_classic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_tls.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_transform.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_domainname_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/solaris_process_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sort_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistics.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_expressions_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_writer_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlist_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syntax_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysinfo_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_generic_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var_expressions_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/variable_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vercmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vercmp_internal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_packages.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/writer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_writer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_writer_test.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libdb_la-dbm_api.lo: ../../libpromises/dbm_api.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_api.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_api.Tpo -c -o libdb_la-dbm_api.lo `test -f '../../libpromises/dbm_api.c' || echo '$(srcdir)/'`../../libpromises/dbm_api.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_api.Tpo $(DEPDIR)/libdb_la-dbm_api.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_api.c' object='libdb_la-dbm_api.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_api.lo `test -f '../../libpromises/dbm_api.c' || echo '$(srcdir)/'`../../libpromises/dbm_api.c libdb_la-mutex.lo: ../../libpromises/mutex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-mutex.lo -MD -MP -MF $(DEPDIR)/libdb_la-mutex.Tpo -c -o libdb_la-mutex.lo `test -f '../../libpromises/mutex.c' || echo '$(srcdir)/'`../../libpromises/mutex.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-mutex.Tpo $(DEPDIR)/libdb_la-mutex.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/mutex.c' object='libdb_la-mutex.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-mutex.lo `test -f '../../libpromises/mutex.c' || echo '$(srcdir)/'`../../libpromises/mutex.c libdb_la-dbm_quick.lo: ../../libpromises/dbm_quick.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_quick.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_quick.Tpo -c -o libdb_la-dbm_quick.lo `test -f '../../libpromises/dbm_quick.c' || echo '$(srcdir)/'`../../libpromises/dbm_quick.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_quick.Tpo $(DEPDIR)/libdb_la-dbm_quick.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_quick.c' object='libdb_la-dbm_quick.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_quick.lo `test -f '../../libpromises/dbm_quick.c' || echo '$(srcdir)/'`../../libpromises/dbm_quick.c libdb_la-dbm_tokyocab.lo: ../../libpromises/dbm_tokyocab.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_tokyocab.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_tokyocab.Tpo -c -o libdb_la-dbm_tokyocab.lo `test -f '../../libpromises/dbm_tokyocab.c' || echo '$(srcdir)/'`../../libpromises/dbm_tokyocab.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_tokyocab.Tpo $(DEPDIR)/libdb_la-dbm_tokyocab.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_tokyocab.c' object='libdb_la-dbm_tokyocab.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_tokyocab.lo `test -f '../../libpromises/dbm_tokyocab.c' || echo '$(srcdir)/'`../../libpromises/dbm_tokyocab.c libdb_la-dbm_lmdb.lo: ../../libpromises/dbm_lmdb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_lmdb.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_lmdb.Tpo -c -o libdb_la-dbm_lmdb.lo `test -f '../../libpromises/dbm_lmdb.c' || echo '$(srcdir)/'`../../libpromises/dbm_lmdb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_lmdb.Tpo $(DEPDIR)/libdb_la-dbm_lmdb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_lmdb.c' object='libdb_la-dbm_lmdb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_lmdb.lo `test -f '../../libpromises/dbm_lmdb.c' || echo '$(srcdir)/'`../../libpromises/dbm_lmdb.c libdb_la-dbm_migration.lo: ../../libpromises/dbm_migration.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_migration.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_migration.Tpo -c -o libdb_la-dbm_migration.lo `test -f '../../libpromises/dbm_migration.c' || echo '$(srcdir)/'`../../libpromises/dbm_migration.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_migration.Tpo $(DEPDIR)/libdb_la-dbm_migration.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_migration.c' object='libdb_la-dbm_migration.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_migration.lo `test -f '../../libpromises/dbm_migration.c' || echo '$(srcdir)/'`../../libpromises/dbm_migration.c libdb_la-dbm_migration_lastseen.lo: ../../libpromises/dbm_migration_lastseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_migration_lastseen.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_migration_lastseen.Tpo -c -o libdb_la-dbm_migration_lastseen.lo `test -f '../../libpromises/dbm_migration_lastseen.c' || echo '$(srcdir)/'`../../libpromises/dbm_migration_lastseen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_migration_lastseen.Tpo $(DEPDIR)/libdb_la-dbm_migration_lastseen.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_migration_lastseen.c' object='libdb_la-dbm_migration_lastseen.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_migration_lastseen.lo `test -f '../../libpromises/dbm_migration_lastseen.c' || echo '$(srcdir)/'`../../libpromises/dbm_migration_lastseen.c libdb_la-dbm_migration_bundles.lo: ../../libpromises/dbm_migration_bundles.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-dbm_migration_bundles.lo -MD -MP -MF $(DEPDIR)/libdb_la-dbm_migration_bundles.Tpo -c -o libdb_la-dbm_migration_bundles.lo `test -f '../../libpromises/dbm_migration_bundles.c' || echo '$(srcdir)/'`../../libpromises/dbm_migration_bundles.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-dbm_migration_bundles.Tpo $(DEPDIR)/libdb_la-dbm_migration_bundles.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/dbm_migration_bundles.c' object='libdb_la-dbm_migration_bundles.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-dbm_migration_bundles.lo `test -f '../../libpromises/dbm_migration_bundles.c' || echo '$(srcdir)/'`../../libpromises/dbm_migration_bundles.c libdb_la-logging.lo: ../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-logging.lo -MD -MP -MF $(DEPDIR)/libdb_la-logging.Tpo -c -o libdb_la-logging.lo `test -f '../../libutils/logging.c' || echo '$(srcdir)/'`../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-logging.Tpo $(DEPDIR)/libdb_la-logging.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/logging.c' object='libdb_la-logging.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-logging.lo `test -f '../../libutils/logging.c' || echo '$(srcdir)/'`../../libutils/logging.c libdb_la-atexit.lo: ../../libutils/atexit.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-atexit.lo -MD -MP -MF $(DEPDIR)/libdb_la-atexit.Tpo -c -o libdb_la-atexit.lo `test -f '../../libutils/atexit.c' || echo '$(srcdir)/'`../../libutils/atexit.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-atexit.Tpo $(DEPDIR)/libdb_la-atexit.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/atexit.c' object='libdb_la-atexit.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-atexit.lo `test -f '../../libutils/atexit.c' || echo '$(srcdir)/'`../../libutils/atexit.c libdb_la-cf3globals.lo: ../../libpromises/cf3globals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -MT libdb_la-cf3globals.lo -MD -MP -MF $(DEPDIR)/libdb_la-cf3globals.Tpo -c -o libdb_la-cf3globals.lo `test -f '../../libpromises/cf3globals.c' || echo '$(srcdir)/'`../../libpromises/cf3globals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libdb_la-cf3globals.Tpo $(DEPDIR)/libdb_la-cf3globals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/cf3globals.c' object='libdb_la-cf3globals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdb_la_CFLAGS) $(CFLAGS) -c -o libdb_la-cf3globals.lo `test -f '../../libpromises/cf3globals.c' || echo '$(srcdir)/'`../../libpromises/cf3globals.c string_lib.lo: ../../libutils/string_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT string_lib.lo -MD -MP -MF $(DEPDIR)/string_lib.Tpo -c -o string_lib.lo `test -f '../../libutils/string_lib.c' || echo '$(srcdir)/'`../../libutils/string_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/string_lib.Tpo $(DEPDIR)/string_lib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/string_lib.c' object='string_lib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o string_lib.lo `test -f '../../libutils/string_lib.c' || echo '$(srcdir)/'`../../libutils/string_lib.c regex.lo: ../../libutils/regex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT regex.lo -MD -MP -MF $(DEPDIR)/regex.Tpo -c -o regex.lo `test -f '../../libutils/regex.c' || echo '$(srcdir)/'`../../libutils/regex.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/regex.Tpo $(DEPDIR)/regex.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/regex.c' object='regex.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o regex.lo `test -f '../../libutils/regex.c' || echo '$(srcdir)/'`../../libutils/regex.c encode.lo: ../../libutils/encode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encode.lo -MD -MP -MF $(DEPDIR)/encode.Tpo -c -o encode.lo `test -f '../../libutils/encode.c' || echo '$(srcdir)/'`../../libutils/encode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/encode.Tpo $(DEPDIR)/encode.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/encode.c' object='encode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encode.lo `test -f '../../libutils/encode.c' || echo '$(srcdir)/'`../../libutils/encode.c writer.lo: ../../libutils/writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT writer.lo -MD -MP -MF $(DEPDIR)/writer.Tpo -c -o writer.lo `test -f '../../libutils/writer.c' || echo '$(srcdir)/'`../../libutils/writer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/writer.Tpo $(DEPDIR)/writer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/writer.c' object='writer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o writer.lo `test -f '../../libutils/writer.c' || echo '$(srcdir)/'`../../libutils/writer.c sequence.lo: ../../libutils/sequence.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sequence.lo -MD -MP -MF $(DEPDIR)/sequence.Tpo -c -o sequence.lo `test -f '../../libutils/sequence.c' || echo '$(srcdir)/'`../../libutils/sequence.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/sequence.Tpo $(DEPDIR)/sequence.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/sequence.c' object='sequence.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sequence.lo `test -f '../../libutils/sequence.c' || echo '$(srcdir)/'`../../libutils/sequence.c alloc.lo: ../../libutils/alloc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT alloc.lo -MD -MP -MF $(DEPDIR)/alloc.Tpo -c -o alloc.lo `test -f '../../libutils/alloc.c' || echo '$(srcdir)/'`../../libutils/alloc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/alloc.Tpo $(DEPDIR)/alloc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/alloc.c' object='alloc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o alloc.lo `test -f '../../libutils/alloc.c' || echo '$(srcdir)/'`../../libutils/alloc.c patches.lo: ../../libpromises/patches.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT patches.lo -MD -MP -MF $(DEPDIR)/patches.Tpo -c -o patches.lo `test -f '../../libpromises/patches.c' || echo '$(srcdir)/'`../../libpromises/patches.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/patches.Tpo $(DEPDIR)/patches.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/patches.c' object='patches.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o patches.lo `test -f '../../libpromises/patches.c' || echo '$(srcdir)/'`../../libpromises/patches.c constants.lo: ../../libpromises/constants.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT constants.lo -MD -MP -MF $(DEPDIR)/constants.Tpo -c -o constants.lo `test -f '../../libpromises/constants.c' || echo '$(srcdir)/'`../../libpromises/constants.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/constants.Tpo $(DEPDIR)/constants.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/constants.c' object='constants.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o constants.lo `test -f '../../libpromises/constants.c' || echo '$(srcdir)/'`../../libpromises/constants.c known_dirs.lo: ../../libpromises/known_dirs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT known_dirs.lo -MD -MP -MF $(DEPDIR)/known_dirs.Tpo -c -o known_dirs.lo `test -f '../../libpromises/known_dirs.c' || echo '$(srcdir)/'`../../libpromises/known_dirs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/known_dirs.Tpo $(DEPDIR)/known_dirs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/known_dirs.c' object='known_dirs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o known_dirs.lo `test -f '../../libpromises/known_dirs.c' || echo '$(srcdir)/'`../../libpromises/known_dirs.c map.lo: ../../libutils/map.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT map.lo -MD -MP -MF $(DEPDIR)/map.Tpo -c -o map.lo `test -f '../../libutils/map.c' || echo '$(srcdir)/'`../../libutils/map.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/map.Tpo $(DEPDIR)/map.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/map.c' object='map.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o map.lo `test -f '../../libutils/map.c' || echo '$(srcdir)/'`../../libutils/map.c array_map.lo: ../../libutils/array_map.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT array_map.lo -MD -MP -MF $(DEPDIR)/array_map.Tpo -c -o array_map.lo `test -f '../../libutils/array_map.c' || echo '$(srcdir)/'`../../libutils/array_map.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/array_map.Tpo $(DEPDIR)/array_map.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/array_map.c' object='array_map.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o array_map.lo `test -f '../../libutils/array_map.c' || echo '$(srcdir)/'`../../libutils/array_map.c hash.lo: ../../libutils/hash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hash.lo -MD -MP -MF $(DEPDIR)/hash.Tpo -c -o hash.lo `test -f '../../libutils/hash.c' || echo '$(srcdir)/'`../../libutils/hash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hash.Tpo $(DEPDIR)/hash.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/hash.c' object='hash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hash.lo `test -f '../../libutils/hash.c' || echo '$(srcdir)/'`../../libutils/hash.c hash_map.lo: ../../libutils/hash_map.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hash_map.lo -MD -MP -MF $(DEPDIR)/hash_map.Tpo -c -o hash_map.lo `test -f '../../libutils/hash_map.c' || echo '$(srcdir)/'`../../libutils/hash_map.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hash_map.Tpo $(DEPDIR)/hash_map.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/hash_map.c' object='hash_map.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hash_map.lo `test -f '../../libutils/hash_map.c' || echo '$(srcdir)/'`../../libutils/hash_map.c process_unix.o: ../../libpromises/process_unix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_unix.o -MD -MP -MF $(DEPDIR)/process_unix.Tpo -c -o process_unix.o `test -f '../../libpromises/process_unix.c' || echo '$(srcdir)/'`../../libpromises/process_unix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_unix.Tpo $(DEPDIR)/process_unix.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_unix.c' object='process_unix.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_unix.o `test -f '../../libpromises/process_unix.c' || echo '$(srcdir)/'`../../libpromises/process_unix.c process_unix.obj: ../../libpromises/process_unix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_unix.obj -MD -MP -MF $(DEPDIR)/process_unix.Tpo -c -o process_unix.obj `if test -f '../../libpromises/process_unix.c'; then $(CYGPATH_W) '../../libpromises/process_unix.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_unix.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_unix.Tpo $(DEPDIR)/process_unix.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_unix.c' object='process_unix.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_unix.obj `if test -f '../../libpromises/process_unix.c'; then $(CYGPATH_W) '../../libpromises/process_unix.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_unix.c'; fi` process_aix.o: ../../libpromises/process_aix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_aix.o -MD -MP -MF $(DEPDIR)/process_aix.Tpo -c -o process_aix.o `test -f '../../libpromises/process_aix.c' || echo '$(srcdir)/'`../../libpromises/process_aix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_aix.Tpo $(DEPDIR)/process_aix.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_aix.c' object='process_aix.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_aix.o `test -f '../../libpromises/process_aix.c' || echo '$(srcdir)/'`../../libpromises/process_aix.c process_aix.obj: ../../libpromises/process_aix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_aix.obj -MD -MP -MF $(DEPDIR)/process_aix.Tpo -c -o process_aix.obj `if test -f '../../libpromises/process_aix.c'; then $(CYGPATH_W) '../../libpromises/process_aix.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_aix.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_aix.Tpo $(DEPDIR)/process_aix.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_aix.c' object='process_aix.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_aix.obj `if test -f '../../libpromises/process_aix.c'; then $(CYGPATH_W) '../../libpromises/process_aix.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_aix.c'; fi` file_lib.o: ../../libutils/file_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib.o -MD -MP -MF $(DEPDIR)/file_lib.Tpo -c -o file_lib.o `test -f '../../libutils/file_lib.c' || echo '$(srcdir)/'`../../libutils/file_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib.Tpo $(DEPDIR)/file_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/file_lib.c' object='file_lib.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib.o `test -f '../../libutils/file_lib.c' || echo '$(srcdir)/'`../../libutils/file_lib.c file_lib.obj: ../../libutils/file_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib.obj -MD -MP -MF $(DEPDIR)/file_lib.Tpo -c -o file_lib.obj `if test -f '../../libutils/file_lib.c'; then $(CYGPATH_W) '../../libutils/file_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/file_lib.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib.Tpo $(DEPDIR)/file_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/file_lib.c' object='file_lib.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib.obj `if test -f '../../libutils/file_lib.c'; then $(CYGPATH_W) '../../libutils/file_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/file_lib.c'; fi` server_common.o: ../../cf-serverd/server_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_common.o -MD -MP -MF $(DEPDIR)/server_common.Tpo -c -o server_common.o `test -f '../../cf-serverd/server_common.c' || echo '$(srcdir)/'`../../cf-serverd/server_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_common.Tpo $(DEPDIR)/server_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_common.c' object='server_common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_common.o `test -f '../../cf-serverd/server_common.c' || echo '$(srcdir)/'`../../cf-serverd/server_common.c server_common.obj: ../../cf-serverd/server_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_common.obj -MD -MP -MF $(DEPDIR)/server_common.Tpo -c -o server_common.obj `if test -f '../../cf-serverd/server_common.c'; then $(CYGPATH_W) '../../cf-serverd/server_common.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_common.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_common.Tpo $(DEPDIR)/server_common.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_common.c' object='server_common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_common.obj `if test -f '../../cf-serverd/server_common.c'; then $(CYGPATH_W) '../../cf-serverd/server_common.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_common.c'; fi` server_tls.o: ../../cf-serverd/server_tls.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_tls.o -MD -MP -MF $(DEPDIR)/server_tls.Tpo -c -o server_tls.o `test -f '../../cf-serverd/server_tls.c' || echo '$(srcdir)/'`../../cf-serverd/server_tls.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_tls.Tpo $(DEPDIR)/server_tls.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_tls.c' object='server_tls.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_tls.o `test -f '../../cf-serverd/server_tls.c' || echo '$(srcdir)/'`../../cf-serverd/server_tls.c server_tls.obj: ../../cf-serverd/server_tls.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_tls.obj -MD -MP -MF $(DEPDIR)/server_tls.Tpo -c -o server_tls.obj `if test -f '../../cf-serverd/server_tls.c'; then $(CYGPATH_W) '../../cf-serverd/server_tls.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_tls.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_tls.Tpo $(DEPDIR)/server_tls.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_tls.c' object='server_tls.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_tls.obj `if test -f '../../cf-serverd/server_tls.c'; then $(CYGPATH_W) '../../cf-serverd/server_tls.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_tls.c'; fi` server.o: ../../cf-serverd/server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server.o -MD -MP -MF $(DEPDIR)/server.Tpo -c -o server.o `test -f '../../cf-serverd/server.c' || echo '$(srcdir)/'`../../cf-serverd/server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server.Tpo $(DEPDIR)/server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server.c' object='server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server.o `test -f '../../cf-serverd/server.c' || echo '$(srcdir)/'`../../cf-serverd/server.c server.obj: ../../cf-serverd/server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server.obj -MD -MP -MF $(DEPDIR)/server.Tpo -c -o server.obj `if test -f '../../cf-serverd/server.c'; then $(CYGPATH_W) '../../cf-serverd/server.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server.Tpo $(DEPDIR)/server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server.c' object='server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server.obj `if test -f '../../cf-serverd/server.c'; then $(CYGPATH_W) '../../cf-serverd/server.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server.c'; fi` server_transform.o: ../../cf-serverd/server_transform.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_transform.o -MD -MP -MF $(DEPDIR)/server_transform.Tpo -c -o server_transform.o `test -f '../../cf-serverd/server_transform.c' || echo '$(srcdir)/'`../../cf-serverd/server_transform.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_transform.Tpo $(DEPDIR)/server_transform.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_transform.c' object='server_transform.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_transform.o `test -f '../../cf-serverd/server_transform.c' || echo '$(srcdir)/'`../../cf-serverd/server_transform.c server_transform.obj: ../../cf-serverd/server_transform.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_transform.obj -MD -MP -MF $(DEPDIR)/server_transform.Tpo -c -o server_transform.obj `if test -f '../../cf-serverd/server_transform.c'; then $(CYGPATH_W) '../../cf-serverd/server_transform.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_transform.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_transform.Tpo $(DEPDIR)/server_transform.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_transform.c' object='server_transform.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_transform.obj `if test -f '../../cf-serverd/server_transform.c'; then $(CYGPATH_W) '../../cf-serverd/server_transform.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_transform.c'; fi` cf-serverd-enterprise-stubs.o: ../../cf-serverd/cf-serverd-enterprise-stubs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cf-serverd-enterprise-stubs.o -MD -MP -MF $(DEPDIR)/cf-serverd-enterprise-stubs.Tpo -c -o cf-serverd-enterprise-stubs.o `test -f '../../cf-serverd/cf-serverd-enterprise-stubs.c' || echo '$(srcdir)/'`../../cf-serverd/cf-serverd-enterprise-stubs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf-serverd-enterprise-stubs.Tpo $(DEPDIR)/cf-serverd-enterprise-stubs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/cf-serverd-enterprise-stubs.c' object='cf-serverd-enterprise-stubs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cf-serverd-enterprise-stubs.o `test -f '../../cf-serverd/cf-serverd-enterprise-stubs.c' || echo '$(srcdir)/'`../../cf-serverd/cf-serverd-enterprise-stubs.c cf-serverd-enterprise-stubs.obj: ../../cf-serverd/cf-serverd-enterprise-stubs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cf-serverd-enterprise-stubs.obj -MD -MP -MF $(DEPDIR)/cf-serverd-enterprise-stubs.Tpo -c -o cf-serverd-enterprise-stubs.obj `if test -f '../../cf-serverd/cf-serverd-enterprise-stubs.c'; then $(CYGPATH_W) '../../cf-serverd/cf-serverd-enterprise-stubs.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/cf-serverd-enterprise-stubs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf-serverd-enterprise-stubs.Tpo $(DEPDIR)/cf-serverd-enterprise-stubs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/cf-serverd-enterprise-stubs.c' object='cf-serverd-enterprise-stubs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cf-serverd-enterprise-stubs.obj `if test -f '../../cf-serverd/cf-serverd-enterprise-stubs.c'; then $(CYGPATH_W) '../../cf-serverd/cf-serverd-enterprise-stubs.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/cf-serverd-enterprise-stubs.c'; fi` server_access.o: ../../cf-serverd/server_access.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_access.o -MD -MP -MF $(DEPDIR)/server_access.Tpo -c -o server_access.o `test -f '../../cf-serverd/server_access.c' || echo '$(srcdir)/'`../../cf-serverd/server_access.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_access.Tpo $(DEPDIR)/server_access.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_access.c' object='server_access.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_access.o `test -f '../../cf-serverd/server_access.c' || echo '$(srcdir)/'`../../cf-serverd/server_access.c server_access.obj: ../../cf-serverd/server_access.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_access.obj -MD -MP -MF $(DEPDIR)/server_access.Tpo -c -o server_access.obj `if test -f '../../cf-serverd/server_access.c'; then $(CYGPATH_W) '../../cf-serverd/server_access.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_access.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_access.Tpo $(DEPDIR)/server_access.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_access.c' object='server_access.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_access.obj `if test -f '../../cf-serverd/server_access.c'; then $(CYGPATH_W) '../../cf-serverd/server_access.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_access.c'; fi` server_classic.o: ../../cf-serverd/server_classic.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_classic.o -MD -MP -MF $(DEPDIR)/server_classic.Tpo -c -o server_classic.o `test -f '../../cf-serverd/server_classic.c' || echo '$(srcdir)/'`../../cf-serverd/server_classic.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_classic.Tpo $(DEPDIR)/server_classic.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_classic.c' object='server_classic.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_classic.o `test -f '../../cf-serverd/server_classic.c' || echo '$(srcdir)/'`../../cf-serverd/server_classic.c server_classic.obj: ../../cf-serverd/server_classic.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_classic.obj -MD -MP -MF $(DEPDIR)/server_classic.Tpo -c -o server_classic.obj `if test -f '../../cf-serverd/server_classic.c'; then $(CYGPATH_W) '../../cf-serverd/server_classic.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_classic.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/server_classic.Tpo $(DEPDIR)/server_classic.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/server_classic.c' object='server_classic.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_classic.obj `if test -f '../../cf-serverd/server_classic.c'; then $(CYGPATH_W) '../../cf-serverd/server_classic.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/server_classic.c'; fi` strlist.o: ../../cf-serverd/strlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strlist.o -MD -MP -MF $(DEPDIR)/strlist.Tpo -c -o strlist.o `test -f '../../cf-serverd/strlist.c' || echo '$(srcdir)/'`../../cf-serverd/strlist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/strlist.Tpo $(DEPDIR)/strlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/strlist.c' object='strlist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strlist.o `test -f '../../cf-serverd/strlist.c' || echo '$(srcdir)/'`../../cf-serverd/strlist.c strlist.obj: ../../cf-serverd/strlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strlist.obj -MD -MP -MF $(DEPDIR)/strlist.Tpo -c -o strlist.obj `if test -f '../../cf-serverd/strlist.c'; then $(CYGPATH_W) '../../cf-serverd/strlist.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/strlist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/strlist.Tpo $(DEPDIR)/strlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/strlist.c' object='strlist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strlist.obj `if test -f '../../cf-serverd/strlist.c'; then $(CYGPATH_W) '../../cf-serverd/strlist.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/strlist.c'; fi` buffer.o: ../../libutils/buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT buffer.o -MD -MP -MF $(DEPDIR)/buffer.Tpo -c -o buffer.o `test -f '../../libutils/buffer.c' || echo '$(srcdir)/'`../../libutils/buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer.Tpo $(DEPDIR)/buffer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/buffer.c' object='buffer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.o `test -f '../../libutils/buffer.c' || echo '$(srcdir)/'`../../libutils/buffer.c buffer.obj: ../../libutils/buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT buffer.obj -MD -MP -MF $(DEPDIR)/buffer.Tpo -c -o buffer.obj `if test -f '../../libutils/buffer.c'; then $(CYGPATH_W) '../../libutils/buffer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/buffer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/buffer.Tpo $(DEPDIR)/buffer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/buffer.c' object='buffer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o buffer.obj `if test -f '../../libutils/buffer.c'; then $(CYGPATH_W) '../../libutils/buffer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/buffer.c'; fi` cf-key-functions.o: ../../cf-key/cf-key-functions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cf-key-functions.o -MD -MP -MF $(DEPDIR)/cf-key-functions.Tpo -c -o cf-key-functions.o `test -f '../../cf-key/cf-key-functions.c' || echo '$(srcdir)/'`../../cf-key/cf-key-functions.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf-key-functions.Tpo $(DEPDIR)/cf-key-functions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-key/cf-key-functions.c' object='cf-key-functions.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cf-key-functions.o `test -f '../../cf-key/cf-key-functions.c' || echo '$(srcdir)/'`../../cf-key/cf-key-functions.c cf-key-functions.obj: ../../cf-key/cf-key-functions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cf-key-functions.obj -MD -MP -MF $(DEPDIR)/cf-key-functions.Tpo -c -o cf-key-functions.obj `if test -f '../../cf-key/cf-key-functions.c'; then $(CYGPATH_W) '../../cf-key/cf-key-functions.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-key/cf-key-functions.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf-key-functions.Tpo $(DEPDIR)/cf-key-functions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-key/cf-key-functions.c' object='cf-key-functions.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cf-key-functions.obj `if test -f '../../cf-key/cf-key-functions.c'; then $(CYGPATH_W) '../../cf-key/cf-key-functions.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-key/cf-key-functions.c'; fi` cf_upgrade_test-cf_upgrade_test.o: cf_upgrade_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-cf_upgrade_test.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Tpo -c -o cf_upgrade_test-cf_upgrade_test.o `test -f 'cf_upgrade_test.c' || echo '$(srcdir)/'`cf_upgrade_test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Tpo $(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf_upgrade_test.c' object='cf_upgrade_test-cf_upgrade_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-cf_upgrade_test.o `test -f 'cf_upgrade_test.c' || echo '$(srcdir)/'`cf_upgrade_test.c cf_upgrade_test-cf_upgrade_test.obj: cf_upgrade_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-cf_upgrade_test.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Tpo -c -o cf_upgrade_test-cf_upgrade_test.obj `if test -f 'cf_upgrade_test.c'; then $(CYGPATH_W) 'cf_upgrade_test.c'; else $(CYGPATH_W) '$(srcdir)/cf_upgrade_test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Tpo $(DEPDIR)/cf_upgrade_test-cf_upgrade_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf_upgrade_test.c' object='cf_upgrade_test-cf_upgrade_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-cf_upgrade_test.obj `if test -f 'cf_upgrade_test.c'; then $(CYGPATH_W) 'cf_upgrade_test.c'; else $(CYGPATH_W) '$(srcdir)/cf_upgrade_test.c'; fi` cf_upgrade_test-alloc-mini.o: $(CFUPGRADE)/alloc-mini.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-alloc-mini.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-alloc-mini.Tpo -c -o cf_upgrade_test-alloc-mini.o `test -f '$(CFUPGRADE)/alloc-mini.c' || echo '$(srcdir)/'`$(CFUPGRADE)/alloc-mini.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-alloc-mini.Tpo $(DEPDIR)/cf_upgrade_test-alloc-mini.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/alloc-mini.c' object='cf_upgrade_test-alloc-mini.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-alloc-mini.o `test -f '$(CFUPGRADE)/alloc-mini.c' || echo '$(srcdir)/'`$(CFUPGRADE)/alloc-mini.c cf_upgrade_test-alloc-mini.obj: $(CFUPGRADE)/alloc-mini.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-alloc-mini.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-alloc-mini.Tpo -c -o cf_upgrade_test-alloc-mini.obj `if test -f '$(CFUPGRADE)/alloc-mini.c'; then $(CYGPATH_W) '$(CFUPGRADE)/alloc-mini.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/alloc-mini.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-alloc-mini.Tpo $(DEPDIR)/cf_upgrade_test-alloc-mini.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/alloc-mini.c' object='cf_upgrade_test-alloc-mini.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-alloc-mini.obj `if test -f '$(CFUPGRADE)/alloc-mini.c'; then $(CYGPATH_W) '$(CFUPGRADE)/alloc-mini.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/alloc-mini.c'; fi` cf_upgrade_test-command_line.o: $(CFUPGRADE)/command_line.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-command_line.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-command_line.Tpo -c -o cf_upgrade_test-command_line.o `test -f '$(CFUPGRADE)/command_line.c' || echo '$(srcdir)/'`$(CFUPGRADE)/command_line.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-command_line.Tpo $(DEPDIR)/cf_upgrade_test-command_line.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/command_line.c' object='cf_upgrade_test-command_line.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-command_line.o `test -f '$(CFUPGRADE)/command_line.c' || echo '$(srcdir)/'`$(CFUPGRADE)/command_line.c cf_upgrade_test-command_line.obj: $(CFUPGRADE)/command_line.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-command_line.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-command_line.Tpo -c -o cf_upgrade_test-command_line.obj `if test -f '$(CFUPGRADE)/command_line.c'; then $(CYGPATH_W) '$(CFUPGRADE)/command_line.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/command_line.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-command_line.Tpo $(DEPDIR)/cf_upgrade_test-command_line.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/command_line.c' object='cf_upgrade_test-command_line.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-command_line.obj `if test -f '$(CFUPGRADE)/command_line.c'; then $(CYGPATH_W) '$(CFUPGRADE)/command_line.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/command_line.c'; fi` cf_upgrade_test-configuration.o: $(CFUPGRADE)/configuration.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-configuration.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-configuration.Tpo -c -o cf_upgrade_test-configuration.o `test -f '$(CFUPGRADE)/configuration.c' || echo '$(srcdir)/'`$(CFUPGRADE)/configuration.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-configuration.Tpo $(DEPDIR)/cf_upgrade_test-configuration.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/configuration.c' object='cf_upgrade_test-configuration.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-configuration.o `test -f '$(CFUPGRADE)/configuration.c' || echo '$(srcdir)/'`$(CFUPGRADE)/configuration.c cf_upgrade_test-configuration.obj: $(CFUPGRADE)/configuration.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-configuration.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-configuration.Tpo -c -o cf_upgrade_test-configuration.obj `if test -f '$(CFUPGRADE)/configuration.c'; then $(CYGPATH_W) '$(CFUPGRADE)/configuration.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/configuration.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-configuration.Tpo $(DEPDIR)/cf_upgrade_test-configuration.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/configuration.c' object='cf_upgrade_test-configuration.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-configuration.obj `if test -f '$(CFUPGRADE)/configuration.c'; then $(CYGPATH_W) '$(CFUPGRADE)/configuration.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/configuration.c'; fi` cf_upgrade_test-log.o: $(CFUPGRADE)/log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-log.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-log.Tpo -c -o cf_upgrade_test-log.o `test -f '$(CFUPGRADE)/log.c' || echo '$(srcdir)/'`$(CFUPGRADE)/log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-log.Tpo $(DEPDIR)/cf_upgrade_test-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/log.c' object='cf_upgrade_test-log.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-log.o `test -f '$(CFUPGRADE)/log.c' || echo '$(srcdir)/'`$(CFUPGRADE)/log.c cf_upgrade_test-log.obj: $(CFUPGRADE)/log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-log.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-log.Tpo -c -o cf_upgrade_test-log.obj `if test -f '$(CFUPGRADE)/log.c'; then $(CYGPATH_W) '$(CFUPGRADE)/log.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/log.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-log.Tpo $(DEPDIR)/cf_upgrade_test-log.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/log.c' object='cf_upgrade_test-log.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-log.obj `if test -f '$(CFUPGRADE)/log.c'; then $(CYGPATH_W) '$(CFUPGRADE)/log.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/log.c'; fi` cf_upgrade_test-process.o: $(CFUPGRADE)/process.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-process.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-process.Tpo -c -o cf_upgrade_test-process.o `test -f '$(CFUPGRADE)/process.c' || echo '$(srcdir)/'`$(CFUPGRADE)/process.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-process.Tpo $(DEPDIR)/cf_upgrade_test-process.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/process.c' object='cf_upgrade_test-process.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-process.o `test -f '$(CFUPGRADE)/process.c' || echo '$(srcdir)/'`$(CFUPGRADE)/process.c cf_upgrade_test-process.obj: $(CFUPGRADE)/process.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-process.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-process.Tpo -c -o cf_upgrade_test-process.obj `if test -f '$(CFUPGRADE)/process.c'; then $(CYGPATH_W) '$(CFUPGRADE)/process.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/process.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-process.Tpo $(DEPDIR)/cf_upgrade_test-process.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/process.c' object='cf_upgrade_test-process.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-process.obj `if test -f '$(CFUPGRADE)/process.c'; then $(CYGPATH_W) '$(CFUPGRADE)/process.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/process.c'; fi` cf_upgrade_test-update.o: $(CFUPGRADE)/update.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-update.o -MD -MP -MF $(DEPDIR)/cf_upgrade_test-update.Tpo -c -o cf_upgrade_test-update.o `test -f '$(CFUPGRADE)/update.c' || echo '$(srcdir)/'`$(CFUPGRADE)/update.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-update.Tpo $(DEPDIR)/cf_upgrade_test-update.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/update.c' object='cf_upgrade_test-update.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-update.o `test -f '$(CFUPGRADE)/update.c' || echo '$(srcdir)/'`$(CFUPGRADE)/update.c cf_upgrade_test-update.obj: $(CFUPGRADE)/update.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -MT cf_upgrade_test-update.obj -MD -MP -MF $(DEPDIR)/cf_upgrade_test-update.Tpo -c -o cf_upgrade_test-update.obj `if test -f '$(CFUPGRADE)/update.c'; then $(CYGPATH_W) '$(CFUPGRADE)/update.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/update.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_upgrade_test-update.Tpo $(DEPDIR)/cf_upgrade_test-update.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(CFUPGRADE)/update.c' object='cf_upgrade_test-update.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_upgrade_test_CFLAGS) $(CFLAGS) -c -o cf_upgrade_test-update.obj `if test -f '$(CFUPGRADE)/update.c'; then $(CYGPATH_W) '$(CFUPGRADE)/update.c'; else $(CYGPATH_W) '$(srcdir)/$(CFUPGRADE)/update.c'; fi` conversion.o: ../../libpromises/conversion.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT conversion.o -MD -MP -MF $(DEPDIR)/conversion.Tpo -c -o conversion.o `test -f '../../libpromises/conversion.c' || echo '$(srcdir)/'`../../libpromises/conversion.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/conversion.Tpo $(DEPDIR)/conversion.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/conversion.c' object='conversion.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o conversion.o `test -f '../../libpromises/conversion.c' || echo '$(srcdir)/'`../../libpromises/conversion.c conversion.obj: ../../libpromises/conversion.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT conversion.obj -MD -MP -MF $(DEPDIR)/conversion.Tpo -c -o conversion.obj `if test -f '../../libpromises/conversion.c'; then $(CYGPATH_W) '../../libpromises/conversion.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/conversion.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/conversion.Tpo $(DEPDIR)/conversion.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/conversion.c' object='conversion.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o conversion.obj `if test -f '../../libpromises/conversion.c'; then $(CYGPATH_W) '../../libpromises/conversion.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/conversion.c'; fi` csv_parser.o: ../../libutils/csv_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT csv_parser.o -MD -MP -MF $(DEPDIR)/csv_parser.Tpo -c -o csv_parser.o `test -f '../../libutils/csv_parser.c' || echo '$(srcdir)/'`../../libutils/csv_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/csv_parser.Tpo $(DEPDIR)/csv_parser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/csv_parser.c' object='csv_parser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o csv_parser.o `test -f '../../libutils/csv_parser.c' || echo '$(srcdir)/'`../../libutils/csv_parser.c csv_parser.obj: ../../libutils/csv_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT csv_parser.obj -MD -MP -MF $(DEPDIR)/csv_parser.Tpo -c -o csv_parser.obj `if test -f '../../libutils/csv_parser.c'; then $(CYGPATH_W) '../../libutils/csv_parser.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/csv_parser.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/csv_parser.Tpo $(DEPDIR)/csv_parser.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/csv_parser.c' object='csv_parser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o csv_parser.obj `if test -f '../../libutils/csv_parser.c'; then $(CYGPATH_W) '../../libutils/csv_parser.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/csv_parser.c'; fi` csv_writer.o: ../../libutils/csv_writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT csv_writer.o -MD -MP -MF $(DEPDIR)/csv_writer.Tpo -c -o csv_writer.o `test -f '../../libutils/csv_writer.c' || echo '$(srcdir)/'`../../libutils/csv_writer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/csv_writer.Tpo $(DEPDIR)/csv_writer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/csv_writer.c' object='csv_writer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o csv_writer.o `test -f '../../libutils/csv_writer.c' || echo '$(srcdir)/'`../../libutils/csv_writer.c csv_writer.obj: ../../libutils/csv_writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT csv_writer.obj -MD -MP -MF $(DEPDIR)/csv_writer.Tpo -c -o csv_writer.obj `if test -f '../../libutils/csv_writer.c'; then $(CYGPATH_W) '../../libutils/csv_writer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/csv_writer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/csv_writer.Tpo $(DEPDIR)/csv_writer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/csv_writer.c' object='csv_writer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o csv_writer.obj `if test -f '../../libutils/csv_writer.c'; then $(CYGPATH_W) '../../libutils/csv_writer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/csv_writer.c'; fi` exec-config.o: ../../cf-execd/exec-config.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exec-config.o -MD -MP -MF $(DEPDIR)/exec-config.Tpo -c -o exec-config.o `test -f '../../cf-execd/exec-config.c' || echo '$(srcdir)/'`../../cf-execd/exec-config.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exec-config.Tpo $(DEPDIR)/exec-config.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-execd/exec-config.c' object='exec-config.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exec-config.o `test -f '../../cf-execd/exec-config.c' || echo '$(srcdir)/'`../../cf-execd/exec-config.c exec-config.obj: ../../cf-execd/exec-config.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT exec-config.obj -MD -MP -MF $(DEPDIR)/exec-config.Tpo -c -o exec-config.obj `if test -f '../../cf-execd/exec-config.c'; then $(CYGPATH_W) '../../cf-execd/exec-config.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-execd/exec-config.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/exec-config.Tpo $(DEPDIR)/exec-config.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-execd/exec-config.c' object='exec-config.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o exec-config.obj `if test -f '../../cf-execd/exec-config.c'; then $(CYGPATH_W) '../../cf-execd/exec-config.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-execd/exec-config.c'; fi` execd-config.o: ../../cf-execd/execd-config.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT execd-config.o -MD -MP -MF $(DEPDIR)/execd-config.Tpo -c -o execd-config.o `test -f '../../cf-execd/execd-config.c' || echo '$(srcdir)/'`../../cf-execd/execd-config.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/execd-config.Tpo $(DEPDIR)/execd-config.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-execd/execd-config.c' object='execd-config.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o execd-config.o `test -f '../../cf-execd/execd-config.c' || echo '$(srcdir)/'`../../cf-execd/execd-config.c execd-config.obj: ../../cf-execd/execd-config.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT execd-config.obj -MD -MP -MF $(DEPDIR)/execd-config.Tpo -c -o execd-config.obj `if test -f '../../cf-execd/execd-config.c'; then $(CYGPATH_W) '../../cf-execd/execd-config.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-execd/execd-config.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/execd-config.Tpo $(DEPDIR)/execd-config.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-execd/execd-config.c' object='execd-config.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o execd-config.obj `if test -f '../../cf-execd/execd-config.c'; then $(CYGPATH_W) '../../cf-execd/execd-config.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-execd/execd-config.c'; fi` file_lib_test-file_lib_test.o: file_lib_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-file_lib_test.o -MD -MP -MF $(DEPDIR)/file_lib_test-file_lib_test.Tpo -c -o file_lib_test-file_lib_test.o `test -f 'file_lib_test.c' || echo '$(srcdir)/'`file_lib_test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-file_lib_test.Tpo $(DEPDIR)/file_lib_test-file_lib_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='file_lib_test.c' object='file_lib_test-file_lib_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-file_lib_test.o `test -f 'file_lib_test.c' || echo '$(srcdir)/'`file_lib_test.c file_lib_test-file_lib_test.obj: file_lib_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-file_lib_test.obj -MD -MP -MF $(DEPDIR)/file_lib_test-file_lib_test.Tpo -c -o file_lib_test-file_lib_test.obj `if test -f 'file_lib_test.c'; then $(CYGPATH_W) 'file_lib_test.c'; else $(CYGPATH_W) '$(srcdir)/file_lib_test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-file_lib_test.Tpo $(DEPDIR)/file_lib_test-file_lib_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='file_lib_test.c' object='file_lib_test-file_lib_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-file_lib_test.obj `if test -f 'file_lib_test.c'; then $(CYGPATH_W) 'file_lib_test.c'; else $(CYGPATH_W) '$(srcdir)/file_lib_test.c'; fi` file_lib_test-file_lib.o: ../../libutils/file_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-file_lib.o -MD -MP -MF $(DEPDIR)/file_lib_test-file_lib.Tpo -c -o file_lib_test-file_lib.o `test -f '../../libutils/file_lib.c' || echo '$(srcdir)/'`../../libutils/file_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-file_lib.Tpo $(DEPDIR)/file_lib_test-file_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/file_lib.c' object='file_lib_test-file_lib.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-file_lib.o `test -f '../../libutils/file_lib.c' || echo '$(srcdir)/'`../../libutils/file_lib.c file_lib_test-file_lib.obj: ../../libutils/file_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-file_lib.obj -MD -MP -MF $(DEPDIR)/file_lib_test-file_lib.Tpo -c -o file_lib_test-file_lib.obj `if test -f '../../libutils/file_lib.c'; then $(CYGPATH_W) '../../libutils/file_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/file_lib.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-file_lib.Tpo $(DEPDIR)/file_lib_test-file_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/file_lib.c' object='file_lib_test-file_lib.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-file_lib.obj `if test -f '../../libutils/file_lib.c'; then $(CYGPATH_W) '../../libutils/file_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/file_lib.c'; fi` file_lib_test-logging.o: ../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-logging.o -MD -MP -MF $(DEPDIR)/file_lib_test-logging.Tpo -c -o file_lib_test-logging.o `test -f '../../libutils/logging.c' || echo '$(srcdir)/'`../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-logging.Tpo $(DEPDIR)/file_lib_test-logging.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/logging.c' object='file_lib_test-logging.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-logging.o `test -f '../../libutils/logging.c' || echo '$(srcdir)/'`../../libutils/logging.c file_lib_test-logging.obj: ../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-logging.obj -MD -MP -MF $(DEPDIR)/file_lib_test-logging.Tpo -c -o file_lib_test-logging.obj `if test -f '../../libutils/logging.c'; then $(CYGPATH_W) '../../libutils/logging.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/logging.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-logging.Tpo $(DEPDIR)/file_lib_test-logging.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/logging.c' object='file_lib_test-logging.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-logging.obj `if test -f '../../libutils/logging.c'; then $(CYGPATH_W) '../../libutils/logging.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/logging.c'; fi` file_lib_test-misc_lib.o: ../../libutils/misc_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-misc_lib.o -MD -MP -MF $(DEPDIR)/file_lib_test-misc_lib.Tpo -c -o file_lib_test-misc_lib.o `test -f '../../libutils/misc_lib.c' || echo '$(srcdir)/'`../../libutils/misc_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-misc_lib.Tpo $(DEPDIR)/file_lib_test-misc_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/misc_lib.c' object='file_lib_test-misc_lib.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-misc_lib.o `test -f '../../libutils/misc_lib.c' || echo '$(srcdir)/'`../../libutils/misc_lib.c file_lib_test-misc_lib.obj: ../../libutils/misc_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-misc_lib.obj -MD -MP -MF $(DEPDIR)/file_lib_test-misc_lib.Tpo -c -o file_lib_test-misc_lib.obj `if test -f '../../libutils/misc_lib.c'; then $(CYGPATH_W) '../../libutils/misc_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/misc_lib.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-misc_lib.Tpo $(DEPDIR)/file_lib_test-misc_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/misc_lib.c' object='file_lib_test-misc_lib.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-misc_lib.obj `if test -f '../../libutils/misc_lib.c'; then $(CYGPATH_W) '../../libutils/misc_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/misc_lib.c'; fi` file_lib_test-string_lib.o: ../../libutils/string_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-string_lib.o -MD -MP -MF $(DEPDIR)/file_lib_test-string_lib.Tpo -c -o file_lib_test-string_lib.o `test -f '../../libutils/string_lib.c' || echo '$(srcdir)/'`../../libutils/string_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-string_lib.Tpo $(DEPDIR)/file_lib_test-string_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/string_lib.c' object='file_lib_test-string_lib.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-string_lib.o `test -f '../../libutils/string_lib.c' || echo '$(srcdir)/'`../../libutils/string_lib.c file_lib_test-string_lib.obj: ../../libutils/string_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-string_lib.obj -MD -MP -MF $(DEPDIR)/file_lib_test-string_lib.Tpo -c -o file_lib_test-string_lib.obj `if test -f '../../libutils/string_lib.c'; then $(CYGPATH_W) '../../libutils/string_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/string_lib.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-string_lib.Tpo $(DEPDIR)/file_lib_test-string_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/string_lib.c' object='file_lib_test-string_lib.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-string_lib.obj `if test -f '../../libutils/string_lib.c'; then $(CYGPATH_W) '../../libutils/string_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/string_lib.c'; fi` file_lib_test-sequence.o: ../../libutils/sequence.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-sequence.o -MD -MP -MF $(DEPDIR)/file_lib_test-sequence.Tpo -c -o file_lib_test-sequence.o `test -f '../../libutils/sequence.c' || echo '$(srcdir)/'`../../libutils/sequence.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-sequence.Tpo $(DEPDIR)/file_lib_test-sequence.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/sequence.c' object='file_lib_test-sequence.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-sequence.o `test -f '../../libutils/sequence.c' || echo '$(srcdir)/'`../../libutils/sequence.c file_lib_test-sequence.obj: ../../libutils/sequence.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-sequence.obj -MD -MP -MF $(DEPDIR)/file_lib_test-sequence.Tpo -c -o file_lib_test-sequence.obj `if test -f '../../libutils/sequence.c'; then $(CYGPATH_W) '../../libutils/sequence.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/sequence.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-sequence.Tpo $(DEPDIR)/file_lib_test-sequence.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/sequence.c' object='file_lib_test-sequence.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-sequence.obj `if test -f '../../libutils/sequence.c'; then $(CYGPATH_W) '../../libutils/sequence.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/sequence.c'; fi` file_lib_test-unix_dir.o: ../../libutils/unix_dir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-unix_dir.o -MD -MP -MF $(DEPDIR)/file_lib_test-unix_dir.Tpo -c -o file_lib_test-unix_dir.o `test -f '../../libutils/unix_dir.c' || echo '$(srcdir)/'`../../libutils/unix_dir.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-unix_dir.Tpo $(DEPDIR)/file_lib_test-unix_dir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/unix_dir.c' object='file_lib_test-unix_dir.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-unix_dir.o `test -f '../../libutils/unix_dir.c' || echo '$(srcdir)/'`../../libutils/unix_dir.c file_lib_test-unix_dir.obj: ../../libutils/unix_dir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-unix_dir.obj -MD -MP -MF $(DEPDIR)/file_lib_test-unix_dir.Tpo -c -o file_lib_test-unix_dir.obj `if test -f '../../libutils/unix_dir.c'; then $(CYGPATH_W) '../../libutils/unix_dir.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/unix_dir.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-unix_dir.Tpo $(DEPDIR)/file_lib_test-unix_dir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/unix_dir.c' object='file_lib_test-unix_dir.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-unix_dir.obj `if test -f '../../libutils/unix_dir.c'; then $(CYGPATH_W) '../../libutils/unix_dir.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/unix_dir.c'; fi` file_lib_test-writer.o: ../../libutils/writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-writer.o -MD -MP -MF $(DEPDIR)/file_lib_test-writer.Tpo -c -o file_lib_test-writer.o `test -f '../../libutils/writer.c' || echo '$(srcdir)/'`../../libutils/writer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-writer.Tpo $(DEPDIR)/file_lib_test-writer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/writer.c' object='file_lib_test-writer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-writer.o `test -f '../../libutils/writer.c' || echo '$(srcdir)/'`../../libutils/writer.c file_lib_test-writer.obj: ../../libutils/writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_lib_test-writer.obj -MD -MP -MF $(DEPDIR)/file_lib_test-writer.Tpo -c -o file_lib_test-writer.obj `if test -f '../../libutils/writer.c'; then $(CYGPATH_W) '../../libutils/writer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/writer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/file_lib_test-writer.Tpo $(DEPDIR)/file_lib_test-writer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/writer.c' object='file_lib_test-writer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(file_lib_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_lib_test-writer.obj `if test -f '../../libutils/writer.c'; then $(CYGPATH_W) '../../libutils/writer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/writer.c'; fi` findhub.o: ../../cf-agent/findhub.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT findhub.o -MD -MP -MF $(DEPDIR)/findhub.Tpo -c -o findhub.o `test -f '../../cf-agent/findhub.c' || echo '$(srcdir)/'`../../cf-agent/findhub.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/findhub.Tpo $(DEPDIR)/findhub.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/findhub.c' object='findhub.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o findhub.o `test -f '../../cf-agent/findhub.c' || echo '$(srcdir)/'`../../cf-agent/findhub.c findhub.obj: ../../cf-agent/findhub.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT findhub.obj -MD -MP -MF $(DEPDIR)/findhub.Tpo -c -o findhub.obj `if test -f '../../cf-agent/findhub.c'; then $(CYGPATH_W) '../../cf-agent/findhub.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/findhub.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/findhub.Tpo $(DEPDIR)/findhub.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/findhub.c' object='findhub.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o findhub.obj `if test -f '../../cf-agent/findhub.c'; then $(CYGPATH_W) '../../cf-agent/findhub.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/findhub.c'; fi` load_avahi.o: ../../cf-agent/load_avahi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT load_avahi.o -MD -MP -MF $(DEPDIR)/load_avahi.Tpo -c -o load_avahi.o `test -f '../../cf-agent/load_avahi.c' || echo '$(srcdir)/'`../../cf-agent/load_avahi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/load_avahi.Tpo $(DEPDIR)/load_avahi.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/load_avahi.c' object='load_avahi.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o load_avahi.o `test -f '../../cf-agent/load_avahi.c' || echo '$(srcdir)/'`../../cf-agent/load_avahi.c load_avahi.obj: ../../cf-agent/load_avahi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT load_avahi.obj -MD -MP -MF $(DEPDIR)/load_avahi.Tpo -c -o load_avahi.obj `if test -f '../../cf-agent/load_avahi.c'; then $(CYGPATH_W) '../../cf-agent/load_avahi.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/load_avahi.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/load_avahi.Tpo $(DEPDIR)/load_avahi.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/load_avahi.c' object='load_avahi.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o load_avahi.obj `if test -f '../../cf-agent/load_avahi.c'; then $(CYGPATH_W) '../../cf-agent/load_avahi.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/load_avahi.c'; fi` lastseen.o: ../../libpromises/lastseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lastseen.o -MD -MP -MF $(DEPDIR)/lastseen.Tpo -c -o lastseen.o `test -f '../../libpromises/lastseen.c' || echo '$(srcdir)/'`../../libpromises/lastseen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lastseen.Tpo $(DEPDIR)/lastseen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/lastseen.c' object='lastseen.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lastseen.o `test -f '../../libpromises/lastseen.c' || echo '$(srcdir)/'`../../libpromises/lastseen.c lastseen.obj: ../../libpromises/lastseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lastseen.obj -MD -MP -MF $(DEPDIR)/lastseen.Tpo -c -o lastseen.obj `if test -f '../../libpromises/lastseen.c'; then $(CYGPATH_W) '../../libpromises/lastseen.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/lastseen.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lastseen.Tpo $(DEPDIR)/lastseen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/lastseen.c' object='lastseen.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lastseen.obj `if test -f '../../libpromises/lastseen.c'; then $(CYGPATH_W) '../../libpromises/lastseen.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/lastseen.c'; fi` statistics.o: ../../libutils/statistics.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT statistics.o -MD -MP -MF $(DEPDIR)/statistics.Tpo -c -o statistics.o `test -f '../../libutils/statistics.c' || echo '$(srcdir)/'`../../libutils/statistics.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/statistics.Tpo $(DEPDIR)/statistics.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/statistics.c' object='statistics.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o statistics.o `test -f '../../libutils/statistics.c' || echo '$(srcdir)/'`../../libutils/statistics.c statistics.obj: ../../libutils/statistics.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT statistics.obj -MD -MP -MF $(DEPDIR)/statistics.Tpo -c -o statistics.obj `if test -f '../../libutils/statistics.c'; then $(CYGPATH_W) '../../libutils/statistics.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/statistics.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/statistics.Tpo $(DEPDIR)/statistics.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/statistics.c' object='statistics.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o statistics.obj `if test -f '../../libutils/statistics.c'; then $(CYGPATH_W) '../../libutils/statistics.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/statistics.c'; fi` item_lib.o: ../../libpromises/item_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT item_lib.o -MD -MP -MF $(DEPDIR)/item_lib.Tpo -c -o item_lib.o `test -f '../../libpromises/item_lib.c' || echo '$(srcdir)/'`../../libpromises/item_lib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/item_lib.Tpo $(DEPDIR)/item_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/item_lib.c' object='item_lib.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o item_lib.o `test -f '../../libpromises/item_lib.c' || echo '$(srcdir)/'`../../libpromises/item_lib.c item_lib.obj: ../../libpromises/item_lib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT item_lib.obj -MD -MP -MF $(DEPDIR)/item_lib.Tpo -c -o item_lib.obj `if test -f '../../libpromises/item_lib.c'; then $(CYGPATH_W) '../../libpromises/item_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/item_lib.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/item_lib.Tpo $(DEPDIR)/item_lib.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/item_lib.c' object='item_lib.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o item_lib.obj `if test -f '../../libpromises/item_lib.c'; then $(CYGPATH_W) '../../libpromises/item_lib.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/item_lib.c'; fi` libcompat_test-libcompat_test.o: libcompat_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcompat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcompat_test-libcompat_test.o -MD -MP -MF $(DEPDIR)/libcompat_test-libcompat_test.Tpo -c -o libcompat_test-libcompat_test.o `test -f 'libcompat_test.c' || echo '$(srcdir)/'`libcompat_test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcompat_test-libcompat_test.Tpo $(DEPDIR)/libcompat_test-libcompat_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat_test.c' object='libcompat_test-libcompat_test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcompat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcompat_test-libcompat_test.o `test -f 'libcompat_test.c' || echo '$(srcdir)/'`libcompat_test.c libcompat_test-libcompat_test.obj: libcompat_test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcompat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcompat_test-libcompat_test.obj -MD -MP -MF $(DEPDIR)/libcompat_test-libcompat_test.Tpo -c -o libcompat_test-libcompat_test.obj `if test -f 'libcompat_test.c'; then $(CYGPATH_W) 'libcompat_test.c'; else $(CYGPATH_W) '$(srcdir)/libcompat_test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcompat_test-libcompat_test.Tpo $(DEPDIR)/libcompat_test-libcompat_test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcompat_test.c' object='libcompat_test-libcompat_test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcompat_test_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcompat_test-libcompat_test.obj `if test -f 'libcompat_test.c'; then $(CYGPATH_W) 'libcompat_test.c'; else $(CYGPATH_W) '$(srcdir)/libcompat_test.c'; fi` process_linux.o: ../../libpromises/process_linux.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_linux.o -MD -MP -MF $(DEPDIR)/process_linux.Tpo -c -o process_linux.o `test -f '../../libpromises/process_linux.c' || echo '$(srcdir)/'`../../libpromises/process_linux.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_linux.Tpo $(DEPDIR)/process_linux.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_linux.c' object='process_linux.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_linux.o `test -f '../../libpromises/process_linux.c' || echo '$(srcdir)/'`../../libpromises/process_linux.c process_linux.obj: ../../libpromises/process_linux.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_linux.obj -MD -MP -MF $(DEPDIR)/process_linux.Tpo -c -o process_linux.obj `if test -f '../../libpromises/process_linux.c'; then $(CYGPATH_W) '../../libpromises/process_linux.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_linux.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_linux.Tpo $(DEPDIR)/process_linux.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_linux.c' object='process_linux.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_linux.obj `if test -f '../../libpromises/process_linux.c'; then $(CYGPATH_W) '../../libpromises/process_linux.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_linux.c'; fi` syslog_client.o: ../../libpromises/syslog_client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syslog_client.o -MD -MP -MF $(DEPDIR)/syslog_client.Tpo -c -o syslog_client.o `test -f '../../libpromises/syslog_client.c' || echo '$(srcdir)/'`../../libpromises/syslog_client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/syslog_client.Tpo $(DEPDIR)/syslog_client.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/syslog_client.c' object='syslog_client.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syslog_client.o `test -f '../../libpromises/syslog_client.c' || echo '$(srcdir)/'`../../libpromises/syslog_client.c syslog_client.obj: ../../libpromises/syslog_client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT syslog_client.obj -MD -MP -MF $(DEPDIR)/syslog_client.Tpo -c -o syslog_client.obj `if test -f '../../libpromises/syslog_client.c'; then $(CYGPATH_W) '../../libpromises/syslog_client.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/syslog_client.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/syslog_client.Tpo $(DEPDIR)/syslog_client.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/syslog_client.c' object='syslog_client.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o syslog_client.obj `if test -f '../../libpromises/syslog_client.c'; then $(CYGPATH_W) '../../libpromises/syslog_client.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/syslog_client.c'; fi` mon_cpu.o: ../../cf-monitord/mon_cpu.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mon_cpu.o -MD -MP -MF $(DEPDIR)/mon_cpu.Tpo -c -o mon_cpu.o `test -f '../../cf-monitord/mon_cpu.c' || echo '$(srcdir)/'`../../cf-monitord/mon_cpu.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mon_cpu.Tpo $(DEPDIR)/mon_cpu.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-monitord/mon_cpu.c' object='mon_cpu.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mon_cpu.o `test -f '../../cf-monitord/mon_cpu.c' || echo '$(srcdir)/'`../../cf-monitord/mon_cpu.c mon_cpu.obj: ../../cf-monitord/mon_cpu.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mon_cpu.obj -MD -MP -MF $(DEPDIR)/mon_cpu.Tpo -c -o mon_cpu.obj `if test -f '../../cf-monitord/mon_cpu.c'; then $(CYGPATH_W) '../../cf-monitord/mon_cpu.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-monitord/mon_cpu.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mon_cpu.Tpo $(DEPDIR)/mon_cpu.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-monitord/mon_cpu.c' object='mon_cpu.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mon_cpu.obj `if test -f '../../cf-monitord/mon_cpu.c'; then $(CYGPATH_W) '../../cf-monitord/mon_cpu.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-monitord/mon_cpu.c'; fi` mon_load.o: ../../cf-monitord/mon_load.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mon_load.o -MD -MP -MF $(DEPDIR)/mon_load.Tpo -c -o mon_load.o `test -f '../../cf-monitord/mon_load.c' || echo '$(srcdir)/'`../../cf-monitord/mon_load.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mon_load.Tpo $(DEPDIR)/mon_load.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-monitord/mon_load.c' object='mon_load.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mon_load.o `test -f '../../cf-monitord/mon_load.c' || echo '$(srcdir)/'`../../cf-monitord/mon_load.c mon_load.obj: ../../cf-monitord/mon_load.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mon_load.obj -MD -MP -MF $(DEPDIR)/mon_load.Tpo -c -o mon_load.obj `if test -f '../../cf-monitord/mon_load.c'; then $(CYGPATH_W) '../../cf-monitord/mon_load.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-monitord/mon_load.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mon_load.Tpo $(DEPDIR)/mon_load.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-monitord/mon_load.c' object='mon_load.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mon_load.obj `if test -f '../../cf-monitord/mon_load.c'; then $(CYGPATH_W) '../../cf-monitord/mon_load.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-monitord/mon_load.c'; fi` mon_processes.o: ../../cf-monitord/mon_processes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mon_processes.o -MD -MP -MF $(DEPDIR)/mon_processes.Tpo -c -o mon_processes.o `test -f '../../cf-monitord/mon_processes.c' || echo '$(srcdir)/'`../../cf-monitord/mon_processes.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mon_processes.Tpo $(DEPDIR)/mon_processes.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-monitord/mon_processes.c' object='mon_processes.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mon_processes.o `test -f '../../cf-monitord/mon_processes.c' || echo '$(srcdir)/'`../../cf-monitord/mon_processes.c mon_processes.obj: ../../cf-monitord/mon_processes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mon_processes.obj -MD -MP -MF $(DEPDIR)/mon_processes.Tpo -c -o mon_processes.obj `if test -f '../../cf-monitord/mon_processes.c'; then $(CYGPATH_W) '../../cf-monitord/mon_processes.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-monitord/mon_processes.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mon_processes.Tpo $(DEPDIR)/mon_processes.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-monitord/mon_processes.c' object='mon_processes.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mon_processes.obj `if test -f '../../cf-monitord/mon_processes.c'; then $(CYGPATH_W) '../../cf-monitord/mon_processes.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-monitord/mon_processes.c'; fi` verify_packages.o: ../../cf-agent/verify_packages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT verify_packages.o -MD -MP -MF $(DEPDIR)/verify_packages.Tpo -c -o verify_packages.o `test -f '../../cf-agent/verify_packages.c' || echo '$(srcdir)/'`../../cf-agent/verify_packages.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/verify_packages.Tpo $(DEPDIR)/verify_packages.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/verify_packages.c' object='verify_packages.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o verify_packages.o `test -f '../../cf-agent/verify_packages.c' || echo '$(srcdir)/'`../../cf-agent/verify_packages.c verify_packages.obj: ../../cf-agent/verify_packages.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT verify_packages.obj -MD -MP -MF $(DEPDIR)/verify_packages.Tpo -c -o verify_packages.obj `if test -f '../../cf-agent/verify_packages.c'; then $(CYGPATH_W) '../../cf-agent/verify_packages.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/verify_packages.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/verify_packages.Tpo $(DEPDIR)/verify_packages.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/verify_packages.c' object='verify_packages.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o verify_packages.obj `if test -f '../../cf-agent/verify_packages.c'; then $(CYGPATH_W) '../../cf-agent/verify_packages.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/verify_packages.c'; fi` vercmp.o: ../../cf-agent/vercmp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vercmp.o -MD -MP -MF $(DEPDIR)/vercmp.Tpo -c -o vercmp.o `test -f '../../cf-agent/vercmp.c' || echo '$(srcdir)/'`../../cf-agent/vercmp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vercmp.Tpo $(DEPDIR)/vercmp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/vercmp.c' object='vercmp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vercmp.o `test -f '../../cf-agent/vercmp.c' || echo '$(srcdir)/'`../../cf-agent/vercmp.c vercmp.obj: ../../cf-agent/vercmp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vercmp.obj -MD -MP -MF $(DEPDIR)/vercmp.Tpo -c -o vercmp.obj `if test -f '../../cf-agent/vercmp.c'; then $(CYGPATH_W) '../../cf-agent/vercmp.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/vercmp.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vercmp.Tpo $(DEPDIR)/vercmp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/vercmp.c' object='vercmp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vercmp.obj `if test -f '../../cf-agent/vercmp.c'; then $(CYGPATH_W) '../../cf-agent/vercmp.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/vercmp.c'; fi` vercmp_internal.o: ../../cf-agent/vercmp_internal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vercmp_internal.o -MD -MP -MF $(DEPDIR)/vercmp_internal.Tpo -c -o vercmp_internal.o `test -f '../../cf-agent/vercmp_internal.c' || echo '$(srcdir)/'`../../cf-agent/vercmp_internal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vercmp_internal.Tpo $(DEPDIR)/vercmp_internal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/vercmp_internal.c' object='vercmp_internal.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vercmp_internal.o `test -f '../../cf-agent/vercmp_internal.c' || echo '$(srcdir)/'`../../cf-agent/vercmp_internal.c vercmp_internal.obj: ../../cf-agent/vercmp_internal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT vercmp_internal.obj -MD -MP -MF $(DEPDIR)/vercmp_internal.Tpo -c -o vercmp_internal.obj `if test -f '../../cf-agent/vercmp_internal.c'; then $(CYGPATH_W) '../../cf-agent/vercmp_internal.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/vercmp_internal.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/vercmp_internal.Tpo $(DEPDIR)/vercmp_internal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/vercmp_internal.c' object='vercmp_internal.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o vercmp_internal.obj `if test -f '../../cf-agent/vercmp_internal.c'; then $(CYGPATH_W) '../../cf-agent/vercmp_internal.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/vercmp_internal.c'; fi` retcode.o: ../../cf-agent/retcode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT retcode.o -MD -MP -MF $(DEPDIR)/retcode.Tpo -c -o retcode.o `test -f '../../cf-agent/retcode.c' || echo '$(srcdir)/'`../../cf-agent/retcode.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/retcode.Tpo $(DEPDIR)/retcode.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/retcode.c' object='retcode.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retcode.o `test -f '../../cf-agent/retcode.c' || echo '$(srcdir)/'`../../cf-agent/retcode.c retcode.obj: ../../cf-agent/retcode.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT retcode.obj -MD -MP -MF $(DEPDIR)/retcode.Tpo -c -o retcode.obj `if test -f '../../cf-agent/retcode.c'; then $(CYGPATH_W) '../../cf-agent/retcode.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/retcode.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/retcode.Tpo $(DEPDIR)/retcode.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/retcode.c' object='retcode.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o retcode.obj `if test -f '../../cf-agent/retcode.c'; then $(CYGPATH_W) '../../cf-agent/retcode.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/retcode.c'; fi` match_scope.o: ../../cf-agent/match_scope.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT match_scope.o -MD -MP -MF $(DEPDIR)/match_scope.Tpo -c -o match_scope.o `test -f '../../cf-agent/match_scope.c' || echo '$(srcdir)/'`../../cf-agent/match_scope.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/match_scope.Tpo $(DEPDIR)/match_scope.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/match_scope.c' object='match_scope.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o match_scope.o `test -f '../../cf-agent/match_scope.c' || echo '$(srcdir)/'`../../cf-agent/match_scope.c match_scope.obj: ../../cf-agent/match_scope.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT match_scope.obj -MD -MP -MF $(DEPDIR)/match_scope.Tpo -c -o match_scope.obj `if test -f '../../cf-agent/match_scope.c'; then $(CYGPATH_W) '../../cf-agent/match_scope.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/match_scope.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/match_scope.Tpo $(DEPDIR)/match_scope.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-agent/match_scope.c' object='match_scope.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o match_scope.obj `if test -f '../../cf-agent/match_scope.c'; then $(CYGPATH_W) '../../cf-agent/match_scope.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-agent/match_scope.c'; fi` cf-serverd-functions.o: ../../cf-serverd/cf-serverd-functions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cf-serverd-functions.o -MD -MP -MF $(DEPDIR)/cf-serverd-functions.Tpo -c -o cf-serverd-functions.o `test -f '../../cf-serverd/cf-serverd-functions.c' || echo '$(srcdir)/'`../../cf-serverd/cf-serverd-functions.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf-serverd-functions.Tpo $(DEPDIR)/cf-serverd-functions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/cf-serverd-functions.c' object='cf-serverd-functions.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cf-serverd-functions.o `test -f '../../cf-serverd/cf-serverd-functions.c' || echo '$(srcdir)/'`../../cf-serverd/cf-serverd-functions.c cf-serverd-functions.obj: ../../cf-serverd/cf-serverd-functions.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cf-serverd-functions.obj -MD -MP -MF $(DEPDIR)/cf-serverd-functions.Tpo -c -o cf-serverd-functions.obj `if test -f '../../cf-serverd/cf-serverd-functions.c'; then $(CYGPATH_W) '../../cf-serverd/cf-serverd-functions.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/cf-serverd-functions.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf-serverd-functions.Tpo $(DEPDIR)/cf-serverd-functions.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../cf-serverd/cf-serverd-functions.c' object='cf-serverd-functions.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cf-serverd-functions.obj `if test -f '../../cf-serverd/cf-serverd-functions.c'; then $(CYGPATH_W) '../../cf-serverd/cf-serverd-functions.c'; else $(CYGPATH_W) '$(srcdir)/../../cf-serverd/cf-serverd-functions.c'; fi` refcount.o: ../../libutils/refcount.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT refcount.o -MD -MP -MF $(DEPDIR)/refcount.Tpo -c -o refcount.o `test -f '../../libutils/refcount.c' || echo '$(srcdir)/'`../../libutils/refcount.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/refcount.Tpo $(DEPDIR)/refcount.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/refcount.c' object='refcount.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o refcount.o `test -f '../../libutils/refcount.c' || echo '$(srcdir)/'`../../libutils/refcount.c refcount.obj: ../../libutils/refcount.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT refcount.obj -MD -MP -MF $(DEPDIR)/refcount.Tpo -c -o refcount.obj `if test -f '../../libutils/refcount.c'; then $(CYGPATH_W) '../../libutils/refcount.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/refcount.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/refcount.Tpo $(DEPDIR)/refcount.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/refcount.c' object='refcount.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o refcount.obj `if test -f '../../libutils/refcount.c'; then $(CYGPATH_W) '../../libutils/refcount.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/refcount.c'; fi` rlist.o: ../../libpromises/rlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rlist.o -MD -MP -MF $(DEPDIR)/rlist.Tpo -c -o rlist.o `test -f '../../libpromises/rlist.c' || echo '$(srcdir)/'`../../libpromises/rlist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rlist.Tpo $(DEPDIR)/rlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/rlist.c' object='rlist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rlist.o `test -f '../../libpromises/rlist.c' || echo '$(srcdir)/'`../../libpromises/rlist.c rlist.obj: ../../libpromises/rlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rlist.obj -MD -MP -MF $(DEPDIR)/rlist.Tpo -c -o rlist.obj `if test -f '../../libpromises/rlist.c'; then $(CYGPATH_W) '../../libpromises/rlist.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/rlist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rlist.Tpo $(DEPDIR)/rlist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/rlist.c' object='rlist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rlist.obj `if test -f '../../libpromises/rlist.c'; then $(CYGPATH_W) '../../libpromises/rlist.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/rlist.c'; fi` logging.o: ../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logging.o -MD -MP -MF $(DEPDIR)/logging.Tpo -c -o logging.o `test -f '../../libutils/logging.c' || echo '$(srcdir)/'`../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logging.Tpo $(DEPDIR)/logging.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/logging.c' object='logging.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logging.o `test -f '../../libutils/logging.c' || echo '$(srcdir)/'`../../libutils/logging.c logging.obj: ../../libutils/logging.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logging.obj -MD -MP -MF $(DEPDIR)/logging.Tpo -c -o logging.obj `if test -f '../../libutils/logging.c'; then $(CYGPATH_W) '../../libutils/logging.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/logging.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logging.Tpo $(DEPDIR)/logging.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/logging.c' object='logging.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logging.obj `if test -f '../../libutils/logging.c'; then $(CYGPATH_W) '../../libutils/logging.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/logging.c'; fi` process_solaris.o: ../../libpromises/process_solaris.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_solaris.o -MD -MP -MF $(DEPDIR)/process_solaris.Tpo -c -o process_solaris.o `test -f '../../libpromises/process_solaris.c' || echo '$(srcdir)/'`../../libpromises/process_solaris.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_solaris.Tpo $(DEPDIR)/process_solaris.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_solaris.c' object='process_solaris.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_solaris.o `test -f '../../libpromises/process_solaris.c' || echo '$(srcdir)/'`../../libpromises/process_solaris.c process_solaris.obj: ../../libpromises/process_solaris.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process_solaris.obj -MD -MP -MF $(DEPDIR)/process_solaris.Tpo -c -o process_solaris.obj `if test -f '../../libpromises/process_solaris.c'; then $(CYGPATH_W) '../../libpromises/process_solaris.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_solaris.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/process_solaris.Tpo $(DEPDIR)/process_solaris.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libpromises/process_solaris.c' object='process_solaris.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process_solaris.obj `if test -f '../../libpromises/process_solaris.c'; then $(CYGPATH_W) '../../libpromises/process_solaris.c'; else $(CYGPATH_W) '$(srcdir)/../../libpromises/process_solaris.c'; fi` xml_writer.o: ../../libutils/xml_writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xml_writer.o -MD -MP -MF $(DEPDIR)/xml_writer.Tpo -c -o xml_writer.o `test -f '../../libutils/xml_writer.c' || echo '$(srcdir)/'`../../libutils/xml_writer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_writer.Tpo $(DEPDIR)/xml_writer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/xml_writer.c' object='xml_writer.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xml_writer.o `test -f '../../libutils/xml_writer.c' || echo '$(srcdir)/'`../../libutils/xml_writer.c xml_writer.obj: ../../libutils/xml_writer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xml_writer.obj -MD -MP -MF $(DEPDIR)/xml_writer.Tpo -c -o xml_writer.obj `if test -f '../../libutils/xml_writer.c'; then $(CYGPATH_W) '../../libutils/xml_writer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/xml_writer.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_writer.Tpo $(DEPDIR)/xml_writer.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../libutils/xml_writer.c' object='xml_writer.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xml_writer.obj `if test -f '../../libutils/xml_writer.c'; then $(CYGPATH_W) '../../libutils/xml_writer.c'; else $(CYGPATH_W) '$(srcdir)/../../libutils/xml_writer.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_LTLIBRARIES) $(check_PROGRAMS) $(check_SCRIPTS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? arg_split_test.log: arg_split_test$(EXEEXT) @p='arg_split_test$(EXEEXT)'; \ b='arg_split_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) assoc_test.log: assoc_test$(EXEEXT) @p='assoc_test$(EXEEXT)'; \ b='assoc_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) atexit_test.log: atexit_test$(EXEEXT) @p='atexit_test$(EXEEXT)'; \ b='atexit_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) csv_writer_test.log: csv_writer_test$(EXEEXT) @p='csv_writer_test$(EXEEXT)'; \ b='csv_writer_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) item_test.log: item_test$(EXEEXT) @p='item_test$(EXEEXT)'; \ b='item_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) rlist_test.log: rlist_test$(EXEEXT) @p='rlist_test$(EXEEXT)'; \ b='rlist_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) domainname_test.log: domainname_test$(EXEEXT) @p='domainname_test$(EXEEXT)'; \ b='domainname_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) set_test.log: set_test$(EXEEXT) @p='set_test$(EXEEXT)'; \ b='set_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) set_domainname_test.log: set_domainname_test$(EXEEXT) @p='set_domainname_test$(EXEEXT)'; \ b='set_domainname_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) str_test.log: str_test$(EXEEXT) @p='str_test$(EXEEXT)'; \ b='str_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) json_test.log: json_test$(EXEEXT) @p='json_test$(EXEEXT)'; \ b='json_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) csv_parser_test.log: csv_parser_test$(EXEEXT) @p='csv_parser_test$(EXEEXT)'; \ b='csv_parser_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) evalfunction_test.log: evalfunction_test$(EXEEXT) @p='evalfunction_test$(EXEEXT)'; \ b='evalfunction_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) eval_context_test.log: eval_context_test$(EXEEXT) @p='eval_context_test$(EXEEXT)'; \ b='eval_context_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) regex_test.log: regex_test$(EXEEXT) @p='regex_test$(EXEEXT)'; \ b='regex_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) alloc_test.log: alloc_test$(EXEEXT) @p='alloc_test$(EXEEXT)'; \ b='alloc_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) string_writer_test.log: string_writer_test$(EXEEXT) @p='string_writer_test$(EXEEXT)'; \ b='string_writer_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) file_writer_test.log: file_writer_test$(EXEEXT) @p='file_writer_test$(EXEEXT)'; \ b='file_writer_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) xml_writer_test.log: xml_writer_test$(EXEEXT) @p='xml_writer_test$(EXEEXT)'; \ b='xml_writer_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) sequence_test.log: sequence_test$(EXEEXT) @p='sequence_test$(EXEEXT)'; \ b='sequence_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) lastseen_test.log: lastseen_test$(EXEEXT) @p='lastseen_test$(EXEEXT)'; \ b='lastseen_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) lastseen_migration_test.log: lastseen_migration_test$(EXEEXT) @p='lastseen_migration_test$(EXEEXT)'; \ b='lastseen_migration_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) changes_migration_test.log: changes_migration_test$(EXEEXT) @p='changes_migration_test$(EXEEXT)'; \ b='changes_migration_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) db_test.log: db_test$(EXEEXT) @p='db_test$(EXEEXT)'; \ b='db_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) db_concurrent_test.log: db_concurrent_test$(EXEEXT) @p='db_concurrent_test$(EXEEXT)'; \ b='db_concurrent_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) dbm_migration_bundles_test.log: dbm_migration_bundles_test$(EXEEXT) @p='dbm_migration_bundles_test$(EXEEXT)'; \ b='dbm_migration_bundles_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) misc_lib_test.log: misc_lib_test$(EXEEXT) @p='misc_lib_test$(EXEEXT)'; \ b='misc_lib_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) item_lib_test.log: item_lib_test$(EXEEXT) @p='item_lib_test$(EXEEXT)'; \ b='item_lib_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) crypto_symmetric_test.log: crypto_symmetric_test$(EXEEXT) @p='crypto_symmetric_test$(EXEEXT)'; \ b='crypto_symmetric_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) persistent_lock_test.log: persistent_lock_test$(EXEEXT) @p='persistent_lock_test$(EXEEXT)'; \ b='persistent_lock_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) thread_test.log: thread_test$(EXEEXT) @p='thread_test$(EXEEXT)'; \ b='thread_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) package_versions_compare_test.log: package_versions_compare_test$(EXEEXT) @p='package_versions_compare_test$(EXEEXT)'; \ b='package_versions_compare_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) files_lib_test.log: files_lib_test$(EXEEXT) @p='files_lib_test$(EXEEXT)'; \ b='files_lib_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) file_lib_test.log: file_lib_test$(EXEEXT) @p='file_lib_test$(EXEEXT)'; \ b='file_lib_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) map_test.log: map_test$(EXEEXT) @p='map_test$(EXEEXT)'; \ b='map_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) parsemode_test.log: parsemode_test$(EXEEXT) @p='parsemode_test$(EXEEXT)'; \ b='parsemode_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) parser_test.log: parser_test$(EXEEXT) @p='parser_test$(EXEEXT)'; \ b='parser_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) policy_test.log: policy_test$(EXEEXT) @p='policy_test$(EXEEXT)'; \ b='policy_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) sort_test.log: sort_test$(EXEEXT) @p='sort_test$(EXEEXT)'; \ b='sort_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) file_name_test.log: file_name_test$(EXEEXT) @p='file_name_test$(EXEEXT)'; \ b='file_name_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) logging_test.log: logging_test$(EXEEXT) @p='logging_test$(EXEEXT)'; \ b='logging_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) logging_timestamp_test.log: logging_timestamp_test$(EXEEXT) @p='logging_timestamp_test$(EXEEXT)'; \ b='logging_timestamp_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) granules_test.log: granules_test$(EXEEXT) @p='granules_test$(EXEEXT)'; \ b='granules_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) scope_test.log: scope_test$(EXEEXT) @p='scope_test$(EXEEXT)'; \ b='scope_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) conversion_test.log: conversion_test$(EXEEXT) @p='conversion_test$(EXEEXT)'; \ b='conversion_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) files_interfaces_test.log: files_interfaces_test$(EXEEXT) @p='files_interfaces_test$(EXEEXT)'; \ b='files_interfaces_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) refcount_test.log: refcount_test$(EXEEXT) @p='refcount_test$(EXEEXT)'; \ b='refcount_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) list_test.log: list_test$(EXEEXT) @p='list_test$(EXEEXT)'; \ b='list_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) buffer_test.log: buffer_test$(EXEEXT) @p='buffer_test$(EXEEXT)'; \ b='buffer_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) cf_key_functions_test.log: cf_key_functions_test$(EXEEXT) @p='cf_key_functions_test$(EXEEXT)'; \ b='cf_key_functions_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) connection_management_test.log: connection_management_test$(EXEEXT) @p='connection_management_test$(EXEEXT)'; \ b='connection_management_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) expand_test.log: expand_test$(EXEEXT) @p='expand_test$(EXEEXT)'; \ b='expand_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) string_expressions_test.log: string_expressions_test$(EXEEXT) @p='string_expressions_test$(EXEEXT)'; \ b='string_expressions_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) var_expressions_test.log: var_expressions_test$(EXEEXT) @p='var_expressions_test$(EXEEXT)'; \ b='var_expressions_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) process_terminate_unix_test.log: process_terminate_unix_test$(EXEEXT) @p='process_terminate_unix_test$(EXEEXT)'; \ b='process_terminate_unix_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) exec-config-test.log: exec-config-test$(EXEEXT) @p='exec-config-test$(EXEEXT)'; \ b='exec-config-test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) generic_agent_test.log: generic_agent_test$(EXEEXT) @p='generic_agent_test$(EXEEXT)'; \ b='generic_agent_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) syntax_test.log: syntax_test$(EXEEXT) @p='syntax_test$(EXEEXT)'; \ b='syntax_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) sysinfo_test.log: sysinfo_test$(EXEEXT) @p='sysinfo_test$(EXEEXT)'; \ b='sysinfo_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ipaddress_test.log: ipaddress_test$(EXEEXT) @p='ipaddress_test$(EXEEXT)'; \ b='ipaddress_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) hashes_test.log: hashes_test$(EXEEXT) @p='hashes_test$(EXEEXT)'; \ b='hashes_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) rb-tree-test.log: rb-tree-test$(EXEEXT) @p='rb-tree-test$(EXEEXT)'; \ b='rb-tree-test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) variable_test.log: variable_test$(EXEEXT) @p='variable_test$(EXEEXT)'; \ b='variable_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) protocol_test.log: protocol_test$(EXEEXT) @p='protocol_test$(EXEEXT)'; \ b='protocol_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) mon_cpu_test.log: mon_cpu_test$(EXEEXT) @p='mon_cpu_test$(EXEEXT)'; \ b='mon_cpu_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) mon_load_test.log: mon_load_test$(EXEEXT) @p='mon_load_test$(EXEEXT)'; \ b='mon_load_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) mon_processes_test.log: mon_processes_test$(EXEEXT) @p='mon_processes_test$(EXEEXT)'; \ b='mon_processes_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) mustache_test.log: mustache_test$(EXEEXT) @p='mustache_test$(EXEEXT)'; \ b='mustache_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) class_test.log: class_test$(EXEEXT) @p='class_test$(EXEEXT)'; \ b='class_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) version_test.log: version_test$(EXEEXT) @p='version_test$(EXEEXT)'; \ b='version_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) hash_test.log: hash_test$(EXEEXT) @p='hash_test$(EXEEXT)'; \ b='hash_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) key_test.log: key_test$(EXEEXT) @p='key_test$(EXEEXT)'; \ b='key_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) cf_upgrade_test.log: cf_upgrade_test$(EXEEXT) @p='cf_upgrade_test$(EXEEXT)'; \ b='cf_upgrade_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) queue_test.log: queue_test$(EXEEXT) @p='queue_test$(EXEEXT)'; \ b='queue_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) matching_test.log: matching_test$(EXEEXT) @p='matching_test$(EXEEXT)'; \ b='matching_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) ring_buffer_test.log: ring_buffer_test$(EXEEXT) @p='ring_buffer_test$(EXEEXT)'; \ b='ring_buffer_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) strlist_test.log: strlist_test$(EXEEXT) @p='strlist_test$(EXEEXT)'; \ b='strlist_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) addr_lib_test.log: addr_lib_test$(EXEEXT) @p='addr_lib_test$(EXEEXT)'; \ b='addr_lib_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) libcompat_test.log: libcompat_test$(EXEEXT) @p='libcompat_test$(EXEEXT)'; \ b='libcompat_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) findhub_test.log: findhub_test$(EXEEXT) @p='findhub_test$(EXEEXT)'; \ b='findhub_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) avahi_config_test.log: avahi_config_test$(EXEEXT) @p='avahi_config_test$(EXEEXT)'; \ b='avahi_config_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) enterprise_extension_test.log: enterprise_extension_test$(EXEEXT) @p='enterprise_extension_test$(EXEEXT)'; \ b='enterprise_extension_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) linux_process_test.log: linux_process_test$(EXEEXT) @p='linux_process_test$(EXEEXT)'; \ b='linux_process_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) aix_process_test.log: aix_process_test$(EXEEXT) @p='aix_process_test$(EXEEXT)'; \ b='aix_process_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) solaris_process_test.log: solaris_process_test$(EXEEXT) @p='solaris_process_test$(EXEEXT)'; \ b='solaris_process_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) tls_generic_test.log: tls_generic_test$(EXEEXT) @p='tls_generic_test$(EXEEXT)'; \ b='tls_generic_test'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) dynamic_dependency_test.sh.log: dynamic_dependency_test.sh @p='dynamic_dependency_test.sh'; \ b='dynamic_dependency_test.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) 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 $(MAKE) $(AM_MAKEFLAGS) $(check_LTLIBRARIES) $(check_PROGRAMS) \ $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ clean-libtool 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: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkLTLIBRARIES clean-checkPROGRAMS clean-generic \ clean-libtool cscopelist-am ctags ctags-am 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 recheck tags tags-am uninstall \ uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/tests/unit/set_domainname_test.c0000664000175100017510000000406712400110676021331 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include /* Global variables we care about */ char VFQNAME[CF_MAXVARSIZE]; char VUQNAME[CF_MAXVARSIZE]; char VDOMAIN[CF_MAXVARSIZE]; static struct hostent h = { .h_name = "laptop.intra.cfengine.com" }; #ifdef SOLARIS int gethostname(char *name, ARG_UNUSED int len) #else int gethostname(char *name, ARG_UNUSED size_t len) #endif { strcpy(name, "laptop.intra"); return 0; } struct hostent *gethostbyname(const char *name) { assert_string_equal(name, "laptop.intra"); return &h; } typedef struct { const char *name; const char *value; bool found; } ExpectedVars; ExpectedVars expected_vars[] = { {"host", "laptop.intra"}, {"fqhost", "laptop.intra.cfengine.com"}, {"uqhost", "laptop.intra"}, {"domain", "cfengine.com"}, }; static void TestSysVar(EvalContext *ctx, const char *lval, const char *expected) { #ifdef _AIX return; //redmine6317 #endif VarRef *ref = VarRefParseFromScope(lval, "sys"); assert_string_equal(expected, EvalContextVariableGet(ctx, ref, NULL)); VarRefDestroy(ref); } static void test_set_names(void) { EvalContext *ctx = EvalContextNew(); DetectDomainName(ctx, "laptop.intra"); assert_true(!EvalContextClassGet(ctx, NULL, "laptop_intra_cfengine_com")->is_soft); assert_true(!EvalContextClassGet(ctx, NULL, "intra_cfengine_com")->is_soft); assert_true(!EvalContextClassGet(ctx, NULL, "cfengine_com")->is_soft); assert_true(!EvalContextClassGet(ctx, NULL, "com")->is_soft); assert_true(!EvalContextClassGet(ctx, NULL, "laptop_intra")->is_soft); TestSysVar(ctx, "host", "laptop.intra"); TestSysVar(ctx, "fqhost", "laptop.intra.cfengine.com"); TestSysVar(ctx, "uqhost", "laptop.intra"); TestSysVar(ctx, "domain", "cfengine.com"); EvalContextDestroy(ctx); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_set_names), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/file_name_test.c0000664000175100017510000000640512400110676020263 0ustar00a10038a1003800000000000000#include #include static void test_first_file_separator(void) { const char *out; const char *in = "/tmp/myfile"; out = FirstFileSeparator(in); assert_true(out == in); in = "tmp/myfile"; out = FirstFileSeparator(in); assert_true(out == in + 3); in = "c:/tmp/myfile"; out = FirstFileSeparator(in); assert_true(out == in + 2); in = "\\\\my\\windows\\share"; out = FirstFileSeparator(in); assert_true(out == in + 1); } static void test_get_parent_directory_copy(void) { char *out; #ifndef _WIN32 /* unix, will fail on windows because of IsFileSep */ out = GetParentDirectoryCopy("/some/path/here"); assert_string_equal(out, "/some/path"); free(out); out = GetParentDirectoryCopy("/some/path/here/dir/"); assert_string_equal(out, "/some/path/here/dir"); free(out); out = GetParentDirectoryCopy("/some/path/here/dir/."); assert_string_equal(out, "/some/path/here/dir"); free(out); out = GetParentDirectoryCopy("/some"); assert_string_equal(out, "/"); free(out); #else /* _WIN32 */ /* windows, will fail on unix because of IsFileSep */ out = GetParentDirectoryCopy("c:\\some\\path with space\\here and now"); assert_string_equal(out, "c:\\some\\path with space"); free(out); out = GetParentDirectoryCopy("c:\\some"); assert_string_equal(out, "c:\\"); free(out); out = GetParentDirectoryCopy("\\\\some\\path"); assert_string_equal(out, "\\\\some"); free(out); out = GetParentDirectoryCopy("\\\\some"); assert_string_equal(out, "\\\\"); free(out); #endif /* _WIN32 */ } static void test_delete_redundant_slashes(void) { { char str[] = "///a//b////c/"; DeleteRedundantSlashes(str); assert_string_equal(str, "/a/b/c/"); } { char str[] = "a//b////c/"; DeleteRedundantSlashes(str); assert_string_equal(str, "a/b/c/"); } { char str[] = "/a/b/c/"; DeleteRedundantSlashes(str); assert_string_equal(str, "/a/b/c/"); } { char str[] = "a///b////c///"; DeleteRedundantSlashes(str); assert_string_equal(str, "a/b/c/"); } { char str[] = "a///b////c"; DeleteRedundantSlashes(str); assert_string_equal(str, "a/b/c"); } { char str[] = "a///b/c"; DeleteRedundantSlashes(str); assert_string_equal(str, "a/b/c"); } { char str[] = "alpha///beta/charlie///zeta"; DeleteRedundantSlashes(str); assert_string_equal(str, "alpha/beta/charlie/zeta"); } { char str[] = "////alpha///beta/charlie///zeta///"; DeleteRedundantSlashes(str); assert_string_equal(str, "/alpha/beta/charlie/zeta/"); } { char str[] = "/a"; DeleteRedundantSlashes(str); assert_string_equal(str, "/a"); } { char str[] = "/alpha"; DeleteRedundantSlashes(str); assert_string_equal(str, "/alpha"); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_first_file_separator), unit_test(test_get_parent_directory_copy), unit_test(test_delete_redundant_slashes) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/db_test.c0000664000175100017510000001117512400110676016731 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ char CFWORKDIR[CF_BUFSIZE]; void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/db_test.XXXXXX"); mkdtemp(CFWORKDIR); } void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } void test_open_close(void) { // Test that we can simply open and close a database without doing anything. CF_DB *db; assert_int_equal(OpenDB(&db, dbid_classes), true); CloseDB(db); } void test_read_write(void) { // Test that we can do normal reads and write, and that the values are // reflected in the database. CF_DB *db; char value[CF_BUFSIZE]; strcpy(value, "myvalue"); int vsize = strlen(value) + 1; assert_int_equal(OpenDB(&db, dbid_classes), true); assert_int_equal(ReadDB(db, "written_entry", &value, vsize), false); assert_string_equal(value, "myvalue"); assert_int_equal(WriteDB(db, "written_entry", value, vsize), true); strcpy(value, ""); assert_int_equal(ReadDB(db, "written_entry", &value, vsize), true); assert_string_equal(value, "myvalue"); CloseDB(db); // Check also after we reopen the database. assert_int_equal(OpenDB(&db, dbid_classes), true); strcpy(value, ""); assert_int_equal(ReadDB(db, "written_entry", &value, vsize), true); assert_string_equal(value, "myvalue"); CloseDB(db); } void test_iter_modify_entry(void) { /* Test that deleting entry under cursor does not interrupt iteration */ CF_DB *db; assert_int_equal(OpenDB(&db, dbid_classes), true); assert_int_equal(WriteDB(db, "foobar", "abc", 3), true); assert_int_equal(WriteDB(db, "bazbaz", "def", 3), true); assert_int_equal(WriteDB(db, "booo", "ghi", 3), true); CF_DBC *cursor; assert_int_equal(NewDBCursor(db, &cursor), true); char *key; int ksize; void *value; int vsize; assert_int_equal(NextDB(cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(DBCursorWriteEntry(cursor, "eee", 3), true); assert_int_equal(NextDB(cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(NextDB(cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(DeleteDBCursor(cursor), true); CloseDB(db); } void test_iter_delete_entry(void) { /* Test that deleting entry under cursor does not interrupt iteration */ CF_DB *db; assert_int_equal(OpenDB(&db, dbid_classes), true); assert_int_equal(WriteDB(db, "foobar", "abc", 3), true); assert_int_equal(WriteDB(db, "bazbaz", "def", 3), true); assert_int_equal(WriteDB(db, "booo", "ghi", 3), true); CF_DBC *cursor; assert_int_equal(NewDBCursor(db, &cursor), true); char *key; int ksize; void *value; int vsize; assert_int_equal(NextDB(cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(DBCursorDeleteEntry(cursor), true); assert_int_equal(NextDB(cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(NextDB(cursor, &key, &ksize, &value, &vsize), true); assert_int_equal(DeleteDBCursor(cursor), true); CloseDB(db); } #if defined(HAVE_LIBTOKYOCABINET) || defined(HAVE_LIBQDBM) || defined(HAVE_LIBLMDB) static void CreateGarbage(const char *filename) { FILE *fh = fopen(filename, "w"); for(int i = 0; i < 2; ++i) { fwrite("some garbage!", 14, 1, fh); } fclose(fh); } #endif /* HAVE_LIBTOKYOCABINET || HAVE_LIBQDBM */ void test_recreate(void) { /* Test that recreating database works properly */ #ifdef HAVE_LIBTOKYOCABINET char tcdb_db[CF_BUFSIZE]; xsnprintf(tcdb_db, CF_BUFSIZE, "%s/cf_classes.tcdb", CFWORKDIR); CreateGarbage(tcdb_db); #endif #ifdef HAVE_LIBQDBM char qdbm_db[CF_BUFSIZE]; xsnprintf(qdbm_db, CF_BUFSIZE, "%s/cf_classes.qdbm", CFWORKDIR); CreateGarbage(qdbm_db); #endif #ifdef HAVE_LIBLMDB char lmdb_db[CF_BUFSIZE]; xsnprintf(lmdb_db, CF_BUFSIZE, "%s/cf_classes.lmdb", CFWORKDIR); CreateGarbage(lmdb_db); #endif CF_DB *db; assert_int_equal(OpenDB(&db, dbid_classes), true); CloseDB(db); } int main() { PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { unit_test(test_open_close), unit_test(test_read_write), unit_test(test_iter_modify_entry), unit_test(test_iter_delete_entry), unit_test(test_recreate), }; PRINT_TEST_BANNER(); int ret = run_tests(tests); tests_teardown(); return ret; } /* STUBS */ void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } cfengine-3.6.2/tests/unit/enterprise_extension_test.c0000664000175100017510000000432312400110676022615 0ustar00a10038a1003800000000000000#include #include #include #include ENTERPRISE_FUNC_2ARG_DECLARE(int64_t, extension_function, int32_t, short_int, int64_t, long_int); ENTERPRISE_FUNC_2ARG_DECLARE(int64_t, extension_function_broken, int32_t, short_int, int64_t, long_int); ENTERPRISE_FUNC_2ARG_DEFINE_STUB(int64_t, extension_function, int32_t, short_int, int64_t, long_int) { return short_int + long_int; } ENTERPRISE_FUNC_2ARG_DEFINE_STUB(int64_t, extension_function_broken, int32_t, short_int, int64_t, long_int) { return short_int + long_int; } static void test_extension_function_stub(void) { putenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR=nonexistingdir"); assert_int_equal(extension_function(2, 3), 5); unsetenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR"); } static void test_extension_function(void) { putenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR=.libs"); assert_int_equal(extension_function(2, 3), 6); unsetenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR"); } static void test_extension_function_broken(void) { putenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR=.libs"); // This one should call the stub, even if the extension is available, because the // function signature is different. assert_int_equal(extension_function_broken(2, 3), 5); unsetenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR"); } static void test_extension_function_version_mismatch() { putenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR=.libs"); putenv("CFENGINE_TEST_RETURN_VERSION=1.1.1"); // This one should call the stub, even if the extension is available, because the // version is different. assert_int_equal(extension_function(2, 3), 5); unsetenv("CFENGINE_TEST_RETURN_VERSION"); unsetenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR"); } int main() { putenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE=1"); PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_extension_function_stub), unit_test(test_extension_function), unit_test(test_extension_function_broken), unit_test(test_extension_function_version_mismatch), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/cmockery.c0000664000175100017510000021545512400110676017130 0ustar00a10038a1003800000000000000/* LCOV_EXCL_STOP */ /* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* LCOV_EXCL_START */ #ifdef HAVE_CONFIG_H # include #endif #ifdef HAVE_MALLOC_H # include #endif #include #ifndef _WIN32 # include #endif // !_WIN32 #include #include #include #include #include #include #include #include #ifdef _WIN32 # include #endif // _WIN32 #include #include #include /* Backwards compatibility with headers shipped with Visual Studio 2005 and * earlier. */ #ifdef _WIN32 WINBASEAPI BOOL WINAPI IsDebuggerPresent(VOID); #endif // _WIN32 // Size of guard bytes around dynamically allocated blocks. #define MALLOC_GUARD_SIZE 16 // Pattern used to initialize guard blocks. #define MALLOC_GUARD_PATTERN 0xEF // Pattern used to initialize memory allocated with test_malloc(). #define MALLOC_ALLOC_PATTERN 0xBA #define MALLOC_FREE_PATTERN 0xCD // Alignment of allocated blocks. NOTE: This must be base2. #define MALLOC_ALIGNMENT sizeof(size_t) // Printf formatting for source code locations. #define SOURCE_LOCATION_FORMAT "%s:%d" // Calculates the number of elements in an array. #define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0])) // Declare and initialize the pointer member of ValuePointer variable name // with ptr. #define declare_initialize_value_pointer_pointer(name, ptr) \ ValuePointer name ; \ name.value = 0; \ name.pointer = (void*)(ptr) // Declare and initialize the value member of ValuePointer variable name // with val. #define declare_initialize_value_pointer_value(name, val) \ ValuePointer name ; \ name.value = val // Cast a LargestIntegralType to pointer_type via a ValuePointer. #define cast_largest_integral_type_to_pointer( \ pointer_type, largest_integral_type) \ ((pointer_type)((ValuePointer*)&(largest_integral_type))->pointer) // Used to cast LargestIntegralType to void* and vice versa. typedef union ValuePointer { LargestIntegralType value; void *pointer; } ValuePointer; // Doubly linked list node. typedef struct ListNode { const void *value; int refcount; struct ListNode *next; struct ListNode *prev; } ListNode; // Debug information for malloc(). typedef struct MallocBlockInfo { void *block; // Address of the block returned by malloc(). size_t allocated_size; // Total size of the allocated block. size_t size; // Request block size. SourceLocation location; // Where the block was allocated. ListNode node; // Node within list of all allocated blocks. } MallocBlockInfo; // State of each test. typedef struct TestState { const ListNode *check_point; // Check point of the test if there's a // setup function. void *state; // State associated with the test. } TestState; // Determines whether two values are the same. typedef int (*EqualityFunction) (const void *left, const void *right); // Value of a symbol and the place it was declared. typedef struct SymbolValue { SourceLocation location; LargestIntegralType value; } SymbolValue; /* Contains a list of values for a symbol. * NOTE: Each structure referenced by symbol_values_list_head must have a * SourceLocation as its' first member. */ typedef struct SymbolMapValue { const char *symbol_name; ListNode symbol_values_list_head; } SymbolMapValue; // Used by list_free() to deallocate values referenced by list nodes. typedef void (*CleanupListValue) (const void *value, void *cleanup_value_data); // Structure used to check the range of integer types. typedef struct CheckIntegerRange { CheckParameterEvent event; LargestIntegralType minimum; LargestIntegralType maximum; } CheckIntegerRange; // Structure used to check whether an integer value is in a set. typedef struct CheckIntegerSet { CheckParameterEvent event; const LargestIntegralType *set; size_t size_of_set; } CheckIntegerSet; /* Used to check whether a parameter matches the area of memory referenced by * this structure. */ typedef struct CheckMemoryData { CheckParameterEvent event; const void *memory; size_t size; } CheckMemoryData; static ListNode *list_initialize(ListNode *const node); static ListNode *list_add(ListNode *const head, ListNode *new_node); static ListNode *list_add_value(ListNode *const head, const void *value, const int count); static ListNode *list_remove(ListNode *const node, const CleanupListValue cleanup_value, void *const cleanup_value_data); static void list_remove_free(ListNode *const node, const CleanupListValue cleanup_value, void *const cleanup_value_data); static int list_empty(const ListNode *const head); static int list_find(ListNode *const head, const void *value, const EqualityFunction equal_func, ListNode **output); static int list_first(ListNode *const head, ListNode **output); static ListNode *list_free(ListNode *const head, const CleanupListValue cleanup_value, void *const cleanup_value_data); static void add_symbol_value(ListNode *const symbol_map_head, const char *const symbol_names[], const size_t number_of_symbol_names, const void *value, const int count); static int get_symbol_value(ListNode *const symbol_map_head, const char *const symbol_names[], const size_t number_of_symbol_names, void **output); static void free_value(const void *value, void *cleanup_value_data); static void free_symbol_map_value(const void *value, void *cleanup_value_data); static void remove_always_return_values(ListNode *const map_head, const size_t number_of_symbol_names); static int check_for_leftover_values(const ListNode *const map_head, const char *const error_message, const size_t number_of_symbol_names); // This must be called at the beginning of a test to initialize some data // structures. static void initialize_testing(void); // This must be called at the end of a test to free() allocated structures. static void teardown_testing(void); // Keeps track of the calling context returned by setenv() so that the fail() // method can jump out of a test. static jmp_buf global_run_test_env; static int global_running_test = 0; // Keeps track of the calling context returned by setenv() so that // mock_assert() can optionally jump back to expect_assert_failure(). jmp_buf global_expect_assert_env; const char *global_expect_assert_expression; int global_expecting_assert = 0; // Keeps a map of the values that functions will have to return to provide // mocked interfaces. static ListNode global_function_result_map_head; // Location of the last mock value returned was declared. static SourceLocation global_last_mock_value_location; /* Keeps a map of the values that functions expect as parameters to their * mocked interfaces. */ static ListNode global_function_parameter_map_head; // Location of last parameter value checked was declared. static SourceLocation global_last_parameter_location; // List of all currently allocated blocks. static ListNode global_allocated_blocks; // Data of running tests for XML output. static int global_errors; static const char *global_filename; static const char *global_xmlfile; static int global_is_file_writer_test; /* bool, but type not defined here */ #ifndef _WIN32 // Signals caught by exception_handler(). static const int exception_signals[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, }; // Default signal functions that should be restored after a test is complete. typedef void (*SignalFunction) (int signal); static SignalFunction default_signal_functions[ARRAY_LENGTH(exception_signals)]; #else // _WIN32 // The default exception filter. static LPTOP_LEVEL_EXCEPTION_FILTER previous_exception_filter; // Fatal exceptions. typedef struct ExceptionCodeInfo { DWORD code; const char *description; } ExceptionCodeInfo; # define EXCEPTION_CODE_INFO(exception_code) {exception_code, #exception_code} static const ExceptionCodeInfo exception_codes[] = { EXCEPTION_CODE_INFO(EXCEPTION_ACCESS_VIOLATION), EXCEPTION_CODE_INFO(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), EXCEPTION_CODE_INFO(EXCEPTION_DATATYPE_MISALIGNMENT), EXCEPTION_CODE_INFO(EXCEPTION_FLT_DENORMAL_OPERAND), EXCEPTION_CODE_INFO(EXCEPTION_FLT_DIVIDE_BY_ZERO), EXCEPTION_CODE_INFO(EXCEPTION_FLT_INEXACT_RESULT), EXCEPTION_CODE_INFO(EXCEPTION_FLT_INVALID_OPERATION), EXCEPTION_CODE_INFO(EXCEPTION_FLT_OVERFLOW), EXCEPTION_CODE_INFO(EXCEPTION_FLT_STACK_CHECK), EXCEPTION_CODE_INFO(EXCEPTION_FLT_UNDERFLOW), EXCEPTION_CODE_INFO(EXCEPTION_GUARD_PAGE), EXCEPTION_CODE_INFO(EXCEPTION_ILLEGAL_INSTRUCTION), EXCEPTION_CODE_INFO(EXCEPTION_INT_DIVIDE_BY_ZERO), EXCEPTION_CODE_INFO(EXCEPTION_INT_OVERFLOW), EXCEPTION_CODE_INFO(EXCEPTION_INVALID_DISPOSITION), EXCEPTION_CODE_INFO(EXCEPTION_INVALID_HANDLE), EXCEPTION_CODE_INFO(EXCEPTION_IN_PAGE_ERROR), EXCEPTION_CODE_INFO(EXCEPTION_NONCONTINUABLE_EXCEPTION), EXCEPTION_CODE_INFO(EXCEPTION_PRIV_INSTRUCTION), EXCEPTION_CODE_INFO(EXCEPTION_STACK_OVERFLOW), }; #endif // !_WIN32 static void exit_test(void) FUNC_ATTR_NORETURN; // Exit the currently executing test. static void exit_test(void) { if (global_running_test) { longjmp(global_run_test_env, 1); } else { exit(-1); } } #ifdef _WIN32 // Exit the currently executing test. static void exit_test_no_app(void) { if (global_running_test) { longjmp(global_run_test_env, 1); } } #endif // Initialize a SourceLocation structure. static void initialize_source_location(SourceLocation *const location) { assert_true(location); location->file = NULL; location->line = 0; } // Determine whether a source location is currently set. static int source_location_is_set(const SourceLocation *const location) { assert_true(location); return location->file && location->line; } // Set a source location. static void set_source_location(SourceLocation *const location, const char *const file, const int line) { assert_true(location); location->file = file; location->line = line; } // Create function results and expected parameter lists. void initialize_testing(void) { list_initialize(&global_function_result_map_head); initialize_source_location(&global_last_mock_value_location); list_initialize(&global_function_parameter_map_head); initialize_source_location(&global_last_parameter_location); } static void fail_if_leftover_values(const char *test_name) { int error_occurred = 0; remove_always_return_values(&global_function_result_map_head, 1); if (check_for_leftover_values(&global_function_result_map_head, "%s() has remaining non-returned values.\n", 1)) { print_xml(XS_RUN_TEST_ERROR "\"%s() has remaining non-returned values.\">\n" XS_RUN_TEST_ERROR_END, "fail_if_leftover_values", test_name); error_occurred = 1; } remove_always_return_values(&global_function_parameter_map_head, 2); if (check_for_leftover_values(&global_function_parameter_map_head, "%s parameter still has values that haven't been checked.\n", 2)) { print_xml(XS_RUN_TEST_ERROR "\"%s parameter still has values that haven't been checked.\">\n" XS_RUN_TEST_ERROR_END, "fail_if_leftover_values", test_name); error_occurred = 1; } if (error_occurred) { global_errors++; exit_test(); } } void teardown_testing(void) { list_free(&global_function_result_map_head, free_symbol_map_value, (void *) 0); initialize_source_location(&global_last_mock_value_location); list_free(&global_function_parameter_map_head, free_symbol_map_value, (void *) 1); initialize_source_location(&global_last_parameter_location); } // Initialize a list node. static ListNode *list_initialize(ListNode *const node) { node->value = NULL; node->next = node; node->prev = node; node->refcount = 1; return node; } /* Adds a value at the tail of a given list. * The node referencing the value is allocated from the heap. */ static ListNode *list_add_value(ListNode *const head, const void *value, const int refcount) { ListNode *const new_node = (ListNode *) malloc(sizeof(ListNode)); assert_true(head); assert_true(value); new_node->value = value; new_node->refcount = refcount; return list_add(head, new_node); } // Add new_node to the end of the list. static ListNode *list_add(ListNode *const head, ListNode *new_node) { assert_true(head); assert_true(new_node); new_node->next = head; new_node->prev = head->prev; head->prev->next = new_node; head->prev = new_node; return new_node; } // Remove a node from a list. static ListNode *list_remove(ListNode *const node, const CleanupListValue cleanup_value, void *const cleanup_value_data) { assert_true(node); node->prev->next = node->next; node->next->prev = node->prev; if (cleanup_value) { cleanup_value(node->value, cleanup_value_data); } return node; } /* Remove a list node from a list and free the node. */ static void list_remove_free(ListNode *const node, const CleanupListValue cleanup_value, void *const cleanup_value_data) { assert_true(node); free(list_remove(node, cleanup_value, cleanup_value_data)); } /* Frees memory kept by a linked list * The cleanup_value function is called for every "value" field of nodes in the * list, except for the head. In addition to each list value, * cleanup_value_data is passed to each call to cleanup_value. The head * of the list is not deallocated. */ static ListNode *list_free(ListNode *const head, const CleanupListValue cleanup_value, void *const cleanup_value_data) { assert_true(head); while (!list_empty(head)) { list_remove_free(head->next, cleanup_value, cleanup_value_data); } return head; } // Determine whether a list is empty. static int list_empty(const ListNode *const head) { assert_true(head); return head->next == head; } /* Find a value in the list using the equal_func to compare each node with the * value. */ static int list_find(ListNode *const head, const void *value, const EqualityFunction equal_func, ListNode **output) { ListNode *current; assert_true(head); for (current = head->next; current != head; current = current->next) { if (equal_func(current->value, value)) { *output = current; return 1; } } return 0; } // Returns the first node of a list static int list_first(ListNode *const head, ListNode **output) { ListNode *target_node; assert_true(head); if (list_empty(head)) { return 0; } target_node = head->next; *output = target_node; return 1; } #if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__ * 10) >= 240) # define ARG_UNUSED __attribute__((unused)) #else # define ARG_UNUSED #endif // Deallocate a value referenced by a list. static void free_value(const void *value, ARG_UNUSED void *cleanup_value_data) { assert_true(value); free((void *) value); } // Releases memory associated to a symbol_map_value. static void free_symbol_map_value(const void *value, void *cleanup_value_data) { SymbolMapValue *const map_value = (SymbolMapValue *) value; const uintptr_t children = (uintptr_t) cleanup_value_data; assert_true(value); list_free(&map_value->symbol_values_list_head, children ? free_symbol_map_value : free_value, (void *) (children - 1)); free(map_value); } /* Determine whether a symbol name referenced by a symbol_map_value * matches the specified function name. */ static int symbol_names_match(const void *map_value, const void *symbol) { return !strcmp(((SymbolMapValue *) map_value)->symbol_name, (const char *) symbol); } /* Adds a value to the queue of values associated with the given * hierarchy of symbols. It's assumed value is allocated from the heap. */ static void add_symbol_value(ListNode *const symbol_map_head, const char *const symbol_names[], const size_t number_of_symbol_names, const void *value, const int refcount) { const char *symbol_name; ListNode *target_node; SymbolMapValue *target_map_value; assert_true(symbol_map_head); assert_true((const char *const *)symbol_names); assert_true(number_of_symbol_names); symbol_name = symbol_names[0]; if (!list_find(symbol_map_head, symbol_name, symbol_names_match, &target_node)) { SymbolMapValue *const new_symbol_map_value = malloc(sizeof(*new_symbol_map_value)); new_symbol_map_value->symbol_name = symbol_name; list_initialize(&new_symbol_map_value->symbol_values_list_head); target_node = list_add_value(symbol_map_head, new_symbol_map_value, 1); } target_map_value = (SymbolMapValue *) target_node->value; if (number_of_symbol_names == 1) { list_add_value(&target_map_value->symbol_values_list_head, value, refcount); } else { add_symbol_value(&target_map_value->symbol_values_list_head, &symbol_names[1], number_of_symbol_names - 1, value, refcount); } } /* Gets the next value associated with the given hierarchy of symbols. * The value is returned as an output parameter with the function returning the * node's old refcount value if a value is found, 0 otherwise. * This means that a return value of 1 indicates the node was just removed from * the list. */ static int get_symbol_value(ListNode *const head, const char *const symbol_names[], const size_t number_of_symbol_names, void **output) { const char *symbol_name; ListNode *target_node; assert_true(head); assert_true((const char *const *)symbol_names); assert_true(number_of_symbol_names); assert_true(output); symbol_name = symbol_names[0]; if (list_find(head, symbol_name, symbol_names_match, &target_node)) { SymbolMapValue *map_value; ListNode *child_list; int return_value = 0; assert_true(target_node); assert_true(target_node->value); map_value = (SymbolMapValue *) target_node->value; child_list = &map_value->symbol_values_list_head; if (number_of_symbol_names == 1) { ListNode *value_node = NULL; return_value = list_first(child_list, &value_node); assert_true(return_value); *output = (void *) value_node->value; return_value = value_node->refcount; if (--value_node->refcount == 0) { list_remove_free(value_node, NULL, NULL); } } else { return_value = get_symbol_value(child_list, &symbol_names[1], number_of_symbol_names - 1, output); } if (list_empty(child_list)) { list_remove_free(target_node, free_symbol_map_value, (void *) 0); } return return_value; } else { print_error("No entries for symbol %s.\n", symbol_name); } return 0; } /* Traverse down a tree of symbol values and remove the first symbol value * in each branch that has a refcount < -1 (i.e should always be returned * and has been returned at least once). */ static void remove_always_return_values(ListNode *const map_head, const size_t number_of_symbol_names) { ListNode *current; assert_true(map_head); assert_true(number_of_symbol_names); current = map_head->next; while (current != map_head) { SymbolMapValue *const value = (SymbolMapValue *) current->value; ListNode *const next = current->next; ListNode *child_list; assert_true(value); child_list = &value->symbol_values_list_head; if (!list_empty(child_list)) { if (number_of_symbol_names == 1) { ListNode *const child_node = child_list->next; // If this item has been returned more than once, free it. if (child_node->refcount < -1) { list_remove_free(child_node, free_value, NULL); } } else { remove_always_return_values(child_list, number_of_symbol_names - 1); } } if (list_empty(child_list)) { list_remove_free(current, free_value, NULL); } current = next; } } /* Checks if there are any leftover values set up by the test that were never * retrieved through execution, and fail the test if that is the case. */ static int check_for_leftover_values(const ListNode *const map_head, const char *const error_message, const size_t number_of_symbol_names) { const ListNode *current; int symbols_with_leftover_values = 0; assert_true(map_head); assert_true(number_of_symbol_names); for (current = map_head->next; current != map_head; current = current->next) { const SymbolMapValue *const value = (SymbolMapValue *) current->value; const ListNode *child_list; assert_true(value); child_list = &value->symbol_values_list_head; if (!list_empty(child_list)) { if (number_of_symbol_names == 1) { const ListNode *child_node; print_error(error_message, value->symbol_name); print_error(" Remaining item(s) declared at...\n"); for (child_node = child_list->next; child_node != child_list; child_node = child_node->next) { const SourceLocation *const location = child_node->value; print_error(" " SOURCE_LOCATION_FORMAT "\n", location->file, location->line); } } else { print_error("%s.", value->symbol_name); check_for_leftover_values(child_list, error_message, number_of_symbol_names - 1); } symbols_with_leftover_values++; } } return symbols_with_leftover_values; } LargestIntegralType _cast_to_largest_integral_type(size_t size, ...) { LargestIntegralType ret; va_list args; va_start(args, size); if (size <= sizeof(unsigned int)) { ret = va_arg(args, unsigned int); } else if (size <= sizeof(unsigned long)) { ret = va_arg(args, unsigned long); } else if (size <= sizeof(LargestIntegralType)) { ret = va_arg(args, LargestIntegralType); } else { assert(size <= sizeof(LargestIntegralType)); exit(255); } return ret; } // Get the next return value for the specified mock function. LargestIntegralType _mock(const char *const function, const char *const file, const int line) { void *result; const int rc = get_symbol_value(&global_function_result_map_head, &function, 1, &result); if (rc) { SymbolValue *const symbol = (SymbolValue *) result; const LargestIntegralType value = symbol->value; global_last_mock_value_location = symbol->location; if (rc == 1) { free(symbol); } return value; } else { print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value " "to mock function %s\n", file, line, function); print_xml(XS_RUN_TEST_ERROR "\"ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value " "to mock function %s\"\n", "_mock", file, line, function); if (source_location_is_set(&global_last_mock_value_location)) { print_error("Previously returned mock value was declared at " SOURCE_LOCATION_FORMAT "\n", global_last_mock_value_location.file, global_last_mock_value_location.line); print_xml(" \"Previously returned mock value was declared at " SOURCE_LOCATION_FORMAT "\">\n" XS_RUN_TEST_ERROR_END, global_last_mock_value_location.file, global_last_mock_value_location.line); } else { print_error("There were no previously returned mock values for " "this test.\n"); print_xml(" \"There were no previously returned mock values for this test.\">\n" XS_RUN_TEST_ERROR_END); } global_errors++; exit_test(); } return 0; } // Add a return value for the specified mock function name. void _will_return(const char *const function_name, const char *const file, const int line, const LargestIntegralType value, const int count) { SymbolValue *const return_value = malloc(sizeof(*return_value)); assert_true(count > 0 || count == -1); return_value->value = value; set_source_location(&return_value->location, file, line); add_symbol_value(&global_function_result_map_head, &function_name, 1, return_value, count); } /* Add a custom parameter checking function. If the event parameter is NULL * the event structure is allocated internally by this function. If event * parameter is provided it must be allocated on the heap and doesn't need to * be deallocated by the caller. */ void _expect_check(const char *const function, const char *const parameter, const char *const file, const int line, const CheckParameterValue check_function, const LargestIntegralType check_data, CheckParameterEvent *const event, const int count) { CheckParameterEvent *const check = event ? event : malloc(sizeof(*check)); const char *symbols[] = { function, parameter }; check->parameter_name = parameter; check->check_value = check_function; check->check_value_data = check_data; set_source_location(&check->location, file, line); add_symbol_value(&global_function_parameter_map_head, symbols, 2, check, count); } /* Returns 1 if the specified values are equal. If the values are not equal * an error is displayed and 0 is returned. */ static int values_equal_display_error(const LargestIntegralType left, const LargestIntegralType right) { const int equal = left == right; if (!equal) { print_error(LargestIntegralTypePrintfFormat " != " LargestIntegralTypePrintfFormat "\n", left, right); } return equal; } /* Returns 1 if the specified values are not equal. If the values are equal * an error is displayed and 0 is returned. */ static int values_not_equal_display_error(const LargestIntegralType left, const LargestIntegralType right) { const int not_equal = left != right; if (!not_equal) { print_error(LargestIntegralTypePrintfFormat " == " LargestIntegralTypePrintfFormat "\n", left, right); } return not_equal; } /* Determine whether value is contained within check_integer_set. * If invert is 0 and the value is in the set 1 is returned, otherwise 0 is * returned and an error is displayed. If invert is 1 and the value is not * in the set 1 is returned, otherwise 0 is returned and an error is * displayed. */ static int value_in_set_display_error(const LargestIntegralType value, const CheckIntegerSet *const check_integer_set, const int invert) { int succeeded = invert; assert_true(check_integer_set); { const LargestIntegralType *const set = check_integer_set->set; const size_t size_of_set = check_integer_set->size_of_set; size_t i; for (i = 0; i < size_of_set; i++) { if (set[i] == value) { // If invert = 0 and item is found, succeeded = 1. // If invert = 1 and item is found, succeeded = 0. succeeded = !succeeded; break; } } if (succeeded) { return 1; } print_error(LargestIntegralTypePrintfDecimal " is %sin the set (", value, invert ? "" : "not "); for (i = 0; i < size_of_set; i++) { print_error(LargestIntegralTypePrintfDecimal ", ", set[i]); } print_error(")\n"); } return 0; } /* Determine whether a value is within the specified range. If the value is * within the specified range 1 is returned. If the value isn't within the * specified range an error is displayed and 0 is returned. */ static int integer_in_range_display_error(const LargestIntegralType value, const LargestIntegralType range_min, const LargestIntegralType range_max) { if (value >= range_min && value <= range_max) { return 1; } print_error(LargestIntegralTypePrintfDecimal " is not within the range " LargestIntegralTypePrintfDecimal "-" LargestIntegralTypePrintfDecimal "\n", value, range_min, range_max); return 0; } /* Determine whether a value is within the specified range. If the value * is not within the range 1 is returned. If the value is within the * specified range an error is displayed and zero is returned. */ static int integer_not_in_range_display_error(const LargestIntegralType value, const LargestIntegralType range_min, const LargestIntegralType range_max) { if (value < range_min || value > range_max) { return 1; } print_error(LargestIntegralTypePrintfDecimal " is within the range " LargestIntegralTypePrintfDecimal "-" LargestIntegralTypePrintfDecimal "\n", value, range_min, range_max); return 0; } /* Determine whether the specified strings are equal. If the strings are equal * 1 is returned. If they're not equal an error is displayed and 0 is * returned. */ static int string_equal_display_error(const char *const left, const char *const right) { if (strcmp(left, right) == 0) { return 1; } print_error("\"%s\" != \"%s\"\n", left, right); return 0; } /* Determine whether the specified strings are equal. If the strings are not * equal 1 is returned. If they're not equal an error is displayed and 0 is * returned */ static int string_not_equal_display_error(const char *const left, const char *const right) { if (strcmp(left, right) != 0) { return 1; } print_error("\"%s\" == \"%s\"\n", left, right); return 0; } /* Determine whether the specified areas of memory are equal. If they're equal * 1 is returned otherwise an error is displayed and 0 is returned. */ static int memory_equal_display_error(const char *const a, const char *const b, const size_t size) { int differences = 0; size_t i; for (i = 0; i < size; i++) { const char l = a[i]; const char r = b[i]; if (l != r) { print_error("difference at offset %d 0x%02x 0x%02x\n", i, l, r); differences++; } } if (differences) { print_error("%d bytes of 0x%08x and 0x%08x differ\n", differences, a, b); return 0; } return 1; } /* Determine whether the specified areas of memory are not equal. If they're * not equal 1 is returned otherwise an error is displayed and 0 is * returned. */ static int memory_not_equal_display_error(const char *const a, const char *const b, const size_t size) { int same = 0; size_t i; for (i = 0; i < size; i++) { const char l = a[i]; const char r = b[i]; if (l == r) { same++; } } if (same == size) { print_error("%d bytes of 0x%08x and 0x%08x the same\n", same, a, b); return 0; } return 1; } // CheckParameterValue callback to check whether a value is within a set. static int check_in_set(const LargestIntegralType value, const LargestIntegralType check_value_data) { return value_in_set_display_error(value, cast_largest_integral_type_to_pointer(CheckIntegerSet *, check_value_data), 0); } // CheckParameterValue callback to check whether a value isn't within a set. static int check_not_in_set(const LargestIntegralType value, const LargestIntegralType check_value_data) { return value_in_set_display_error(value, cast_largest_integral_type_to_pointer(CheckIntegerSet *, check_value_data), 1); } /* Create the callback data for check_in_set() or check_not_in_set() and * register a check event. */ static void expect_set(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType values[], const size_t number_of_values, const CheckParameterValue check_function, const int count) { CheckIntegerSet *const check_integer_set = malloc(sizeof(*check_integer_set) + (sizeof(values[0]) * number_of_values)); LargestIntegralType *const set = (LargestIntegralType *) (check_integer_set + 1); declare_initialize_value_pointer_pointer(check_data, check_integer_set); assert_true((const unsigned long long *)values); assert_true(number_of_values); memcpy(set, values, number_of_values * sizeof(values[0])); check_integer_set->set = set; _expect_check(function, parameter, file, line, check_function, check_data.value, &check_integer_set->event, count); } // Add an event to check whether a value is in a set. void _expect_in_set(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType values[], const size_t number_of_values, const int count) { expect_set(function, parameter, file, line, values, number_of_values, check_in_set, count); } // Add an event to check whether a value isn't in a set. void _expect_not_in_set(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType values[], const size_t number_of_values, const int count) { expect_set(function, parameter, file, line, values, number_of_values, check_not_in_set, count); } // CheckParameterValue callback to check whether a value is within a range. static int check_in_range(const LargestIntegralType value, const LargestIntegralType check_value_data) { CheckIntegerRange *const check_integer_range = cast_largest_integral_type_to_pointer(CheckIntegerRange *, check_value_data); assert_true(check_integer_range); return integer_in_range_display_error(value, check_integer_range->minimum, check_integer_range->maximum); } // CheckParameterValue callback to check whether a value is not within a range. static int check_not_in_range(const LargestIntegralType value, const LargestIntegralType check_value_data) { CheckIntegerRange *const check_integer_range = cast_largest_integral_type_to_pointer(CheckIntegerRange *, check_value_data); assert_true(check_integer_range); return integer_not_in_range_display_error(value, check_integer_range->minimum, check_integer_range->maximum); } /* Create the callback data for check_in_range() or check_not_in_range() and * register a check event. */ static void expect_range(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType minimum, const LargestIntegralType maximum, const CheckParameterValue check_function, const int count) { CheckIntegerRange *const check_integer_range = malloc(sizeof(*check_integer_range)); declare_initialize_value_pointer_pointer(check_data, check_integer_range); check_integer_range->minimum = minimum; check_integer_range->maximum = maximum; _expect_check(function, parameter, file, line, check_function, check_data.value, &check_integer_range->event, count); } // Add an event to determine whether a parameter is within a range. void _expect_in_range(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType minimum, const LargestIntegralType maximum, const int count) { expect_range(function, parameter, file, line, minimum, maximum, check_in_range, count); } // Add an event to determine whether a parameter is not within a range. void _expect_not_in_range(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType minimum, const LargestIntegralType maximum, const int count) { expect_range(function, parameter, file, line, minimum, maximum, check_not_in_range, count); } /* CheckParameterValue callback to check whether a value is equal to an * expected value. */ static int check_value(const LargestIntegralType value, const LargestIntegralType check_value_data) { return values_equal_display_error(value, check_value_data); } // Add an event to check a parameter equals an expected value. void _expect_value(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType value, const int count) { _expect_check(function, parameter, file, line, check_value, value, NULL, count); } /* CheckParameterValue callback to check whether a value is not equal to an * expected value. */ static int check_not_value(const LargestIntegralType value, const LargestIntegralType check_value_data) { return values_not_equal_display_error(value, check_value_data); } // Add an event to check a parameter is not equal to an expected value. void _expect_not_value(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType value, const int count) { _expect_check(function, parameter, file, line, check_not_value, value, NULL, count); } // CheckParameterValue callback to check whether a parameter equals a string. static int check_string(const LargestIntegralType value, const LargestIntegralType check_value_data) { return string_equal_display_error(cast_largest_integral_type_to_pointer(char *, value), cast_largest_integral_type_to_pointer(char *, check_value_data)); } // Add an event to check whether a parameter is equal to a string. void _expect_string(const char *const function, const char *const parameter, const char *const file, const int line, const char *string, const int count) { declare_initialize_value_pointer_pointer(string_pointer, (char *) string); _expect_check(function, parameter, file, line, check_string, string_pointer.value, NULL, count); } /* CheckParameterValue callback to check whether a parameter is not equals to * a string. */ static int check_not_string(const LargestIntegralType value, const LargestIntegralType check_value_data) { return string_not_equal_display_error(cast_largest_integral_type_to_pointer(char *, value), cast_largest_integral_type_to_pointer(char *, check_value_data)); } // Add an event to check whether a parameter is not equal to a string. void _expect_not_string(const char *const function, const char *const parameter, const char *const file, const int line, const char *string, const int count) { declare_initialize_value_pointer_pointer(string_pointer, (char *) string); _expect_check(function, parameter, file, line, check_not_string, string_pointer.value, NULL, count); } /* CheckParameterValue callback to check whether a parameter equals an area of * memory. */ static int check_memory(const LargestIntegralType value, const LargestIntegralType check_value_data) { CheckMemoryData *const check = cast_largest_integral_type_to_pointer(CheckMemoryData *, check_value_data); assert_true(check); return memory_equal_display_error(cast_largest_integral_type_to_pointer(void *, value), check->memory, check->size); } /* Create the callback data for check_memory() or check_not_memory() and * register a check event. */ static void expect_memory_setup(const char *const function, const char *const parameter, const char *const file, const int line, const void *const memory, const size_t size, const CheckParameterValue check_function, const int count) { CheckMemoryData *const check_data = malloc(sizeof(*check_data) + size); void *const mem = (void *) (check_data + 1); declare_initialize_value_pointer_pointer(check_data_pointer, check_data); assert_true(memory); assert_true(size); memcpy(mem, memory, size); check_data->memory = mem; check_data->size = size; _expect_check(function, parameter, file, line, check_function, check_data_pointer.value, &check_data->event, count); } // Add an event to check whether a parameter matches an area of memory. void _expect_memory(const char *const function, const char *const parameter, const char *const file, const int line, const void *const memory, const size_t size, const int count) { expect_memory_setup(function, parameter, file, line, memory, size, check_memory, count); } /* CheckParameterValue callback to check whether a parameter is not equal to * an area of memory. */ static int check_not_memory(const LargestIntegralType value, const LargestIntegralType check_value_data) { CheckMemoryData *const check = cast_largest_integral_type_to_pointer(CheckMemoryData *, check_value_data); assert_true(check); return memory_not_equal_display_error(cast_largest_integral_type_to_pointer(void *, value), check->memory, check->size); } // Add an event to check whether a parameter doesn't match an area of memory. void _expect_not_memory(const char *const function, const char *const parameter, const char *const file, const int line, const void *const memory, const size_t size, const int count) { expect_memory_setup(function, parameter, file, line, memory, size, check_not_memory, count); } // CheckParameterValue callback that always returns 1. static int check_any(ARG_UNUSED const LargestIntegralType value, ARG_UNUSED const LargestIntegralType check_value_data) { return 1; } // Add an event to allow any value for a parameter. void _expect_any(const char *const function, const char *const parameter, const char *const file, const int line, const int count) { _expect_check(function, parameter, file, line, check_any, 0, NULL, count); } void _check_expected(const char *const function_name, const char *const parameter_name, const char *file, const int line, const LargestIntegralType value) { void *result; const char *symbols[] = { function_name, parameter_name }; const int rc = get_symbol_value(&global_function_parameter_map_head, symbols, 2, &result); if (rc) { CheckParameterEvent *const check = (CheckParameterEvent *) result; int check_succeeded; global_last_parameter_location = check->location; check_succeeded = check->check_value(value, check->check_value_data); if (rc == 1) { free(check); } if (!check_succeeded) { print_error("ERROR: Check of parameter %s, function %s failed\n" "Expected parameter declared at " SOURCE_LOCATION_FORMAT "\n", parameter_name, function_name, global_last_parameter_location.file, global_last_parameter_location.line); print_xml(XS_RUN_TEST_ERROR "\"ERROR: Check of parameter %s, function %s failed\"\n" " \"Expected parameter declared at " SOURCE_LOCATION_FORMAT "\">\n" XS_RUN_TEST_ERROR_END, "check_expected", parameter_name, function_name, global_last_parameter_location.file, global_last_parameter_location.line); global_errors++; _fail(file, line); } } else { print_error("ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value " "to check parameter %s of function %s\n", file, line, parameter_name, function_name); print_xml(XS_RUN_TEST_ERROR "\"ERROR: " SOURCE_LOCATION_FORMAT " - Could not get value " "to check parameter %s of function %s\"\n", "check_expected", file, line, parameter_name, function_name); if (source_location_is_set(&global_last_parameter_location)) { print_error("Previously declared parameter value was declared at " SOURCE_LOCATION_FORMAT "\n", global_last_parameter_location.file, global_last_parameter_location.line); print_xml(" \"Previously declared parameter value was declared at " SOURCE_LOCATION_FORMAT "\">\n" XS_RUN_TEST_ERROR_END, global_last_parameter_location.file, global_last_parameter_location.line); } else { print_error("There were no previously declared parameter values " "for this test.\n"); print_xml(" \"There were no previously declared parameter values " "for this test.\">\n" XS_RUN_TEST_ERROR_END); } global_errors++; exit_test (); } } // Replacement for assert. void mock_assert(const int result, const char *const expression, const char *const file, const int line) { if (!result) { if (global_expecting_assert) { global_expect_assert_expression = expression; longjmp(global_expect_assert_env, 1); } else { const char *assertname = "mock_assert"; print_error("ASSERT: %s\n", expression); print_xml (XS_RUN_TEST_FAILURE_ASSERT, assertname, result, global_filename, line, assertname, result); _fail(file, line); } } } void _assert_true(const LargestIntegralType result, const char *const expression, const char *const file, const int line) { if (!result) { const char *assertname = "assert_true"; print_error("%s\n", expression); print_xml (XS_RUN_TEST_FAILURE_ASSERT, assertname, result, global_filename, line, assertname, result); _fail(file, line); } } void _assert_int_equal(const LargestIntegralType a, const LargestIntegralType b, const char *const file, const int line) { if (!values_equal_display_error(a, b)) { const char *assertname = "assert_int_equal"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_LLD, assertname, a, b, global_filename, line, assertname, a, b); _fail(file, line); } } void _assert_int_not_equal(const LargestIntegralType a, const LargestIntegralType b, const char *const file, const int line) { if (!values_not_equal_display_error(a, b)) { const char *assertname = "assert_int_not_equal"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_LLD, assertname, a, b, global_filename, line, assertname, a, b); _fail(file, line); } } void _assert_string_equal(const char *const a, const char *const b, const char *const file, const int line) { if (!string_equal_display_error(a, b)) { const char *assertname = "assert_string_equal"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_STRING, assertname, a, b, global_filename, line, assertname, a, b); _fail(file, line); } } void _assert_string_not_equal(const char *const a, const char *const b, const char *file, const int line) { if (!string_not_equal_display_error(a, b)) { const char *assertname = "assert_string_not_equal"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_STRING, assertname, a, b, global_filename, line, assertname, a, b); _fail(file, line); } } void _assert_memory_equal(const void *const a, const void *const b, const size_t size, const char *const file, const int line) { if (!memory_equal_display_error((const char *) a, (const char *) b, size)) { const char *assertname = "assert_memory_equal"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_LLD, assertname, a, b, global_filename, line, assertname, a, b); _fail(file, line); } } void _assert_memory_not_equal(const void *const a, const void *const b, const size_t size, const char *const file, const int line) { if (!memory_not_equal_display_error((const char *) a, (const char *) b, size)) { const char *assertname = "assert_memory_not_equal"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_LLD, assertname, a, b, global_filename, line, assertname, a, b); _fail(file, line); } } void _assert_in_range(const LargestIntegralType value, const LargestIntegralType minimum, const LargestIntegralType maximum, const char *const file, const int line) { if (!integer_in_range_display_error(value, minimum, maximum)) { const char *assertname = "assert_in_range"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_RANGE_LLD, assertname, value, minimum, maximum, global_filename, line, assertname, value, minimum, maximum); _fail(file, line); } } void _assert_not_in_range(const LargestIntegralType value, const LargestIntegralType minimum, const LargestIntegralType maximum, const char *const file, const int line) { if (!integer_not_in_range_display_error(value, minimum, maximum)) { const char *assertname = "assert_not_in_range"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_RANGE_LLD, assertname, value, minimum, maximum, global_filename, line, assertname, value, minimum, maximum); _fail(file, line); } } void _assert_in_set(const LargestIntegralType value, const LargestIntegralType values[], const size_t number_of_values, const char *const file, const int line) { CheckIntegerSet check_integer_set; check_integer_set.set = values; check_integer_set.size_of_set = number_of_values; if (!value_in_set_display_error(value, &check_integer_set, 0)) { const char *assertname = "assert_in_set"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_SET_LLD, assertname, value, number_of_values, global_filename, line, assertname, value, number_of_values); _fail(file, line); } } void _assert_not_in_set(const LargestIntegralType value, const LargestIntegralType values[], const size_t number_of_values, const char *const file, const int line) { CheckIntegerSet check_integer_set; check_integer_set.set = values; check_integer_set.size_of_set = number_of_values; if (!value_in_set_display_error(value, &check_integer_set, 1)) { const char *assertname = "assert_not_in_set"; print_xml (XS_RUN_TEST_FAILURE_ASSERT_SET_LLD, assertname, value, number_of_values, global_filename, line, assertname, value, number_of_values); _fail(file, line); } } // Get the list of allocated blocks. static ListNode *get_allocated_blocks_list() { // If it initialized, initialize the list of allocated blocks. if (!global_allocated_blocks.value) { list_initialize(&global_allocated_blocks); global_allocated_blocks.value = (void *) 1; } return &global_allocated_blocks; } // Use the real malloc in this function. #undef malloc void *_test_malloc(const size_t size, const char *file, const int line) { char *ptr; MallocBlockInfo *block_info; ListNode *const block_list = get_allocated_blocks_list(); const size_t allocate_size = size + (MALLOC_GUARD_SIZE * 2) + sizeof(*block_info) + MALLOC_ALIGNMENT; char *const block = (char *) malloc(allocate_size); assert_true(block); // Calculate the returned address. ptr = (char *) (((size_t) block + MALLOC_GUARD_SIZE + sizeof(*block_info) + MALLOC_ALIGNMENT) & ~(MALLOC_ALIGNMENT - 1)); // Initialize the guard blocks. memset(ptr - MALLOC_GUARD_SIZE, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); memset(ptr + size, MALLOC_GUARD_PATTERN, MALLOC_GUARD_SIZE); memset(ptr, MALLOC_ALLOC_PATTERN, size); block_info = (MallocBlockInfo *) (ptr - (MALLOC_GUARD_SIZE + sizeof(*block_info))); set_source_location(&block_info->location, file, line); block_info->allocated_size = allocate_size; block_info->size = size; block_info->block = block; block_info->node.value = block_info; list_add(block_list, &block_info->node); return ptr; } #define malloc test_malloc void *_test_calloc(const size_t number_of_elements, const size_t size, const char *file, const int line) { void *const ptr = _test_malloc(number_of_elements * size, file, line); if (ptr) { memset(ptr, 0, number_of_elements * size); } return ptr; } // Use the real free in this function. #undef free void _test_free(void *const ptr, const char *file, const int line) { unsigned int i; char *block = (char *) ptr; MallocBlockInfo *block_info; _assert_true(ptr != NULL, "ptr", file, line); block_info = (MallocBlockInfo *) (block - (MALLOC_GUARD_SIZE + sizeof(*block_info))); // Check the guard blocks. { char *guards[2] = { block - MALLOC_GUARD_SIZE, block + block_info->size }; for (i = 0; i < ARRAY_LENGTH(guards); i++) { unsigned int j; char *const guard = guards[i]; for (j = 0; j < MALLOC_GUARD_SIZE; j++) { const char diff = guard[j] - MALLOC_GUARD_PATTERN; if (diff) { print_error("Guard block of 0x%08x size=%d allocated by " SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\n", (size_t) ptr, block_info->size, block_info->location.file, block_info->location.line, (size_t) &guard[j]); print_xml(XS_RUN_TEST_ERROR "\"Guard block of 0x%08x size=%d allocated by " SOURCE_LOCATION_FORMAT " at 0x%08x is corrupt\">\n" XS_RUN_TEST_ERROR_END, "test_free", (size_t) ptr, block_info->size, block_info->location.file, block_info->location.line, (size_t) &guard[j]); global_errors++; _fail(file, line); } } } } list_remove(&block_info->node, NULL, NULL); block = block_info->block; memset(block, MALLOC_FREE_PATTERN, block_info->allocated_size); free(block); } #define free test_free // Crudely checkpoint the current heap state. static const ListNode *check_point_allocated_blocks() { return get_allocated_blocks_list()->prev; } /* Display the blocks allocated after the specified check point. This * function returns the number of blocks displayed. */ static int display_allocated_blocks(const ListNode *const check_point) { const ListNode *const head = get_allocated_blocks_list(); const ListNode *node; int allocated_blocks = 0; assert_true(check_point); assert_true(check_point->next); for (node = check_point->next; node != head; node = node->next) { const MallocBlockInfo *const block_info = node->value; assert_true(block_info); if (!allocated_blocks) { print_error("Blocks allocated...\n"); } print_error(" 0x%08x : " SOURCE_LOCATION_FORMAT "\n", block_info->block, block_info->location.file, block_info->location.line); allocated_blocks++; } return allocated_blocks; } // Free all blocks allocated after the specified check point. static void free_allocated_blocks(const ListNode *const check_point) { const ListNode *const head = get_allocated_blocks_list(); const ListNode *node; assert_true(check_point); node = check_point->next; assert_true(node); while (node != head) { MallocBlockInfo *const block_info = (MallocBlockInfo *) node->value; node = node->next; free((char *) block_info + sizeof(*block_info) + MALLOC_GUARD_SIZE); } } // Fail if any any blocks are allocated after the specified check point. static void fail_if_blocks_allocated(const ListNode *const check_point, const char *const test_name) { const int allocated_blocks = display_allocated_blocks(check_point); if (allocated_blocks) { free_allocated_blocks(check_point); print_error("ERROR: %s leaked %d block(s)\n", test_name, allocated_blocks); print_xml(XS_RUN_TEST_ERROR "\"ERROR: %s leaked %d block(s)\">\n" XS_RUN_TEST_ERROR_END, "fail_if_blocks_allocated", test_name, allocated_blocks); global_errors++; exit_test(); } } void _fail(const char *const file, const int line) { print_error("ERROR: " SOURCE_LOCATION_FORMAT " Failure!\n", file, line); exit_test(); } #ifndef _WIN32 static void exception_handler(int sig) { print_error("%s\n", strsignal(sig)); print_xml(XS_RUN_TEST_ERROR "\"%s\">\n" XS_RUN_TEST_ERROR_END, "exception_handler", strsignal(sig)); global_errors++; exit_test(); } #else // _WIN32 static LONG WINAPI exception_filter(EXCEPTION_POINTERS *exception_pointers) { EXCEPTION_RECORD *const exception_record = exception_pointers->ExceptionRecord; const DWORD code = exception_record->ExceptionCode; unsigned int i; for (i = 0; i < ARRAY_LENGTH(exception_codes); i++) { const ExceptionCodeInfo *const code_info = &exception_codes[i]; if (code == code_info->code) { static int shown_debug_message = 0; fflush(stdout); print_error("%s occurred at 0x%08x.\n", code_info->description, exception_record->ExceptionAddress); print_xml(XS_RUN_TEST_ERROR "\"%s occurred at 0x%08x.\">\n" XS_RUN_TEST_ERROR_END, "exception_filter", code_info->description, exception_record->ExceptionAddress); if (!shown_debug_message) { print_error("\n" "To debug in Visual Studio...\n" "1. Select menu item File->Open Project\n" "2. Change 'Files of type' to 'Executable Files'\n" "3. Open this executable.\n" "4. Select menu item Debug->Start\n" "\n" "Alternatively, set the environment variable \n" "UNIT_TESTING_DEBUG to 1 and rebuild this executable, \n" "then click 'Debug' in the popup dialog box.\n" "\n"); shown_debug_message = 1; } global_errors++; exit_test_no_app(); return EXCEPTION_EXECUTE_HANDLER; } } return EXCEPTION_CONTINUE_SEARCH; } #endif // !_WIN32 void vinit_xml (const char *const format, va_list args) { FILE* xmlfile = fopen(global_xmlfile, "w"); vfprintf(xmlfile, format, args); fclose(xmlfile); #ifdef _WIN32 OutputDebugString(buffer); #endif // _WIN32 } void init_xml (const char *const format, ...) { if (!global_is_file_writer_test) { va_list args; va_start(args, format); vinit_xml(format, args); va_end(args); } } void vprint_xml(const char *const format, va_list args) { FILE* xmlfile = fopen(global_xmlfile, "a"); vfprintf(xmlfile, format, args); fclose(xmlfile); #ifdef _WIN32 OutputDebugString(buffer); #endif // _WIN32 } void print_xml(const char *const format, ...) { if (!global_is_file_writer_test) { va_list args; va_start(args, format); vprint_xml(format, args); va_end(args); } } void append_xml(const char *ofile, const char *ifile) { if (!global_is_file_writer_test) { char ch; FILE* xmlfile = fopen(ofile, "ab"); FILE* xml_tmp = fopen(ifile, "rb"); while(!feof(xml_tmp)) { ch = getc(xml_tmp); if(!feof(xml_tmp)) { putc(ch, xmlfile); } } fclose(xmlfile); fclose(xml_tmp); } } // Standard output and error print methods. void vprint_message(const char *const format, va_list args) { vprintf(format, args); #ifdef _WIN32 OutputDebugString(buffer); #endif // _WIN32 } void vprint_error(const char *const format, va_list args) { vfprintf(stderr, format, args); #ifdef _WIN32 OutputDebugString(buffer); #endif // _WIN32 } void print_message(const char *const format, ...) { va_list args; va_start(args, format); vprint_message(format, args); va_end(args); } void print_error(const char *const format, ...) { va_list args; va_start(args, format); vprint_error(format, args); va_end(args); } int _run_test(const char *const function_name, const UnitTestFunction Function, void **const state, const UnitTestFunctionType function_type, const void *const heap_check_point) { const ListNode *const check_point = heap_check_point ? heap_check_point : check_point_allocated_blocks(); void *current_state = NULL; int rc = 1; int handle_exceptions = 1; #ifdef _WIN32 handle_exceptions = !IsDebuggerPresent(); #endif // _WIN32 #if UNIT_TESTING_DEBUG handle_exceptions = 0; #endif // UNIT_TESTING_DEBUG if (handle_exceptions) { #ifndef _WIN32 unsigned int i; for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) { default_signal_functions[i] = signal(exception_signals[i], exception_handler); } #else // _WIN32 previous_exception_filter = SetUnhandledExceptionFilter(exception_filter); #endif // !_WIN32 } if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST || function_type == UNIT_TEST_FUNCTION_TYPE_TEST_WITH_STATE) { print_message("%s: Starting test\n", function_name); } initialize_testing(); global_running_test = 1; if (setjmp(global_run_test_env) == 0) { if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST) { Function(); } else { ((UnitTestFunctionWithState)Function)(state ? state : ¤t_state); } fail_if_leftover_values(function_name); /* If this is a setup function then ignore any allocated blocks * only ensure they're deallocated on tear down. */ if (function_type != UNIT_TEST_FUNCTION_TYPE_SETUP) { fail_if_blocks_allocated(check_point, function_name); } global_running_test = 0; if (function_type == UNIT_TEST_FUNCTION_TYPE_TEST || function_type == UNIT_TEST_FUNCTION_TYPE_TEST_WITH_STATE) { print_message("%s: Test completed successfully.\n", function_name); } rc = 0; } else { global_running_test = 0; print_message("%s: Test failed.\n", function_name); } teardown_testing(); if (handle_exceptions) { #ifndef _WIN32 unsigned int i; for (i = 0; i < ARRAY_LENGTH(exception_signals); i++) { signal(exception_signals[i], default_signal_functions[i]); } #else // _WIN32 if (previous_exception_filter) { SetUnhandledExceptionFilter(previous_exception_filter); previous_exception_filter = NULL; } #endif // !_WIN32 } return rc; } int _run_tests(const UnitTest *const tests, const size_t number_of_tests, const char *const file) { // Whether to execute the next test. int run_next_test = 1; // Whether the previous test failed. int previous_test_failed = 0; // Check point of the heap state. const ListNode *const check_point = check_point_allocated_blocks(); // Time of testsuite execution time_t time_suite, time_case, time_now; time_t ttime; time(&ttime); char timestamp[1024]; strcpy(timestamp, ctime(&ttime)); timestamp[strlen(timestamp)-1] = '\0'; // Current test being executed. size_t current_test = 0; // Number of tests executed. size_t tests_executed = 0; // Number of failed tests. size_t total_failed = 0; // Number of setup functions. size_t setups = 0; // Number of teardown functions. size_t teardowns = 0; /* A stack of test states. A state is pushed on the stack * when a test setup occurs and popped on tear down. */ TestState *test_states = malloc(number_of_tests * sizeof(*test_states)); size_t number_of_test_states = 0; // Names of the tests that failed. const char **failed_names = malloc(number_of_tests * sizeof(*failed_names)); void **current_state = NULL; // Make sure LargestIntegralType is at least the size of a pointer. assert_true(sizeof(LargestIntegralType) >= sizeof(void *)); //Initialize an xml file and parameters char path[1024] = {0}; char filename[1024] = {0}; char suitename[1024] = {0}; char casename[1024] = {0}; char xmlfile[1024] = {0}; int len; strcpy(path, file); strcpy(filename, basename(path)); len = strrchr(filename, '.')-filename; strcpy(suitename, ""); strncat(suitename, filename, len); strcpy(xmlfile, "xml_tmp_suite"); global_filename = filename; global_is_file_writer_test = (0 == strcmp(suitename, "file_writer_test")); global_xmlfile = xmlfile; global_errors = 0; init_xml(""); time(&time_suite); while (current_test < number_of_tests) { const ListNode *test_check_point = NULL; TestState *current_TestState; const UnitTest *const test = &tests[current_test++]; if (!test->f.function) { continue; } switch (test->function_type) { case UNIT_TEST_FUNCTION_TYPE_TEST: case UNIT_TEST_FUNCTION_TYPE_TEST_WITH_STATE: run_next_test = 1; break; case UNIT_TEST_FUNCTION_TYPE_SETUP: { // Checkpoint the heap before the setup. current_TestState = &test_states[number_of_test_states++]; current_TestState->check_point = check_point_allocated_blocks(); test_check_point = current_TestState->check_point; current_state = ¤t_TestState->state; *current_state = NULL; run_next_test = 1; setups++; break; } case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: // Check the heap based on the last setup checkpoint. assert_true(number_of_test_states); current_TestState = &test_states[--number_of_test_states]; test_check_point = current_TestState->check_point; current_state = ¤t_TestState->state; teardowns++; break; default: print_error("Invalid unit test function type %d\n", test->function_type); print_xml(XS_RUN_TEST_ERROR "\"Invalid unit test function type %d\">\n" XS_RUN_TEST_ERROR_END, "", test->function_type); global_errors++; exit_test(); break; } if (run_next_test) { strcpy(casename, test->name); strcpy(xmlfile, "xml_tmp_case"); init_xml(""); time(&time_case); int failed = _run_test(test->name, test->f.function, current_state, test->function_type, test_check_point); strcpy(xmlfile, "xml_tmp_suite"); time(&time_now); print_xml(XS_TESTCASE, casename, path, difftime(time_now, time_case)); if (failed) { failed_names[total_failed] = test->name; append_xml("xml_tmp_suite", "xml_tmp_case"); } print_xml(XS_TESTCASE_END); switch (test->function_type) { case UNIT_TEST_FUNCTION_TYPE_TEST: case UNIT_TEST_FUNCTION_TYPE_TEST_WITH_STATE: previous_test_failed = failed; total_failed += failed; tests_executed++; break; case UNIT_TEST_FUNCTION_TYPE_SETUP: if (failed) { total_failed++; tests_executed++; // Skip forward until the next test or setup function. run_next_test = 0; } previous_test_failed = 0; break; case UNIT_TEST_FUNCTION_TYPE_TEARDOWN: // If this test failed. if (failed && !previous_test_failed) { total_failed++; } break; default: assert_false("BUG: shouldn't be here!"); break; } } } sprintf(xmlfile, "%s.xml", suitename); time(&time_now); init_xml(XS_INIT_TESTSUITE, suitename, timestamp, "localhost", number_of_tests, total_failed, global_errors, difftime(time_now, time_suite)); append_xml(xmlfile, "xml_tmp_suite"); print_xml(XS_TESTSUITE_END); if (total_failed) { size_t i; print_error("%d out of %d tests failed!\n", total_failed, tests_executed); for (i = 0; i < total_failed; i++) { print_error(" %s\n", failed_names[i]); } } else { print_message("All %d tests passed\n", tests_executed); } if (number_of_test_states) { print_error("Mismatched number of setup %d and teardown %d " "functions\n", setups, teardowns); total_failed = -1; } free(test_states); free((void *) failed_names); fail_if_blocks_allocated(check_point, "run_tests"); return (int) total_failed; } /* LCOV_EXCL_STOP */ cfengine-3.6.2/tests/unit/persistent_lock_test.c0000664000175100017510000000141412400110676021547 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ static void tests_setup(void) { OpenSSL_add_all_digests(); /* FIXME: get rid of hardcoded filenames */ xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/persistent_lock_test.XXXXXX"); mkdtemp(CFWORKDIR); char buf[CF_BUFSIZE]; xsnprintf(buf, CF_BUFSIZE, "%s/state", CFWORKDIR); mkdir(buf, 0755); } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } int main() { PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { }; int ret = run_tests(tests); tests_teardown(); return ret; } cfengine-3.6.2/tests/unit/Makefile.am0000664000175100017510000002747712411001073017201 0ustar00a10038a1003800000000000000# Just recursively include in dist tarball all data we need for unit tests EXTRA_DIST = data AM_CPPFLAGS = $(CORE_CPPFLAGS) \ $(ENTERPRISE_CFLAGS) \ -I$(srcdir)/../../libcfnet \ -I$(srcdir)/../../libenv \ -I$(srcdir)/../../libpromises \ -I$(srcdir)/../../libutils \ -I$(srcdir)/../../cf-monitord \ -I$(srcdir)/../../cf-serverd \ -I$(srcdir)/../../cf-agent \ -I$(srcdir)/../../cf-execd \ -I$(srcdir)/../../cf-key \ -DTESTDATADIR='"$(srcdir)/data"' LDADD = ../../libpromises/libpromises.la libtest.la # automake does not support "maude_LIBS" variables. We can only alter # the generic LIBS one. In case the functions are mocked in the test # implementation, then we are pretty sure that they will be overriden by # our local implementation. So we include *everything*... LIBS = $(CORE_LIBS) AM_LDFLAGS = $(CORE_LDFLAGS) check_LTLIBRARIES = libtest.la libtest_la_SOURCES = cmockery.c cmockery.h schema.h test.c test.h \ ../../libutils/alloc.c \ ../../libpromises/patches.c \ ../../libpromises/constants.c \ ../../libpromises/known_dirs.c \ ../../libutils/map.c \ ../../libutils/array_map.c \ ../../libutils/hash.c \ ../../libutils/hash_map.c libtest_la_LIBADD = ../../libcompat/libcompat.la check_LTLIBRARIES += libstr.la libstr_la_SOURCES = ../../libutils/string_lib.c ../../libutils/regex.c \ ../../libutils/encode.c ../../libutils/writer.c \ ../../libutils/sequence.c libstr_la_LIBADD = libtest.la check_LTLIBRARIES += libdb.la libdb_la_SOURCES = ../../libpromises/dbm_api.c \ ../../libpromises/mutex.c \ ../../libpromises/dbm_quick.c \ ../../libpromises/dbm_tokyocab.c \ ../../libpromises/dbm_lmdb.c \ ../../libpromises/dbm_migration.c \ ../../libpromises/dbm_migration_lastseen.c \ ../../libpromises/dbm_migration_bundles.c \ ../../libutils/logging.c \ ../../libutils/atexit.c if HPUX libdb_la_SOURCES += ../../libpromises/cf3globals.c endif libdb_la_LIBADD = libstr.la ../../libutils/libutils.la #libdb_la_CPPFLAGS = $(LMDB_CPPFLAGS) $(TOKYOCABINET_CPPFLAGS) $(QDBM_CPPFLAGS) # Make sure that source files are compiled to separate object files libdb_la-file.o libdb_la_CFLAGS = $(AM_CFLAGS) check_PROGRAMS = \ arg_split_test \ assoc_test \ atexit_test \ csv_writer_test \ item_test \ rlist_test \ domainname_test \ set_test \ set_domainname_test \ str_test \ json_test \ csv_parser_test \ evalfunction_test \ eval_context_test \ regex_test \ alloc_test \ string_writer_test \ file_writer_test \ xml_writer_test \ sequence_test \ lastseen_test \ lastseen_migration_test \ changes_migration_test \ db_test \ db_concurrent_test \ dbm_migration_bundles_test \ misc_lib_test \ item_lib_test \ crypto_symmetric_test \ persistent_lock_test \ thread_test \ package_versions_compare_test \ files_lib_test \ file_lib_test \ map_test \ parsemode_test \ parser_test \ policy_test \ sort_test \ file_name_test \ logging_test \ logging_timestamp_test \ granules_test \ scope_test \ conversion_test \ files_interfaces_test \ refcount_test \ list_test \ buffer_test \ cf_key_functions_test \ connection_management_test \ expand_test \ string_expressions_test \ var_expressions_test \ process_terminate_unix_test \ exec-config-test \ generic_agent_test \ syntax_test \ sysinfo_test \ ipaddress_test \ hashes_test \ rb-tree-test \ variable_test \ protocol_test \ mon_cpu_test \ mon_load_test \ mon_processes_test \ mustache_test \ class_test \ version_test \ hash_test \ key_test \ cf_upgrade_test \ queue_test \ matching_test \ ring_buffer_test \ strlist_test \ addr_lib_test \ libcompat_test if HAVE_AVAHI_CLIENT if HAVE_AVAHI_COMMON check_PROGRAMS += \ findhub_test \ avahi_config_test endif endif check_SCRIPTS = dynamic_dependency_test.sh EXTRA_DIST += dynamic_dependency_test.sh TESTS = $(check_PROGRAMS) $(check_SCRIPTS) # # OS X uses real system calls instead of our stubs unless this option is used # TESTS_ENVIRONMENT = DYLD_FORCE_FLAT_NAMESPACE=yes atexit_test_SOURCES = atexit_test.c atexit_test_LDADD = libtest.la libdb.la csv_writer_test_SOURCES = csv_writer_test.c ../../libutils/csv_writer.c csv_writer_test_LDADD = libtest.la libstr.la conversion_test_SOURCES = conversion_test.c ../../libpromises/conversion.c if !BUILTIN_EXTENSIONS check_PROGRAMS += enterprise_extension_test enterprise_extension_test_SOURCES = enterprise_extension_test.c check_LTLIBRARIES += cfengine-enterprise.la cfengine_enterprise_la_SOURCES = enterprise_extension_test_lib.c cfengine_enterprise_la_LDFLAGS = $(AM_LDFLAGS) \ -avoid-version -module -shared -export-dynamic -rpath / EXTRA_enterprise_extension_test_DEPENDENCIES = cfengine-enterprise.la endif set_domainname_test_SOURCES = set_domainname_test.c set_domainname_test_LDADD = libstr.la ../../libpromises/libpromises.la str_test_SOURCES = str_test.c str_test_LDADD = libstr.la xml_writer_test_SOURCES = xml_writer_test.c ../../libutils/xml_writer.c xml_writer_test_LDADD = libtest.la libstr.la list_test_SOURCES = list_test.c refcount_test_SOURCES = refcount_test.c ../../libutils/refcount.c buffer_test_SOURCES = buffer_test.c ../../libutils/buffer.c csv_parser_test_SOURCES = csv_parser_test.c ../../libutils/csv_parser.c csv_parser_test_LDADD = libtest.la ../../libutils/libutils.la regex_test_SOURCES = regex_test.c ../../cf-agent/match_scope.c cf_key_functions_test_SOURCES = cf_key_functions_test.c ../../cf-key/cf-key-functions.c ipaddress_test_SOURCES = ipaddress_test.c protocol_test_SOURCES = protocol_test.c \ ../../cf-serverd/server_common.c \ ../../cf-serverd/server_tls.c \ ../../cf-serverd/server.c \ ../../cf-serverd/cf-serverd-enterprise-stubs.c \ ../../cf-serverd/server_transform.c \ ../../cf-serverd/cf-serverd-functions.c \ ../../cf-serverd/server_access.c \ ../../cf-serverd/strlist.c protocol_test_LDADD = ../../libpromises/libpromises.la libtest.la if HAVE_AVAHI_CLIENT if HAVE_AVAHI_COMMON findhub_test_SOURCES = findhub_test.c ../../cf-agent/findhub.c ../../cf-agent/load_avahi.c avahi_config_test_SOURCES = avahi_config_test.c \ ../../cf-serverd/server_common.c \ ../../cf-serverd/server_tls.c \ ../../cf-serverd/server.c \ ../../cf-serverd/server_transform.c \ ../../cf-serverd/cf-serverd-enterprise-stubs.c \ ../../cf-serverd/server_access.c \ ../../cf-serverd/server_classic.c \ ../../cf-serverd/strlist.c avahi_config_test_LDADD = ../../libpromises/libpromises.la libtest.la endif endif #file_writer_test_CPPFLAGS = -I$(top_srcdir)/libutils file_writer_test_SOURCES = file_writer_test.c gcov-stub.c db_test_SOURCES = db_test.c db_test_LDADD = libdb.la db_concurrent_test_SOURCES = db_concurrent_test.c #db_concurrent_test_CPPFLAGS = $(libdb_la_CPPFLAGS) db_concurrent_test_LDADD = libdb.la lastseen_test_SOURCES = lastseen_test.c \ ../../libpromises/item_lib.c ../../libpromises/lastseen.c ../../libutils/statistics.c #lastseen_test_CPPFLAGS = $(libdb_la_CPPFLAGS) lastseen_test_LDADD = libdb.la ../../libpromises/libpromises.la lastseen_migration_test_SOURCES = lastseen_migration_test.c \ ../../libpromises/lastseen.c ../../libutils/statistics.c ../../libpromises/item_lib.c #lastseen_migration_test_CPPFLAGS = $(libdb_la_CPPFLAGS) lastseen_migration_test_LDADD = libdb.la ../../libpromises/libpromises.la dbm_migration_bundles_test_SOURCES = dbm_migration_bundles_test.c dbm_migration_bundles_test_LDADD = libdb.la #dbm_migration_bundles_test_CPPFLAGS = $(libdb_la_CPPFLAGS) CLEANFILES = *.gcno *.gcda cfengine-enterprise.so package_versions_compare_test_SOURCES = package_versions_compare_test.c ../../cf-agent/verify_packages.c ../../cf-agent/vercmp.c ../../cf-agent/vercmp_internal.c ../../cf-agent/retcode.c ../../cf-agent/match_scope.c #package_versions_compare_test_CPPFLAGS = $(AM_CPPFLAGS) package_versions_compare_test_LDADD = ../../libpromises/libpromises.la libtest.la file_lib_test_SOURCES = file_lib_test.c \ ../../libutils/file_lib.c \ ../../libutils/logging.c \ ../../libutils/misc_lib.c \ ../../libutils/string_lib.c \ ../../libutils/sequence.c \ ../../libutils/unix_dir.c \ ../../libutils/writer.c file_lib_test_LDADD = libtest.la file_lib_test_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_SYMLINK_ATOMICITY sort_test_SOURCES = sort_test.c sort_test_LDADD = libtest.la ../../libpromises/libpromises.la logging_test_SOURCES = logging_test.c ../../libpromises/syslog_client.c logging_test_LDADD = libtest.la ../../libutils/libutils.la logging_timestamp_test_SOURCES = logging_timestamp_test.c ../../libutils/logging.h logging_timestamp_test_LDADD = libtest.la ../../libutils/libutils.la connection_management_test_SOURCES = connection_management_test.c ../../cf-serverd/server_common.c ../../cf-serverd/server_tls.c connection_management_test_LDADD = ../../libpromises/libpromises.la libtest.la ../../cf-serverd/libcf-serverd.la rlist_test_SOURCES = rlist_test.c \ ../../libpromises/rlist.c ../../libutils/logging.c rlist_test_LDADD = libtest.la libstr.la ../../libpromises/libpromises.la if LINUX check_PROGRAMS += linux_process_test linux_process_test_SOURCES = linux_process_test.c \ ../../libpromises/process_unix.c \ ../../libpromises/process_linux.c \ ../../libutils/file_lib.c linux_process_test_LDADD = libtest.la ../../libutils/libutils.la endif if AIX check_PROGRAMS += aix_process_test aix_process_test_SOURCES = aix_process_test.c \ ../../libpromises/process_unix.c \ ../../libpromises/process_aix.c \ ../../libutils/file_lib.c aix_process_test_LDADD = libtest.la ../../libutils/libutils.la endif if SOLARIS check_PROGRAMS += solaris_process_test solaris_process_test_SOURCES = solaris_process_test.c \ ../../libpromises/process_unix.c \ ../../libpromises/process_solaris.c \ ../../libutils/file_lib.c solaris_process_test_LDADD = libtest.la ../../libutils/libutils.la endif process_terminate_unix_test_SOURCES = process_terminate_unix_test.c \ ../../libpromises/process_unix.c process_terminate_unix_test_LDADD = libtest.la ../../libutils/libutils.la exec_config_test_SOURCES = exec-config-test.c \ ../../cf-execd/exec-config.c ../../cf-execd/execd-config.c exec_config_test_LDADD = libtest.la ../../libpromises/libpromises.la sysinfo_test_LDADD = libtest.la \ ../../libenv/libenv.la \ ../../libpromises/libpromises.la mon_cpu_test_SOURCES = mon_cpu_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_cpu.c mon_cpu_test_LDADD = ../../libpromises/libpromises.la libtest.la mon_load_test_SOURCES = mon_load_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_load.c mon_load_test_LDADD = ../../libpromises/libpromises.la libtest.la mon_processes_test_SOURCES = mon_processes_test.c ../../cf-monitord/mon.h ../../cf-monitord/mon_processes.c mon_processes_test_LDADD = ../../libpromises/libpromises.la libtest.la # tls_generic_test uses stub functions interposition which does not work (yet) # under OS X. Another way of stubbing functions from libpromises is needed. if !XNU check_PROGRAMS += tls_generic_test tls_generic_test_SOURCES = tls_generic_test.c tls_generic_test_LDADD = libtest.la \ ../../libutils/libutils.la \ ../../libpromises/libpromises.la \ ../../libcfnet/libcfnet.la \ ../../cf-serverd/libcf-serverd.la endif version_test_SOURCES = version_test.c hash_test_SOURCES = hash_test.c hash_test_LDADD = ../../libutils/libutils.la libtest.la key_test_SOURCES = key_test.c key_test_LDADD = ../../libpromises/libpromises.la ../../libutils/libutils.la libtest.la strlist_test_SOURCES = strlist_test.c ../../cf-serverd/strlist.c ../../cf-serverd/strlist.h libcompat_test_CPPFLAGS = -I$(top_srcdir)/libcompat libcompat_test_SOURCES = libcompat_test.c CFUPGRADE=../../cf-upgrade cf_upgrade_test_SOURCES = cf_upgrade_test.c $(CFUPGRADE)/alloc-mini.c $(CFUPGRADE)/alloc-mini.h $(CFUPGRADE)/command_line.c \ $(CFUPGRADE)/command_line.h $(CFUPGRADE)/configuration.c $(CFUPGRADE)/configuration.h $(CFUPGRADE)/log.c $(CFUPGRADE)/log.h \ $(CFUPGRADE)/process.c $(CFUPGRADE)/process.h $(CFUPGRADE)/update.c $(CFUPGRADE)/update.h cf_upgrade_test_CFLAGS = -I$(CFUPGRADE) queue_test_SOURCES = queue_test.c cfengine-3.6.2/tests/unit/libcompat_test.c0000664000175100017510000000756612400110676020327 0ustar00a10038a1003800000000000000#include #include #include /* Include the tested functions directly from libcompat! */ #include #define TEST_SNPRINTF 1 #include /* TODO TEST MORE OF OUR libcompat REPLACEMENTS! */ static void test_memmem() { char *result, *needle, *haystack; /* Can't find anything in nothing. */ needle = "whatever"; result = memmem("EMPTY", 0, needle, strlen(needle)); assert_int_equal(result, NULL); /* Even nothing is not in nothing. */ result = memmem("EMPTY", 0, "EMPTY", 0); assert_int_equal(result, NULL); /* Nothing can be found in anything. */ haystack = "blah"; result = memmem(haystack, strlen(haystack), "EMPTY", 0); assert_int_equal(result, &haystack[0]); /* Find something when exact match. */ haystack = "blah"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, &haystack[0]); /* Find something when at the beginning. */ haystack = "blah123"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, &haystack[0]); /* Find something when in the middle. */ haystack = "123blah123"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, &haystack[3]); /* Find something when in the end. */ haystack = "12345blah"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, &haystack[5]); /* Partial match is not a match, part 1. */ haystack = "12345bla"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, NULL); /* Partial match is not a match, part 2. */ haystack = "bla"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, NULL); /* Partial match is not a match, part 3. */ haystack = "bla123"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, NULL); /* All the right letters, in the right order, not contiguous. */ haystack = "bleach"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, NULL); /* Should not be affected by case. */ haystack = "BLAH"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, NULL); /* Don't jump forward too much on incomplete match. */ haystack = "bblblablah"; needle = "blah"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, &haystack[6]); /* Don't jump forward too much, part 2. */ haystack = "abcabcabcd"; needle = "abcabcd"; result = memmem(haystack, strlen(haystack), needle, strlen(needle)); assert_int_equal(result, &haystack[3]); } static void test_snprintf() { int failures = snprintf_rigorous_test(); if (failures > 0) { puts("\n" "=== WARNING your system's printf() generates different results ===\n" "=== than our printf() in libcompat! ===\n" "=== This is not a necessarily a bug, since this test has lots ===\n" "=== of requirements to run properly, so testsuite result is not affected. ===\n" "=== However it might indicate that printf() in your system's libc is buggy. ===\n" ); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_memmem), unit_test(test_snprintf) /* TODO test rpl_fprintf() outputs short and long strings correctly to a file. */ }; int ret = run_tests(tests); return ret; } cfengine-3.6.2/tests/unit/db_concurrent_test.c0000664000175100017510000000554212400110676021174 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ char CFWORKDIR[CF_BUFSIZE]; void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/db_test.XXXXXX"); mkdtemp(CFWORKDIR); } void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } struct arg_struct { int base; }; /***************************************************************** * launch 5 threads * fct(i) * one by one insert * batch insert * one by one update * batch update * delete one by one * batch delete * * join * check * 0 - 1999 * first 100 * last 1900 * first 500, if %20, update +1 * last 1500, if %20, update +1 * first 500, if %50, delete * last 1500, if %50, delete * * 2000- 3999 * 4000- 5999 * 6000- 7999 * 8000- 9999 *****************************************************************/ static void *fct2(void *arguments) { struct arg_struct *args = (struct arg_struct *)arguments; int base = (int)((Seq *)args->base); CF_DB *db; char key[256]; char val[256]; OpenDB(&db, dbid_classes); for(int i = base*2000; i #include #include /* xsnprintf */ #include #include #include /* PurgeOldConnections */ const int CONNECTION_MAX_AGE_SECONDS = SECONDS_PER_HOUR * 2; /* NOTE: Invalid memory access has been seen in PurgeOldConnections(). This does not always result in a segfault, but running this test in valgrind will detect it. */ static void test_purge_old_connections_nochange(void) { const time_t time_now = 100000; Item *connections = NULL; char time_str[64]; xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS); PrependItem(&connections, "123.123.123.3", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 1); PrependItem(&connections, "123.123.123.2", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 100); PrependItem(&connections, "123.123.123.1", time_str); assert_int_equal(ListLen(connections), 3); PurgeOldConnections(&connections, time_now); assert_int_equal(ListLen(connections), 3); assert_true(IsItemIn(connections, "123.123.123.1")); assert_true(IsItemIn(connections, "123.123.123.2")); assert_true(IsItemIn(connections, "123.123.123.3")); DeleteItemList(connections); } static void test_purge_old_connections_purge_first(void) { const time_t time_now = 100000; Item *connections = NULL; char time_str[64]; xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 100); PrependItem(&connections, "123.123.123.3", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 2); PrependItem(&connections, "123.123.123.2", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS - 5); PrependItem(&connections, "123.123.123.1", time_str); assert_int_equal(ListLen(connections), 3); PurgeOldConnections(&connections, time_now); assert_int_equal(ListLen(connections), 2); assert_false(IsItemIn(connections, "123.123.123.1")); assert_true(IsItemIn(connections, "123.123.123.2")); assert_true(IsItemIn(connections, "123.123.123.3")); DeleteItemList(connections); } static void test_purge_old_connections_purge_middle(void) { const time_t time_now = 100000; Item *connections = NULL; char time_str[64]; xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS); PrependItem(&connections, "123.123.123.3", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS - 1); PrependItem(&connections, "123.123.123.2", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 100); PrependItem(&connections, "123.123.123.1", time_str); assert_int_equal(ListLen(connections), 3); PurgeOldConnections(&connections, time_now); assert_int_equal(ListLen(connections), 2); assert_true(IsItemIn(connections, "123.123.123.1")); assert_false(IsItemIn(connections, "123.123.123.2")); assert_true(IsItemIn(connections, "123.123.123.3")); DeleteItemList(connections); } static void test_purge_old_connections_purge_last(void) { const time_t time_now = 100000; Item *connections = NULL; char time_str[64]; xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS - 100); PrependItem(&connections, "123.123.123.3", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS + 10); PrependItem(&connections, "123.123.123.2", time_str); xsnprintf(time_str, sizeof(time_str), "%ld", time_now - CONNECTION_MAX_AGE_SECONDS); PrependItem(&connections, "123.123.123.1", time_str); assert_int_equal(ListLen(connections), 3); PurgeOldConnections(&connections, time_now); assert_int_equal(ListLen(connections), 2); assert_true(IsItemIn(connections, "123.123.123.1")); assert_true(IsItemIn(connections, "123.123.123.2")); assert_false(IsItemIn(connections, "123.123.123.3")); DeleteItemList(connections); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_purge_old_connections_nochange), unit_test(test_purge_old_connections_purge_first), unit_test(test_purge_old_connections_purge_middle), unit_test(test_purge_old_connections_purge_last) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/logging_timestamp_test.c0000664000175100017510000000250712411001073022044 0ustar00a10038a1003800000000000000#include #include #include #include static void test_timestamp_regex(void) { fflush(stderr); fflush(stdout); int pipe_fd[2]; assert_int_equal(pipe(pipe_fd), 0); // Duplicate stderr. int duplicate_stderr = dup(2); assert_true(duplicate_stderr >= 0); // Make stderr point to the pipe. assert_int_equal(dup2(pipe_fd[1], 2), 2); Log(LOG_LEVEL_ERR, "Test string"); fputc('\n', stderr); /* Make sure fgets() doesn't hang. */ fflush(stderr); fflush(stdout); // Restore stdout. assert_int_equal(dup2(duplicate_stderr, 2), 2); char buf[CF_BUFSIZE]; FILE *pipe_read_end = fdopen(pipe_fd[0], "r"); assert_true(pipe_read_end != NULL); assert_true(fgets(buf, sizeof(buf), pipe_read_end) != NULL); const char *errptr; int erroffset; pcre *regex = pcre_compile(LOGGING_TIMESTAMP_REGEX, PCRE_MULTILINE, &errptr, &erroffset, NULL); assert_true(regex != NULL); assert_true(pcre_exec(regex, NULL, buf, strlen(buf), 0, 0, NULL, 0) >= 0); fclose(pipe_read_end); close(pipe_fd[0]); close(pipe_fd[1]); close(duplicate_stderr); pcre_free(regex); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_timestamp_regex), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/cf_key_functions_test.c0000644000175100017510000000063312352022221021661 0ustar00a10038a1003800000000000000#include #include #include #include #include // Satisfy extern declared signal flag in cf-key-functions.c bool cf_key_interrupted = false; static void test_RemoveKeys(void) { assert_true(1); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_RemoveKeys) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/item_lib_test.c0000644000175100017510000000307612316547775020153 0ustar00a10038a1003800000000000000#include #include #include /* FIXME: MatchRegion is now internal function of cf-agent */ #if 0 static void test_match_region(void) { EvalContext *ctx =EvalContextNew(); Item *items = NULL; Item *begin, *end; PrependItem(&items, "third", NULL); assert_true(MatchRegion(ctx, "third", items, NULL, false)); end = items; PrependItem(&items, "second", NULL); PrependItem(&items, "first", NULL); begin = items; assert_true(MatchRegion(ctx, "first", begin, end, false)); assert_false(MatchRegion(ctx, "second", begin, end, false)); assert_false(MatchRegion(ctx, "third", begin, end, false)); assert_true(MatchRegion(ctx, "first\nsecond", begin, end, false)); assert_false(MatchRegion(ctx, "first\nthird", begin, end, false)); assert_false(MatchRegion(ctx, "second\nthird", begin, end, false)); assert_false(MatchRegion(ctx, "first\nsecond\nthird", begin, end, false)); assert_true(MatchRegion(ctx, "first", begin, NULL, false)); assert_false(MatchRegion(ctx, "second", begin, NULL, false)); assert_false(MatchRegion(ctx, "third", begin, NULL, false)); assert_true(MatchRegion(ctx, "first\nsecond", begin, NULL, false)); assert_false(MatchRegion(ctx, "first\nthird", begin, NULL, false)); assert_false(MatchRegion(ctx, "second\nthird", begin, NULL, false)); assert_true(MatchRegion(ctx, "first\nsecond\nthird", begin, NULL, false)); } #endif int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { }; return run_tests(tests); } // STUBS cfengine-3.6.2/tests/unit/list_test.c0000664000175100017510000007465412400110676017332 0ustar00a10038a1003800000000000000#include #include #include #include // Simple initialization test static void test_initList(void) { List *list = NULL; list = ListNew(NULL, NULL, NULL); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); // We shouldn't use this function yet, but otherwise we leak memory assert_int_equal(ListDestroy(&list), 0); } // This function is just an example function for the destroyer #include void testDestroyer(void *element) { // We know the elements are just char * char *s = (char *)element; printf("element: %s \n", s); free (s); } static void test_destroyer(void) { List *list = NULL; list = ListNew(NULL, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); assert_int_equal(list->compare, NULL); assert_int_equal(list->copy, NULL); assert_int_not_equal(list->destroy, NULL); char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); char *element2 = xstrdup("yet another test string"); char *element3 = xstrdup("and one more test string"); // We add element0 to the list. assert_int_equal(ListPrepend(list, element0), 0); // We add element1 to the list. assert_int_equal(ListPrepend(list, element1), 0); // We add element2 to the list. assert_int_equal(ListPrepend(list, element2), 0); // We add element3 to the list. assert_int_equal(ListPrepend(list, element3), 0); // Now we try to destroy the list. assert_int_equal(ListDestroy(&list), 0); } static void test_prependToList(void) { List *list = NULL; list = ListNew(NULL, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); assert_int_equal(list->compare, NULL); assert_int_equal(list->copy, NULL); assert_int_not_equal(list->destroy, NULL); char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); void *listPointer = NULL; void *firstPointer = NULL; void *lastPointer = NULL; // We add element0 to the list. assert_int_equal(ListPrepend(list, element0), 0); // Now we check the list assert_int_not_equal(list->first, NULL); firstPointer = list->first; assert_int_not_equal(list->list, NULL); listPointer = list->list; assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); lastPointer = list->last; assert_int_equal(list->node_count, 1); // Adding elements does not change the state of the list assert_int_equal(list->state, 0); // We add element1 to the list. assert_int_equal(ListPrepend(list, element1), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == firstPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 2); assert_int_equal(list->state, 0); // Now we try to destroy the list. This should fail because the list is not empty assert_int_equal(ListDestroy(&list), 0); } static void test_appendToList(void) { List *list = NULL; list = ListNew(NULL, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); void *element0tPointer = NULL; // We add element0 to the list. assert_int_equal(ListAppend(list, element0), 0); // Now we check the list assert_int_not_equal(list->first, NULL); element0tPointer = list->first; assert_int_not_equal(list->list, NULL); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_true(list->last == list->first); assert_int_equal(list->node_count, 1); // Adding elements does not change the list state assert_int_equal(list->state, 0); // We add element1 to the list. assert_int_equal(ListAppend(list, element1), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_int_not_equal(list->list, NULL); assert_int_not_equal(list->last, NULL); assert_true(element0tPointer == list->list); assert_true(element0tPointer == list->first); assert_false(list->first == list->last); assert_int_equal(list->node_count, 2); assert_int_equal(list->state, 0); // Now we try to destroy the list. This should fail because the list is not empty assert_int_equal(ListDestroy(&list), 0); } static int compareFunction(const void *a, const void *b) { return strcmp(a, b); } static void copyFunction(const void *s, void **d) { if (!s || !d) return; const char *source = s; char **destination = (char **)d; *destination = xstrdup(source); } static void test_removeFromList(void) { List *list = NULL; list = ListNew(compareFunction, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); assert_int_not_equal(list->destroy, NULL); assert_int_not_equal(list->compare, NULL); assert_int_equal(list->copy, NULL); char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); char *element2 = xstrdup("yet another test string"); char *element3 = xstrdup("and one more test string"); char *element4 = xstrdup("non existing element"); void *listPointer = NULL; void *firstPointer = NULL; void *secondPointer = NULL; void *thirdPointer = NULL; void *lastPointer = NULL; // We add element0 to the list. assert_int_equal(ListPrepend(list, element0), 0); // Now we check the list assert_int_not_equal(list->first, NULL); firstPointer = list->first; assert_int_not_equal(list->list, NULL); listPointer = list->list; assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); lastPointer = list->last; assert_int_equal(list->node_count, 1); // Adding elements does not change the list state assert_int_equal(list->state, 0); // We add element1 to the list. assert_int_equal(ListPrepend(list, element1), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == firstPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); secondPointer = list->list; assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 2); assert_int_equal(list->state, 0); // We add element2 to the list. assert_int_equal(ListPrepend(list, element2), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == firstPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); thirdPointer = list->list; assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 3); assert_int_equal(list->state, 0); // We add element3 to the list. assert_int_equal(ListPrepend(list, element3), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == firstPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 4); assert_int_equal(list->state, 0); // We remove the non existing element assert_int_equal(ListRemove(list, element4), -1); assert_int_not_equal(list->first, NULL); assert_false(list->first == firstPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 4); assert_int_equal(list->state, 0); // Remove element1 which is in the middle of the list assert_int_equal(ListRemove(list, element1), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == firstPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 3); assert_int_equal(list->state, 1); // Remove element3 which is at the beginning of the list assert_int_equal(ListRemove(list, element3), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == secondPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_true(list->last == lastPointer); assert_int_equal(list->node_count, 2); assert_int_equal(list->state, 2); // Remove element0 which is at the end of the list assert_int_equal(ListRemove(list, element0), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == secondPointer); assert_int_not_equal(list->list, NULL); assert_false(list->list == listPointer); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_true(list->last == thirdPointer); assert_int_equal(list->node_count, 1); assert_int_equal(list->state, 3); // Remove element2 which is the only element on the list assert_int_equal(ListRemove(list, element2), 0); // Now we check the list assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 4); // Now we destroy the list. assert_int_equal(ListDestroy(&list), 0); free (element4); } static void test_destroyList(void) { List *list = NULL; list = ListNew(NULL, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); // Now we destroy the list assert_int_equal(ListDestroy(&list), 0); assert_int_equal(list, NULL); } static void test_copyList(void) { /* * First try the normal path, i.e. with a copy function. Then try it without a copy function. */ List *list1 = NULL; List *list2 = NULL; List *list3 = NULL; List *list4 = NULL; char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); char *element2 = xstrdup("yet another test string"); list1 = ListNew(compareFunction, copyFunction, testDestroyer); assert_true(list1 != NULL); assert_int_not_equal(list1, NULL); assert_int_equal(list1->first, NULL); assert_int_equal(list1->list, NULL); assert_int_equal(list1->last, NULL); assert_int_equal(list1->node_count, 0); assert_int_equal(list1->state, 0); assert_int_equal(0, ListPrepend(list1, (void *)element0)); assert_int_equal(1, ListCount(list1)); /* * Copy the list1 to list2 and prepend one more element */ assert_int_equal(0, ListCopy(list1, &list2)); assert_int_equal(1, ListCount(list2)); assert_true(list1->ref_count == list2->ref_count); assert_int_equal(0, ListPrepend(list2, (void *)element1)); /* * The two lists have detached now. */ assert_int_equal(1, ListCount(list1)); assert_int_equal(2, ListCount(list2)); assert_false(list1->ref_count == list2->ref_count); /* * Add one more element to list1 and then attach list3 and list4. * Finally detach list4 by removing one element. */ assert_int_equal(0, ListPrepend(list1, (void *)element2)); assert_int_equal(0, ListCopy(list1, &list3)); assert_int_equal(0, ListCopy(list1, &list4)); assert_int_equal(2, ListCount(list1)); assert_int_equal(2, ListCount(list3)); assert_int_equal(2, ListCount(list4)); assert_true(list1->ref_count == list3->ref_count); assert_true(list1->ref_count == list4->ref_count); assert_true(list4->ref_count == list3->ref_count); assert_int_equal(0, ListRemove(list4, (void *)element0)); assert_int_equal(2, ListCount(list1)); assert_int_equal(2, ListCount(list3)); assert_int_equal(1, ListCount(list4)); assert_true(list1->ref_count == list3->ref_count); assert_false(list1->ref_count == list4->ref_count); assert_false(list4->ref_count == list3->ref_count); assert_int_equal(ListDestroy(&list1), 0); assert_int_equal(ListDestroy(&list2), 0); assert_int_equal(ListDestroy(&list3), 0); assert_int_equal(ListDestroy(&list4), 0); /* * No copy function now, boys don't cry */ List *list5 = NULL; List *list6 = NULL; element0 = xstrdup("this is a test string"); list5 = ListNew(compareFunction, NULL, testDestroyer); assert_true(list5 != NULL); assert_int_not_equal(list5, NULL); assert_int_equal(list5->first, NULL); assert_int_equal(list5->list, NULL); assert_int_equal(list5->last, NULL); assert_int_equal(list5->node_count, 0); assert_int_equal(list5->state, 0); assert_int_equal(0, ListPrepend(list5, (void *)element0)); assert_int_equal(1, ListCount(list5)); /* * Copy the list5 to list6 and prepend one more element */ assert_int_equal(-1, ListCopy(list5, &list6)); assert_true(list6 == NULL); assert_int_equal(ListDestroy(&list5), 0); } static void test_iterator(void) { List *list = NULL; list = ListNew(compareFunction, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); ListIterator *emptyListIterator = NULL; emptyListIterator = ListIteratorGet(list); assert_true(emptyListIterator == NULL); char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); char *element2 = xstrdup("yet another test string"); char *element3 = xstrdup("and one more test string"); void *element0Pointer = NULL; void *element1Pointer = NULL; void *element2Pointer = NULL; void *element3Pointer = NULL; // We add element0 to the list. assert_int_equal(ListPrepend(list, element0), 0); // Now we check the list assert_int_not_equal(list->first, NULL); element0Pointer = list->first; assert_true(list->first == element0Pointer); assert_int_not_equal(list->list, NULL); assert_true(list->list == list->first); assert_int_not_equal(list->last, NULL); assert_int_equal(list->node_count, 1); assert_int_equal(list->state, 0); // We add element1 to the list. assert_int_equal(ListPrepend(list, element1), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == element0Pointer); assert_int_not_equal(list->list, NULL); element1Pointer = list->list; assert_true(list->first == element1Pointer); assert_int_not_equal(list->last, NULL); assert_true(list->last == element0Pointer); assert_int_equal(list->node_count, 2); assert_int_equal(list->state, 0); // We add element2 to the list. assert_int_equal(ListPrepend(list, element2), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == element1Pointer); assert_int_not_equal(list->list, NULL); element2Pointer = list->list; assert_true(list->first == element2Pointer); assert_int_not_equal(list->last, NULL); assert_true(list->last == element0Pointer); assert_int_equal(list->node_count, 3); assert_int_equal(list->state, 0); // We add element3 to the list. assert_int_equal(ListPrepend(list, element3), 0); // Now we check the list assert_int_not_equal(list->first, NULL); assert_false(list->first == element2Pointer); assert_int_not_equal(list->list, NULL); element3Pointer = list->list; assert_true(list->first == element3Pointer); assert_int_not_equal(list->last, NULL); assert_true(list->last == element0Pointer); assert_int_equal(list->node_count, 4); assert_int_equal(list->state, 0); ListIterator *iterator0 = NULL; iterator0 = ListIteratorGet(list); // Check the iterator assert_true(iterator0 != NULL); assert_int_equal(iterator0->state, 0); assert_true(iterator0->origin == list); assert_true(iterator0->current == list->first); // Remove element1 which is in the middle of the list, this will invalidate the iterator assert_int_equal(ListRemove(list, element1), 0); // Check that the iterator is not valid by trying to advance it assert_int_equal(ListIteratorNext(iterator0), -1); // Destroy the iterator assert_int_equal(ListIteratorDestroy(&iterator0), 0); assert_int_equal(iterator0, NULL); // Create a new iterator and move it ListIterator *iterator1 = NULL; iterator1 = ListIteratorGet(list); // Check the iterator assert_int_not_equal(iterator1, NULL); assert_int_equal(iterator1->state, 1); assert_true(iterator1->origin == list); assert_true(iterator1->current == list->first); void *value = NULL; value = ListIteratorData(iterator1); assert_true(value == element3); // Advance it assert_int_equal(ListIteratorNext(iterator1), 0); // Check the value, it should be equal to element2 value = ListIteratorData(iterator1); assert_true(value == element2); // Advance it, now we are at the last element assert_int_equal(ListIteratorNext(iterator1), 0); // Check the value, it should be equal to element0 value = ListIteratorData(iterator1); assert_true(value == element0); // Advance it, should fail and the iterator should stay where it was assert_int_equal(ListIteratorNext(iterator1), -1); // Check the value, it should be equal to element0 value = ListIteratorData(iterator1); assert_true(value == element0); // Go back assert_int_equal(ListIteratorPrevious(iterator1), 0); // Check the value, it should be equal to element2 value = ListIteratorData(iterator1); assert_true(value == element2); // Go back, now we are at the beginning of the list assert_int_equal(ListIteratorPrevious(iterator1), 0); // Check the value, it should be equal to element3 value = ListIteratorData(iterator1); assert_true(value == element3); // Go back, should fail and the iterator should stay where it was assert_int_equal(ListIteratorPrevious(iterator1), -1); // Check the value, it should be equal to element3 value = ListIteratorData(iterator1); assert_true(value == element3); // Jump to the last element assert_int_equal(ListIteratorLast(iterator1), 0); // Check the value, it should be equal to element0 value = ListIteratorData(iterator1); assert_true(value == element0); // Go back assert_true(ListIteratorHasPrevious(iterator1)); assert_int_equal(ListIteratorPrevious(iterator1), 0); // Check the value, it should be equal to element2 value = ListIteratorData(iterator1); assert_true(value == element2); // Jump to the first element assert_int_equal(ListIteratorFirst(iterator1), 0); // Check the value, it should be equal to element3 value = ListIteratorData(iterator1); assert_true(value == element3); // Advance it assert_true(ListIteratorHasNext(iterator1)); assert_int_equal(ListIteratorNext(iterator1), 0); // Check the value, it should be equal to element2 value = ListIteratorData(iterator1); assert_true(value == element2); // Remove the elements assert_int_equal(ListRemove(list, element3), 0); assert_int_equal(ListRemove(list, element0), 0); assert_int_equal(ListRemove(list, element2), 0); // Destroy the iterator assert_int_equal(ListIteratorDestroy(&iterator1), 0); // Now we destroy the list. assert_int_equal(ListDestroy(&list), 0); } static void test_mutableIterator(void) { List *list = NULL; list = ListNew(compareFunction, NULL, testDestroyer); assert_true(list != NULL); assert_int_not_equal(list, NULL); assert_int_equal(list->first, NULL); assert_int_equal(list->list, NULL); assert_int_equal(list->last, NULL); assert_int_equal(list->node_count, 0); assert_int_equal(list->state, 0); ListMutableIterator *emptyListIterator = NULL; emptyListIterator = ListMutableIteratorGet(list); assert_true(emptyListIterator == NULL); char *element0 = xstrdup("this is a test string"); char *element1 = xstrdup("another test string"); char *element2 = xstrdup("yet another test string"); char *element3 = xstrdup("and one more test string"); char *element4 = xstrdup("prepended by iterator"); char *element5 = xstrdup("appended by iterator"); char *element6 = xstrdup("appended by iterator, second time"); char *element7 = xstrdup("prepended by iterator, second time"); // We add element0 to the list. assert_int_equal(ListAppend(list, element0), 0); // We add element1 to the list. assert_int_equal(ListAppend(list, element1), 0); // We add element2 to the list. assert_int_equal(ListAppend(list, element2), 0); // We add element3 to the list. assert_int_equal(ListAppend(list, element3), 0); // We use a light iterator to check that is valid ListIterator *lightIterator = NULL; lightIterator = ListIteratorGet(list); ListMutableIterator *iterator = NULL; ListMutableIterator *secondIterator = NULL; iterator = ListMutableIteratorGet(list); assert_true(iterator != NULL); // The iterator should be pointing to the first element assert_true(iterator->current == list->first); // Trying to create a second iterator must fail secondIterator = ListMutableIteratorGet(list); assert_true(secondIterator == NULL); // Loop through the list until we get to the last element and then back while (ListMutableIteratorHasNext(iterator)) { assert_int_equal(0, ListMutableIteratorNext(iterator)); } assert_int_equal(-1, ListMutableIteratorNext(iterator)); // and back while (ListMutableIteratorHasPrevious(iterator)) { assert_int_equal(0, ListMutableIteratorPrevious(iterator)); } assert_int_equal(-1, ListMutableIteratorPrevious(iterator)); // Jump to the last element assert_int_equal(0, ListMutableIteratorLast(iterator)); // and back to the first element assert_int_equal(0, ListMutableIteratorFirst(iterator)); // Prepend one element at the beginning of the list assert_int_equal(0, ListMutableIteratorPrepend(iterator, (void *)element4)); assert_int_equal(5, list->node_count); // The light iterator is still valid assert_int_equal(list->state, lightIterator->state); // It should be possible to go back one element now. assert_int_equal(0, ListMutableIteratorPrevious(iterator)); // Check that the list and the iterator agree who is the first one. assert_true(list->first == iterator->current); // Append one element after the first element assert_int_equal(0, ListMutableIteratorAppend(iterator, (void *)element5)); assert_int_equal(6, list->node_count); // The light iterator is still valid assert_int_equal(list->state, lightIterator->state); // Loop through the list until we get to the last element and then back while (ListMutableIteratorHasNext(iterator)) { assert_int_equal(0, ListMutableIteratorNext(iterator)); } assert_int_equal(-1, ListMutableIteratorNext(iterator)); // and back while (ListMutableIteratorHasPrevious(iterator)) { assert_int_equal(0, ListMutableIteratorPrevious(iterator)); } assert_int_equal(-1, ListMutableIteratorPrevious(iterator)); // Jump to the last element assert_int_equal(0, ListMutableIteratorLast(iterator)); // and back to the first element assert_int_equal(0, ListMutableIteratorFirst(iterator)); // And back to the last element assert_int_equal(0, ListMutableIteratorLast(iterator)); // Append one element after the last element assert_int_equal(0, ListMutableIteratorAppend(iterator, (void *)element6)); assert_int_equal(7, list->node_count); // The light iterator is still valid assert_int_equal(list->state, lightIterator->state); // It should be possible to advance one position assert_int_equal(0, ListMutableIteratorNext(iterator)); // Check that both the list and the iterator point to the same last element assert_true(iterator->current == list->last); // Prepend one element before the last element assert_int_equal(0, ListMutableIteratorPrepend(iterator, (void *)element7)); assert_int_equal(8, list->node_count); // The light iterator is still valid assert_int_equal(list->state, lightIterator->state); // Go back one element and remove the element assert_int_equal(0, ListMutableIteratorPrevious(iterator)); // We should be located at element4 assert_string_equal(element7, (char *)iterator->current->payload); // Remove the current element assert_int_equal(0, ListMutableIteratorRemove(iterator)); // Check that the list agrees assert_int_equal(7, list->node_count); // We should be at element5 now, the last element of the list assert_string_equal(element6, (char *)iterator->current->payload); assert_true(iterator->current == list->last); // The light iterator is not valid anymore assert_false(list->state == lightIterator->state); // Remove the last element, we should go back to element3 assert_int_equal(0, ListMutableIteratorRemove(iterator)); // Check that the list agrees assert_int_equal(6, list->node_count); // We should be at element3 now, the last element of the list assert_string_equal(element3, (char *)iterator->current->payload); assert_true(iterator->current == list->last); // Jump to the first element of the list assert_int_equal(0, ListMutableIteratorFirst(iterator)); // Remove the first element, we should end up in element5 assert_int_equal(0, ListMutableIteratorRemove(iterator)); // Check that the list agrees assert_int_equal(5, list->node_count); // We should be at element5 now, the first element of the list assert_string_equal(element5, (char *)iterator->current->payload); assert_true(iterator->current == list->first); // Now remove element3, the last element of the list using the Remove function assert_int_equal(0, ListRemove(list, (void *)element3)); assert_int_equal(4, list->node_count); // We should be at element5 now, the first element of the list assert_string_equal(element5, (char *)iterator->current->payload); assert_true(iterator->current == list->first); // Jump to the last element of the list assert_int_equal(0, ListMutableIteratorLast(iterator)); // This should be element2 assert_string_equal(element2, (char *)iterator->current->payload); // Move the iterator to the previous element, element1, and delete it. The iterator should move to element2. assert_int_equal(0, ListMutableIteratorPrevious(iterator)); assert_int_equal(0, ListRemove(list, (void *)element1)); assert_int_equal(3, list->node_count); assert_string_equal(element2, (char *)iterator->current->payload); assert_true(iterator->current == list->last); // Remove the last element of the list, the iterator should move to element0 assert_int_equal(0, ListRemove(list, (void *)element2)); assert_int_equal(2, list->node_count); assert_string_equal(element0, (char *)iterator->current->payload); assert_true(iterator->current == list->last); // Jump to the first element assert_int_equal(0, ListMutableIteratorFirst(iterator)); // Remove the first element, that should move the iterator to element0 assert_int_equal(0, ListRemove(list, (void *)element5)); assert_int_equal(1, list->node_count); assert_string_equal(element0, (char *)iterator->current->payload); assert_true(iterator->current == list->last); assert_true(iterator->current == list->first); // Finally try to remove the only element using the iterator, it should fail. assert_int_equal(-1, ListMutableIteratorRemove(iterator)); // Remove the final element using the list and check that the iterator is invalid assert_int_equal(0, ListRemove(list, (void *)element0)); assert_false(iterator->valid); // Destroy the iterators and the list assert_int_equal(0, ListMutableIteratorRelease(&iterator)); assert_int_equal(0, ListIteratorDestroy(&lightIterator)); assert_int_equal(0, ListDestroy(&list)); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_initList) , unit_test(test_destroyList) , unit_test(test_destroyer) , unit_test(test_prependToList) , unit_test(test_appendToList) , unit_test(test_removeFromList) , unit_test(test_copyList) , unit_test(test_iterator) , unit_test(test_mutableIterator) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/scope_test.c0000664000175100017510000000177612400110676017463 0ustar00a10038a1003800000000000000#include #include #include #include static void test_name_join(void) { { char buf[CF_MAXVARSIZE] = { 0 }; JoinScopeName(NULL, "sys", buf); assert_string_equal("sys", buf); } { char buf[CF_MAXVARSIZE] = { 0 }; JoinScopeName("ns", "b", buf); assert_string_equal("ns:b", buf); } } static void test_name_split(void) { { char ns[CF_MAXVARSIZE] = { 0 }; char b[CF_MAXVARSIZE] = { 0 }; SplitScopeName("sys", ns, b); assert_string_equal("", ns); assert_string_equal("sys", b); } { char ns[CF_MAXVARSIZE] = { 0 }; char b[CF_MAXVARSIZE] = { 0 }; SplitScopeName("ns:b", ns, b); assert_string_equal("ns", ns); assert_string_equal("b", b); } } int main() { const UnitTest tests[] = { unit_test(test_name_split), unit_test(test_name_join), }; PRINT_TEST_BANNER(); return run_tests(tests); } cfengine-3.6.2/tests/unit/solaris_process_test.c0000664000175100017510000000561712400110676021562 0ustar00a10038a1003800000000000000#include #include #include #include /* * procfs.h is not 64-bit off_t clean, but the only affected structure is * priovec, which we don't use. Hence we may work around #error in sys/procfs.h * by lying that we are not compiling with large file support (while we do). */ #define _FILE_OFFSET_BITS 32 #include int open(const char *filename, int flags, ...) { if (!strcmp(filename, "/proc/1/psinfo")) { return 1; } if (!strcmp(filename, "/proc/1/status")) { return 101; } if (!strcmp(filename, "/proc/2/status")) { return 102; } errno = ENOENT; return -1; } int fdpos[3]; ssize_t read(int fd, void *buf, size_t bufsize) { if (fd == 1) { if (fdpos[0] == 0) { psinfo_t psinfo; psinfo.pr_start.tv_sec = 100; memcpy(buf, &psinfo, sizeof(psinfo)); fdpos[0] = sizeof(psinfo); return sizeof(psinfo); } else { return 0; } } if (fd == 101) { if (fdpos[1] == 0) { pstatus_t pstatus; pstatus.pr_lwp.pr_flags = PR_STOPPED; pstatus.pr_lwp.pr_why = PR_SIGNALLED; memcpy(buf, &pstatus, sizeof(pstatus)); fdpos[1] = sizeof(pstatus); return sizeof(pstatus); } else { return 0; } } if (fd == 102) { if (fdpos[2] == 0) { pstatus_t pstatus; pstatus.pr_lwp.pr_flags = 0; pstatus.pr_lwp.pr_why = 0; memcpy(buf, &pstatus, sizeof(pstatus)); fdpos[2] = sizeof(pstatus); return sizeof(pstatus); } else { return 0; } } errno = EIO; return -1; } int close(int fd) { return 0; } static void test_get_start_time_process1(void) { time_t t = GetProcessStartTime(1); assert_int_equal(t, 100); } static void test_get_start_time_process2(void) { time_t t = GetProcessStartTime(2); assert_int_equal(t, PROCESS_START_TIME_UNKNOWN); } static void test_get_state_process1(void) { ProcessState s = GetProcessState(1); assert_int_equal(s, PROCESS_STATE_STOPPED); } static void test_get_state_process2(void) { ProcessState s = GetProcessState(2); assert_int_equal(s, PROCESS_STATE_RUNNING); } static void test_get_state_process3(void) { ProcessState s = GetProcessState(3); assert_int_equal(s, PROCESS_STATE_DOES_NOT_EXIST); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_get_start_time_process1), unit_test(test_get_start_time_process2), unit_test(test_get_state_process1), unit_test(test_get_state_process2), unit_test(test_get_state_process3), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/data/0000775000175100017510000000000012406606752016060 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/unit/data/bundle_body_wrong_statement.cf0000664000175100017510000000007712243421446024156 0ustar00a10038a1003800000000000000bundle agent foo { vars: invalid string => "foo"; } cfengine-3.6.2/tests/unit/data/bundle_body_promiser_wrong_constraint_token.cf0000664000175100017510000000012612243421446027451 0ustar00a10038a1003800000000000000bundle agent foo { vars: "a" string => "foo", "comment" => "bar"; } cfengine-3.6.2/tests/unit/data/rval_function_forgot_cp_colon.cf0000664000175100017510000000017512243421446024474 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "env" string => getenv("PATH", "20" , comment => 'get path"; } cfengine-3.6.2/tests/unit/data/rval_function_forgot_cp_semicolon.cf0000664000175100017510000000014312243421446025345 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "env" string => getenv("PATH", "20" ; } cfengine-3.6.2/tests/unit/data/bundle_body_forgot_ob.cf0000664000175100017510000000002712236160673022715 0ustar00a10038a1003800000000000000bundle agent foo(a) } cfengine-3.6.2/tests/unit/data/bundle_body_promise_missing_arrow.cf0000664000175100017510000000017012243421446025351 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "HvB" - { "@(stakeholders[$(service)])" } comment => "foobar"; } cfengine-3.6.2/tests/unit/data/body_selection_wrong_token.cf0000664000175100017510000000042612243421446024004 0ustar00a10038a1003800000000000000body classes surfsara_all_classes(x) { "promise_repaired" => { "$(x)_repaired" }; promise_kept => { "$(x)_kept" }; repair_failed => { "$(x)_failed" }; repair_denied => { "$(x)_denied" }; repair_timeout => { "$(x)_timeout" }; } cfengine-3.6.2/tests/unit/data/benchmark.json0000664000175100017510000001642512243421446020707 0ustar00a10038a1003800000000000000{ "bundles": [ { "sourcePath": "tests/unit/data/benchmark.cf", "line": 9, "namespace": "default", "name": "main", "bundleType": "agent", "arguments": [], "promiseTypes": [ { "line": 11, "name": "reports", "contexts": [ { "name": "cfengine", "promises": [ { "line": 13, "promiser": "Hello, CFEngine", "attributes": [ { "line": 14, "lval": "friend_pattern", "rval": { "type": "functionCall", "name": "hash", "arguments": [ { "type": "string", "value": "abc" }, { "type": "string", "value": "md5" } ] } } ] } ] }, { "name": "any", "promises": [ { "line": 16, "promiser": "Hello, world", "attributes": [ { "line": 17, "lval": "friend_pattern", "rval": { "type": "functionCall", "name": "hash", "arguments": [ { "type": "string", "value": "abc" }, { "type": "string", "value": "md5" } ] } } ] } ] } ] }, { "line": 19, "name": "files", "contexts": [ { "name": "any", "promises": [ { "line": 20, "promiser": "/tmp/stuff", "promisee": [ "stakeholder" ], "attributes": [ { "line": 21, "lval": "create", "rval": { "type": "string", "value": "true" } }, { "line": 22, "lval": "perms", "rval": { "type": "symbol", "value": "myperms" } } ] } ] } ] }, { "line": 24, "name": "processes", "contexts": [ { "name": "any", "promises": [ { "line": 25, "promiser": "/bin/stuff", "promisee": [ "stakeholder" ], "attributes": [] } ] } ] } ] } ], "bodies": [ { "sourcePath": "tests/unit/data/benchmark.cf", "line": 4, "namespace": "default", "name": "control", "bodyType": "common", "arguments": [], "contexts": [ { "name": "any", "attributes": [ { "line": 6, "lval": "bundlesequence", "rval": { "type": "list", "value": [ { "type": "string", "value": "main" } ] } } ] } ] }, { "sourcePath": "tests/unit/data/benchmark.cf", "line": 28, "namespace": "default", "name": "myperms", "bodyType": "perms", "arguments": [], "contexts": [ { "name": "any", "attributes": [ { "line": 30, "lval": "mode", "rval": { "type": "string", "value": "555" } } ] } ] } ] } cfengine-3.6.2/tests/unit/data/mustache_sections.json0000664000175100017510000002655512243421446022502 0ustar00a10038a1003800000000000000{ "__ATTN__": "Do not edit this file; changes belong in the appropriate YAML file.", "overview": "Section tags and End Section tags are used in combination to wrap a section\nof the template for iteration\n\nThese tags' content MUST be a non-whitespace character sequence NOT\ncontaining the current closing delimiter; each Section tag MUST be followed\nby an End Section tag with the same content within the same section.\n\nThis tag's content names the data to replace the tag. Name resolution is as\nfollows:\n 1) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 2) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 3) If the context is a hash, the data is the value associated with the\n name.\n 4) If the context is an object and the method with the given name has an\n arity of 1, the method SHOULD be called with a String containing the\n unprocessed contents of the sections; the data is the value returned.\n 5) Otherwise, the data is the value returned by calling the method with\n the given name.\n 6) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\nIf the data is not of a list type, it is coerced into a list as follows: if\nthe data is truthy (e.g. `!!data == true`), use a single-element list\ncontaining the data, otherwise use an empty list.\n\nFor each element in the data list, the element MUST be pushed onto the\ncontext stack, the section MUST be rendered, and the element MUST be popped\noff the context stack.\n\nSection and End Section tags SHOULD be treated as standalone when\nappropriate.\n", "tests": [ { "name": "Truthy", "data": { "boolean": true }, "expected": "\"This should be rendered.\"", "template": "\"{{#boolean}}This should be rendered.{{/boolean}}\"", "desc": "Truthy sections should have their contents rendered." }, { "name": "Falsey", "data": { "boolean": false }, "expected": "\"\"", "template": "\"{{#boolean}}This should not be rendered.{{/boolean}}\"", "desc": "Falsey sections should have their contents omitted." }, { "name": "Context", "data": { "context": { "name": "Joe" } }, "expected": "\"Hi Joe.\"", "template": "\"{{#context}}Hi {{name}}.{{/context}}\"", "desc": "Objects and hashes should be pushed onto the context stack." }, { "name": "Deeply Nested Contexts", "data": { "a": { "one": 1 }, "b": { "two": 2 }, "c": { "three": 3 }, "d": { "four": 4 }, "e": { "five": 5 } }, "expected": "1\n121\n12321\n1234321\n123454321\n1234321\n12321\n121\n1\n", "template": "{{#a}}\n{{one}}\n{{#b}}\n{{one}}{{two}}{{one}}\n{{#c}}\n{{one}}{{two}}{{three}}{{two}}{{one}}\n{{#d}}\n{{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}\n{{#e}}\n{{one}}{{two}}{{three}}{{four}}{{five}}{{four}}{{three}}{{two}}{{one}}\n{{/e}}\n{{one}}{{two}}{{three}}{{four}}{{three}}{{two}}{{one}}\n{{/d}}\n{{one}}{{two}}{{three}}{{two}}{{one}}\n{{/c}}\n{{one}}{{two}}{{one}}\n{{/b}}\n{{one}}\n{{/a}}\n", "desc": "All elements on the context stack should be accessible." }, { "name": "List", "data": { "list": [ { "item": 1 }, { "item": 2 }, { "item": 3 } ] }, "expected": "\"123\"", "template": "\"{{#list}}{{item}}{{/list}}\"", "desc": "Lists should be iterated; list items should visit the context stack." }, { "name": "Empty List", "data": { "list": [] }, "expected": "\"\"", "template": "\"{{#list}}Yay lists!{{/list}}\"", "desc": "Empty lists should behave like falsey values." }, { "name": "Doubled", "data": { "two": "second", "bool": true }, "expected": "* first\n* second\n* third\n", "template": "{{#bool}}\n* first\n{{/bool}}\n* {{two}}\n{{#bool}}\n* third\n{{/bool}}\n", "desc": "Multiple sections per template should be permitted." }, { "name": "Nested (Truthy)", "data": { "bool": true }, "expected": "| A B C D E |", "template": "| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |", "desc": "Nested truthy sections should have their contents rendered." }, { "name": "Nested (Falsey)", "data": { "bool": false }, "expected": "| A E |", "template": "| A {{#bool}}B {{#bool}}C{{/bool}} D{{/bool}} E |", "desc": "Nested falsey sections should be omitted." }, { "name": "Context Misses", "data": {}, "expected": "[]", "template": "[{{#missing}}Found key 'missing'!{{/missing}}]", "desc": "Failed context lookups should be considered falsey." }, { "name": "Implicit Iterator - String", "data": { "list": [ "a", "b", "c", "d", "e" ] }, "expected": "\"(a)(b)(c)(d)(e)\"", "template": "\"{{#list}}({{.}}){{/list}}\"", "desc": "Implicit iterators should directly interpolate strings." }, { "name": "Implicit Iterator - Integer", "data": { "list": [ 1, 2, 3, 4, 5 ] }, "expected": "\"(1)(2)(3)(4)(5)\"", "template": "\"{{#list}}({{.}}){{/list}}\"", "desc": "Implicit iterators should cast integers to strings and interpolate." }, { "name": "Implicit Iterator - Decimal", "data": { "list": [ 1.1, 2.2, 3.3, 4.4, 5.5 ] }, "expected": "\"(1.10)(2.20)(3.30)(4.40)(5.50)\"", "template": "\"{{#list}}({{.}}){{/list}}\"", "desc": "Implicit iterators should cast decimals to strings and interpolate." }, { "name": "Dotted Names - Truthy", "data": { "a": { "b": { "c": true } } }, "expected": "\"Here\" == \"Here\"", "template": "\"{{#a.b.c}}Here{{/a.b.c}}\" == \"Here\"", "desc": "Dotted names should be valid for Section tags." }, { "name": "Dotted Names - Falsey", "data": { "a": { "b": { "c": false } } }, "expected": "\"\" == \"\"", "template": "\"{{#a.b.c}}Here{{/a.b.c}}\" == \"\"", "desc": "Dotted names should be valid for Section tags." }, { "name": "Dotted Names - Broken Chains", "data": { "a": {} }, "expected": "\"\" == \"\"", "template": "\"{{#a.b.c}}Here{{/a.b.c}}\" == \"\"", "desc": "Dotted names that cannot be resolved should be considered falsey." }, { "name": "Surrounding Whitespace", "data": { "boolean": true }, "expected": " | \t|\t | \n", "template": " | {{#boolean}}\t|\t{{/boolean}} | \n", "desc": "Sections should not alter surrounding whitespace." }, { "name": "Internal Whitespace", "data": { "boolean": true }, "expected": " | \n | \n", "template": " | {{#boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n", "desc": "Sections should not alter internal whitespace." }, { "name": "Indented Inline Sections", "data": { "boolean": true }, "expected": " YES\n GOOD\n", "template": " {{#boolean}}YES{{/boolean}}\n {{#boolean}}GOOD{{/boolean}}\n", "desc": "Single-line sections should not alter surrounding whitespace." }, { "name": "Standalone Lines", "data": { "boolean": true }, "expected": "| This Is\n|\n| A Line\n", "template": "| This Is\n{{#boolean}}\n|\n{{/boolean}}\n| A Line\n", "desc": "Standalone lines should be removed from the template." }, { "name": "Indented Standalone Lines", "data": { "boolean": true }, "expected": "| This Is\n|\n| A Line\n", "template": "| This Is\n {{#boolean}}\n|\n {{/boolean}}\n| A Line\n", "desc": "Indented standalone lines should be removed from the template." }, { "name": "Standalone Line Endings", "data": { "boolean": true }, "expected": "|\r\n|", "template": "|\r\n{{#boolean}}\r\n{{/boolean}}\r\n|", "desc": "\"\\r\\n\" should be considered a newline for standalone tags." }, { "name": "Standalone Without Previous Line", "data": { "boolean": true }, "expected": "#\n/", "template": " {{#boolean}}\n#{{/boolean}}\n/", "desc": "Standalone tags should not require a newline to precede them." }, { "name": "Standalone Without Newline", "data": { "boolean": true }, "expected": "#\n/\n", "template": "#{{#boolean}}\n/\n {{/boolean}}", "desc": "Standalone tags should not require a newline to follow them." }, { "name": "Padding", "data": { "boolean": true }, "expected": "|=|", "template": "|{{# boolean }}={{/ boolean }}|", "desc": "Superfluous in-tag whitespace should be ignored." } ] } cfengine-3.6.2/tests/unit/data/body_edit_line_common_constraints.cf0000664000175100017510000000013212243421446025330 0ustar00a10038a1003800000000000000bundle edit_line test { delete_lines: "abc" select_region => test_select; } cfengine-3.6.2/tests/unit/data/body_selection_forgot_semicolon.cf0000664000175100017510000000042312243421446025015 0ustar00a10038a1003800000000000000body classes surfsara_all_classes(x) { promise_repaired => { "$(x)_repaired" }; promise_kept => { "$(x)_kept" } repair_failed => { "$(x)_failed" }; repair_denied => { "$(x)_denied" }; repair_timeout => { "$(x)_timeout" }; } cfengine-3.6.2/tests/unit/data/bundle_body_forget_cb_eof.cf0000664000175100017510000000016112243421446023513 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "bas" string => "van der vlies", comment => "lastname"; cfengine-3.6.2/tests/unit/data/rval_function_wrong_input_type.cf0000664000175100017510000000013712243421446024732 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "env" string => getenv("PATH", "bas ); } cfengine-3.6.2/tests/unit/data/bundle_body_promiser_forgot_colon.cf0000664000175100017510000000017112243421446025343 0ustar00a10038a1003800000000000000bundle agent foo { vars: "foo" string => "bar", handle => "foo" comment => "test"; } cfengine-3.6.2/tests/unit/data/rval_list_forgot_colon.cf0000664000175100017510000000012212243421446023130 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: "family" slist => { "andre" "bas" }; } cfengine-3.6.2/tests/unit/data/body_redefinition.cf0000664000175100017510000000014212243421446022055 0ustar00a10038a1003800000000000000body agent control { ifelapsed => "60"; } body agent control { ifelapsed => "120"; } cfengine-3.6.2/tests/unit/data/bundle_reserved_name.cf0000664000175100017510000000010512243421446022530 0ustar00a10038a1003800000000000000bundle agent sys { reports: cfengine3:: "hello world"; } cfengine-3.6.2/tests/unit/data/bundle_body_forgot_semicolon.cf0000664000175100017510000000022112243421446024275 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "bas" string => "van der vlies", handle => "netherlands", comment => "lastname" } cfengine-3.6.2/tests/unit/data/mustache_inverted.json0000664000175100017510000002167112243421446022465 0ustar00a10038a1003800000000000000{ "__ATTN__": "Do not edit this file; changes belong in the appropriate YAML file.", "overview": "Inverted Section tags and End Section tags are used in combination to wrap a\nsection of the template.\n\nThese tags' content MUST be a non-whitespace character sequence NOT\ncontaining the current closing delimiter; each Inverted Section tag MUST be\nfollowed by an End Section tag with the same content within the same\nsection.\n\nThis tag's content names the data to replace the tag. Name resolution is as\nfollows:\n 1) Split the name on periods; the first part is the name to resolve, any\n remaining parts should be retained.\n 2) Walk the context stack from top to bottom, finding the first context\n that is a) a hash containing the name as a key OR b) an object responding\n to a method with the given name.\n 3) If the context is a hash, the data is the value associated with the\n name.\n 4) If the context is an object and the method with the given name has an\n arity of 1, the method SHOULD be called with a String containing the\n unprocessed contents of the sections; the data is the value returned.\n 5) Otherwise, the data is the value returned by calling the method with\n the given name.\n 6) If any name parts were retained in step 1, each should be resolved\n against a context stack containing only the result from the former\n resolution. If any part fails resolution, the result should be considered\n falsey, and should interpolate as the empty string.\nIf the data is not of a list type, it is coerced into a list as follows: if\nthe data is truthy (e.g. `!!data == true`), use a single-element list\ncontaining the data, otherwise use an empty list.\n\nThis section MUST NOT be rendered unless the data list is empty.\n\nInverted Section and End Section tags SHOULD be treated as standalone when\nappropriate.\n", "tests": [ { "name": "Falsey", "data": { "boolean": false }, "expected": "\"This should be rendered.\"", "template": "\"{{^boolean}}This should be rendered.{{/boolean}}\"", "desc": "Falsey sections should have their contents rendered." }, { "name": "Truthy", "data": { "boolean": true }, "expected": "\"\"", "template": "\"{{^boolean}}This should not be rendered.{{/boolean}}\"", "desc": "Truthy sections should have their contents omitted." }, { "name": "Context", "data": { "context": { "name": "Joe" } }, "expected": "\"\"", "template": "\"{{^context}}Hi {{name}}.{{/context}}\"", "desc": "Objects and hashes should behave like truthy values." }, { "name": "List", "data": { "list": [ { "n": 1 }, { "n": 2 }, { "n": 3 } ] }, "expected": "\"\"", "template": "\"{{^list}}{{n}}{{/list}}\"", "desc": "Lists should behave like truthy values." }, { "name": "Empty List", "data": { "list": [] }, "expected": "\"Yay lists!\"", "template": "\"{{^list}}Yay lists!{{/list}}\"", "desc": "Empty lists should behave like falsey values." }, { "name": "Doubled", "data": { "two": "second", "bool": false }, "expected": "* first\n* second\n* third\n", "template": "{{^bool}}\n* first\n{{/bool}}\n* {{two}}\n{{^bool}}\n* third\n{{/bool}}\n", "desc": "Multiple inverted sections per template should be permitted." }, { "name": "Nested (Falsey)", "data": { "bool": false }, "expected": "| A B C D E |", "template": "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |", "desc": "Nested falsey sections should have their contents rendered." }, { "name": "Nested (Truthy)", "data": { "bool": true }, "expected": "| A E |", "template": "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |", "desc": "Nested truthy sections should be omitted." }, { "name": "Context Misses", "data": {}, "expected": "[Cannot find key 'missing'!]", "template": "[{{^missing}}Cannot find key 'missing'!{{/missing}}]", "desc": "Failed context lookups should be considered falsey." }, { "name": "Dotted Names - Truthy", "data": { "a": { "b": { "c": true } } }, "expected": "\"\" == \"\"", "template": "\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"\"", "desc": "Dotted names should be valid for Inverted Section tags." }, { "name": "Dotted Names - Falsey", "data": { "a": { "b": { "c": false } } }, "expected": "\"Not Here\" == \"Not Here\"", "template": "\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"", "desc": "Dotted names should be valid for Inverted Section tags." }, { "name": "Dotted Names - Broken Chains", "data": { "a": {} }, "expected": "\"Not Here\" == \"Not Here\"", "template": "\"{{^a.b.c}}Not Here{{/a.b.c}}\" == \"Not Here\"", "desc": "Dotted names that cannot be resolved should be considered falsey." }, { "name": "Surrounding Whitespace", "data": { "boolean": false }, "expected": " | \t|\t | \n", "template": " | {{^boolean}}\t|\t{{/boolean}} | \n", "desc": "Inverted sections should not alter surrounding whitespace." }, { "name": "Internal Whitespace", "data": { "boolean": false }, "expected": " | \n | \n", "template": " | {{^boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n", "desc": "Inverted should not alter internal whitespace." }, { "name": "Indented Inline Sections", "data": { "boolean": false }, "expected": " NO\n WAY\n", "template": " {{^boolean}}NO{{/boolean}}\n {{^boolean}}WAY{{/boolean}}\n", "desc": "Single-line sections should not alter surrounding whitespace." }, { "name": "Standalone Lines", "data": { "boolean": false }, "expected": "| This Is\n|\n| A Line\n", "template": "| This Is\n{{^boolean}}\n|\n{{/boolean}}\n| A Line\n", "desc": "Standalone lines should be removed from the template." }, { "name": "Standalone Indented Lines", "data": { "boolean": false }, "expected": "| This Is\n|\n| A Line\n", "template": "| This Is\n {{^boolean}}\n|\n {{/boolean}}\n| A Line\n", "desc": "Standalone indented lines should be removed from the template." }, { "name": "Standalone Line Endings", "data": { "boolean": false }, "expected": "|\r\n|", "template": "|\r\n{{^boolean}}\r\n{{/boolean}}\r\n|", "desc": "\"\\r\\n\" should be considered a newline for standalone tags." }, { "name": "Standalone Without Previous Line", "data": { "boolean": false }, "expected": "^\n/", "template": " {{^boolean}}\n^{{/boolean}}\n/", "desc": "Standalone tags should not require a newline to precede them." }, { "name": "Standalone Without Newline", "data": { "boolean": false }, "expected": "^\n/\n", "template": "^{{^boolean}}\n/\n {{/boolean}}", "desc": "Standalone tags should not require a newline to follow them." }, { "name": "Padding", "data": { "boolean": false }, "expected": "|=|", "template": "|{{^ boolean }}={{/ boolean }}|", "desc": "Superfluous in-tag whitespace should be ignored." } ] } cfengine-3.6.2/tests/unit/data/rval_list_forgot_cb_semicolon.cf0000664000175100017510000000014412243421446024456 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "family" slist => { "andre", "bas" ; } cfengine-3.6.2/tests/unit/data/body_body_forget_cb_body.cf0000664000175100017510000000014012243421446023360 0ustar00a10038a1003800000000000000body classes repaired(x) { promise_repaired => { "$(x)_repaired" }; body classes foo { } cfengine-3.6.2/tests/unit/data/body_body_forget_cb_eof.cf0000664000175100017510000000011412243421446023175 0ustar00a10038a1003800000000000000body classes repaired(x) { promise_repaired => { "$(x)_repaired" }; cfengine-3.6.2/tests/unit/data/constraint_comment_nonscalar.cf0000664000175100017510000000011012243421446024322 0ustar00a10038a1003800000000000000bundle agent foo { reports: "hello" comment => { "a" }; } cfengine-3.6.2/tests/unit/data/body_selection_unknown_selection_id.cf0000664000175100017510000000042312243421446025665 0ustar00a10038a1003800000000000000body classes surfsara_all_classes(x) { promise_repaired => { "$(x)_repaired" }; promise_kpt => { "$(x)_kept" }; repair_failed => { "$(x)_failed" }; repair_denied => { "$(x)_denied" }; repair_timeout => { "$(x)_timeout" }; } cfengine-3.6.2/tests/unit/data/bundle_body_forget_cb_body.cf0000664000175100017510000000027512243421446023705 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "bas" string => "van der vlies", comment => "lastname"; body classes repaired(x) { promise_repaired => { "$(x)_repaired" }; } cfengine-3.6.2/tests/unit/data/vars_multiple_types.cf0000664000175100017510000000012512243421446022474 0ustar00a10038a1003800000000000000bundle agent foo { vars: "bar" string => "snookie", int => 42; } cfengine-3.6.2/tests/unit/data/bundle_body_wrong_promise_type_token.cf0000664000175100017510000000004512243421446026064 0ustar00a10038a1003800000000000000bundle agent foo { invalid:: } cfengine-3.6.2/tests/unit/data/rval_list_wrong_input_type.cf0000664000175100017510000000012412243421446024054 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: "family" slist => { "andre", bas:: } ; } cfengine-3.6.2/tests/unit/data/mustache_interpolation.json0000664000175100017510000001431212243421446023526 0ustar00a10038a1003800000000000000{ "tests": [ { "name": "No Interpolation", "data": {}, "expected": "Hello from {Mustache}!\n", "template": "Hello from {Mustache}!\n", "desc": "Mustache-free templates should render as-is." }, { "name": "Basic Interpolation", "data": { "subject": "world" }, "expected": "Hello, world!\n", "template": "Hello, {{subject}}!\n", "desc": "Unadorned tags should interpolate content into the template." }, { "name": "HTML Escaping", "data": { "forbidden": "& \" < >" }, "expected": "These characters should be HTML escaped: & " < >\n", "template": "These characters should be HTML escaped: {{forbidden}}\n", "desc": "Basic interpolation should be HTML escaped." }, { "name": "Triple Mustache", "data": { "forbidden": "& \" < >" }, "expected": "These characters should not be HTML escaped: & \" < >\n", "template": "These characters should not be HTML escaped: {{{forbidden}}}\n", "desc": "Triple mustaches should interpolate without HTML escaping." }, { "name": "Ampersand", "data": { "forbidden": "& \" < >" }, "expected": "These characters should not be HTML escaped: & \" < >\n", "template": "These characters should not be HTML escaped: {{&forbidden}}\n", "desc": "Ampersand should interpolate without HTML escaping." }, { "name": "Basic Integer Interpolation", "data": { "mph": 85 }, "expected": "\"85 miles an hour!\"", "template": "\"{{mph}} miles an hour!\"", "desc": "Integers should interpolate seamlessly." }, { "name": "Triple Mustache Integer Interpolation", "data": { "mph": 85 }, "expected": "\"85 miles an hour!\"", "template": "\"{{{mph}}} miles an hour!\"", "desc": "Integers should interpolate seamlessly." }, { "name": "Ampersand Integer Interpolation", "data": { "mph": 85 }, "expected": "\"85 miles an hour!\"", "template": "\"{{&mph}} miles an hour!\"", "desc": "Integers should interpolate seamlessly." }, { "name": "Basic Decimal Interpolation", "data": { "power": 1.21 }, "expected": "\"1.21 jiggawatts!\"", "template": "\"{{power}} jiggawatts!\"", "desc": "Decimals should interpolate seamlessly with proper significance." }, { "name": "Triple Mustache Decimal Interpolation", "data": { "power": 1.21 }, "expected": "\"1.21 jiggawatts!\"", "template": "\"{{{power}}} jiggawatts!\"", "desc": "Decimals should interpolate seamlessly with proper significance." }, { "name": "Ampersand Decimal Interpolation", "data": { "power": 1.21 }, "expected": "\"1.21 jiggawatts!\"", "template": "\"{{&power}} jiggawatts!\"", "desc": "Decimals should interpolate seamlessly with proper significance." }, { "name": "Interpolation - Surrounding Whitespace", "data": { "string": "---" }, "expected": "| --- |", "template": "| {{string}} |", "desc": "Interpolation should not alter surrounding whitespace." }, { "name": "Triple Mustache - Surrounding Whitespace", "data": { "string": "---" }, "expected": "| --- |", "template": "| {{{string}}} |", "desc": "Interpolation should not alter surrounding whitespace." }, { "name": "Ampersand - Surrounding Whitespace", "data": { "string": "---" }, "expected": "| --- |", "template": "| {{&string}} |", "desc": "Interpolation should not alter surrounding whitespace." }, { "name": "Interpolation - Standalone", "data": { "string": "---" }, "expected": " ---\n", "template": " {{string}}\n", "desc": "Standalone interpolation should not alter surrounding whitespace." }, { "name": "Triple Mustache - Standalone", "data": { "string": "---" }, "expected": " ---\n", "template": " {{{string}}}\n", "desc": "Standalone interpolation should not alter surrounding whitespace." }, { "name": "Ampersand - Standalone", "data": { "string": "---" }, "expected": " ---\n", "template": " {{&string}}\n", "desc": "Standalone interpolation should not alter surrounding whitespace." }, { "name": "Interpolation With Padding", "data": { "string": "---" }, "expected": "|---|", "template": "|{{ string }}|", "desc": "Superfluous in-tag whitespace should be ignored." }, { "name": "Triple Mustache With Padding", "data": { "string": "---" }, "expected": "|---|", "template": "|{{{ string }}}|", "desc": "Superfluous in-tag whitespace should be ignored." }, { "name": "Ampersand With Padding", "data": { "string": "---" }, "expected": "|---|", "template": "|{{& string }}|", "desc": "Superfluous in-tag whitespace should be ignored." } ] } cfengine-3.6.2/tests/unit/data/body_control_no_arguments.cf0000644000175100017510000000007312316547775023657 0ustar00a10038a1003800000000000000body common control(arg) { bundlesequence => { test }; } cfengine-3.6.2/tests/unit/data/promise_promiser_nonscalar.cf0000664000175100017510000000006612243421446024024 0ustar00a10038a1003800000000000000bundle agent foo { vars: a string => "bar"; } cfengine-3.6.2/tests/unit/data/rval_list_forgot_cb_colon.cf0000664000175100017510000000020012243421446023571 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "family" slist => { "andre", "bas" , comment => "brothers"; } cfengine-3.6.2/tests/unit/data/mustache_extra.json0000664000175100017510000000446112243421446021766 0ustar00a10038a1003800000000000000{ "tests": [ { "name": "Demo", "data": { "header": "Colors", "items": [ {"name": "red", "first": true, "url": "#Red"}, {"name": "green", "link": true, "url": "#Green"}, {"name": "blue", "link": true, "url": "#Blue"} ], "empty": false }, "expected": "

Colors

\n\n
  • red
  • \n
  • green
  • \n
  • blue
  • \n\n", "template": "

    {{header}}

    \n{{#bug}}\n{{/bug}}\n\n{{#items}}\n {{#first}}\n
  • {{name}}
  • \n {{/first}}\n {{#link}}\n
  • {{name}}
  • \n {{/link}}\n{{/items}}\n\n{{#empty}}\n

    The list is empty.

    \n{{/empty}}\n" }, { "name": "Ted's Abusive Test 1", "data": { "x": 123 }, "template": "{{x}}", "expected": "123" }, { "name": "Ted's Abusive Test 2", "data": { "x": 123, "y": 456 }, "template": "{{x}} {{y}}", "expected": "123 456" }, { "name": "Ted's Abusive Test 3", "data": [ null ], "template": "{{null}}", "expected": "" }, { "name": "Ted's Abusive Test 4", "data": { "x": 123, "y": 456 }, "template": "{{}}", "expected": "{{}}" }, { "name": "Ted's Abusive Test 5", "data": { "boolean": true}, "template": "{{#boolean}}IT IS TRUE{{/boolean}}", "expected": "IT IS TRUE" }, { "name": "Ted's Abusive Test 6", "data": { "boolean": false}, "template": "{{^boolean}}IT IS FALSE{{/boolean}}", "expected": "IT IS FALSE" }, { "name": "Ted's Abusive Test 7", "data": { "list": [ { "k": 789, "v": 0 }, { "k": null, "v": true }, { "k": -1, "v": -2 } ] }, "template": "{{#list}}{{k}}={{v}}, {{/list}}", "expected": "789=0, =true, -1=-2, " }, ] } cfengine-3.6.2/tests/unit/data/rval_function_forgot_colon.cf0000664000175100017510000000013512243421446024006 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "env" string => getenv("PATH" "20"); } cfengine-3.6.2/tests/unit/data/bundle_body_promiser_statement_missing_assign.cf0000664000175100017510000000014212243421446027750 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "foo" string > "bar", comment => "test"; } cfengine-3.6.2/tests/unit/data/csv_file.csv0000644000175100017510000000011112316547775020367 0ustar00a10038a1003800000000000000field_1, field_2 field_1, "value1 value2 value3" field_1, "field,2" cfengine-3.6.2/tests/unit/data/bundle_body_forget_cb_bundle.cf0000664000175100017510000000020612243421446024213 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "bas" string => "van der vlies", comment => "lastname"; bundle agent bar { } cfengine-3.6.2/tests/unit/data/methods_invalid_arity.cf0000664000175100017510000000024212243421446022743 0ustar00a10038a1003800000000000000bundle agent foo(one, two) { reports: cfengine3:: "$(one), $(two)"; } bundle agent bar { methods: "any" usebundle => foo("snookie"); } cfengine-3.6.2/tests/unit/data/bundle_args_invalid_type.cf0000664000175100017510000000003512236160673023422 0ustar00a10038a1003800000000000000bundle agent foo(a, "b") { } cfengine-3.6.2/tests/unit/data/body_executor_control_empty.cf0000644000175100017510000000000112316547775024221 0ustar00a10038a1003800000000000000 cfengine-3.6.2/tests/unit/data/bundle_invalid_promise_type.cf0000664000175100017510000000007012243421446024137 0ustar00a10038a1003800000000000000bundle agent foo { invalid: "var" string => "test"; } cfengine-3.6.2/tests/unit/data/bundle_body_promisee_no_colon_allowed.cf0000664000175100017510000000016312243421446026152 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "foo" -> "bar", handle => "foo" comment => "test"; } cfengine-3.6.2/tests/unit/data/mustache_comments.json0000664000175100017510000000636712243421446022477 0ustar00a10038a1003800000000000000{ "__ATTN__": "Do not edit this file; changes belong in the appropriate YAML file.", "overview": "Comment tags represent content that should never appear in the resulting\noutput.\n\nThe tag's content may contain any substring (including newlines) EXCEPT the\nclosing delimiter.\n\nComment tags SHOULD be treated as standalone when appropriate.\n", "tests": [ { "name": "Inline", "data": {}, "expected": "1234567890", "template": "12345{{! Comment Block! }}67890", "desc": "Comment blocks should be removed from the template." }, { "name": "Multiline", "data": {}, "expected": "1234567890\n", "template": "12345{{!\n This is a\n multi-line comment...\n}}67890\n", "desc": "Multiline comments should be permitted." }, { "name": "Standalone", "data": {}, "expected": "Begin.\nEnd.\n", "template": "Begin.\n{{! Comment Block! }}\nEnd.\n", "desc": "All standalone comment lines should be removed." }, { "name": "Indented Standalone", "data": {}, "expected": "Begin.\nEnd.\n", "template": "Begin.\n {{! Indented Comment Block! }}\nEnd.\n", "desc": "All standalone comment lines should be removed." }, { "name": "Standalone Line Endings", "data": {}, "expected": "|\r\n|", "template": "|\r\n{{! Standalone Comment }}\r\n|", "desc": "\"\\r\\n\" should be considered a newline for standalone tags." }, { "name": "Standalone Without Previous Line", "data": {}, "expected": "!", "template": " {{! I'm Still Standalone }}\n!", "desc": "Standalone tags should not require a newline to precede them." }, { "name": "Standalone Without Newline", "data": {}, "expected": "!\n", "template": "!\n {{! I'm Still Standalone }}", "desc": "Standalone tags should not require a newline to follow them." }, { "name": "Multiline Standalone", "data": {}, "expected": "Begin.\nEnd.\n", "template": "Begin.\n{{!\nSomething's going on here...\n}}\nEnd.\n", "desc": "All standalone comment lines should be removed." }, { "name": "Indented Multiline Standalone", "data": {}, "expected": "Begin.\nEnd.\n", "template": "Begin.\n {{!\n Something's going on here...\n }}\nEnd.\n", "desc": "All standalone comment lines should be removed." }, { "name": "Indented Inline", "data": {}, "expected": " 12 \n", "template": " 12 {{! 34 }}\n", "desc": "Inline comments should not strip whitespace" }, { "name": "Surrounding Whitespace", "data": {}, "expected": "12345 67890", "template": "12345 {{! Comment Block! }} 67890", "desc": "Comment removal should preserve surrounding whitespace." } ] } cfengine-3.6.2/tests/unit/data/promiser_empty_varref.cf0000664000175100017510000000005512243421446023007 0ustar00a10038a1003800000000000000bundle agent foo { reports: "$()"; } cfengine-3.6.2/tests/unit/data/bundle_body_promiser_unknown_constraint_id.cf0000664000175100017510000000014212243421446027266 0ustar00a10038a1003800000000000000bundle agent foo { vars: debian:: "foo" string => "bar", cmment => "test"; } cfengine-3.6.2/tests/unit/data/bundle_invalid_type.cf0000664000175100017510000000002712236160673022407 0ustar00a10038a1003800000000000000bundle invalid foo { } cfengine-3.6.2/tests/unit/data/mustache_delimiters.json0000664000175100017510000000545012243421446023003 0ustar00a10038a1003800000000000000{ "tests": [ { "name": "Pair Behavior", "data": { "text": "Hey!" }, "expected": "(Hey!)", "template": "{{=<% %>=}}(<%text%>)", "desc": "The equals sign (used on both sides) should permit delimiter changes." }, { "name": "Special Characters", "data": { "text": "It worked!" }, "expected": "(It worked!)", "template": "({{=[ ]=}}[text])", "desc": "Characters with special meaning regexen should be valid delimiters." }, { "name": "Sections", "data": { "section": true, "data": "I got interpolated." }, "expected": "[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n", "template": "[\n{{#section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|#section|\n {{data}}\n |data|\n|/section|\n]\n", "desc": "Delimiters set outside sections should persist." }, { "name": "Inverted Sections", "data": { "section": false, "data": "I got interpolated." }, "expected": "[\n I got interpolated.\n |data|\n\n {{data}}\n I got interpolated.\n]\n", "template": "[\n{{^section}}\n {{data}}\n |data|\n{{/section}}\n\n{{= | | =}}\n|^section|\n {{data}}\n |data|\n|/section|\n]\n", "desc": "Delimiters set outside inverted sections should persist." }, { "name": "Surrounding Whitespace", "data": {}, "expected": "| |", "template": "| {{=@ @=}} |", "desc": "Surrounding whitespace should be left untouched." }, { "name": "Outlying Whitespace (Inline)", "data": {}, "expected": " | \n", "template": " | {{=@ @=}}\n", "desc": "Whitespace should be left untouched." }, { "name": "Standalone Tag", "data": {}, "expected": "Begin.\nEnd.\n", "template": "Begin.\n{{=@ @=}}\nEnd.\n", "desc": "Standalone lines should be removed from the template." }, { "name": "Indented Standalone Tag", "data": {}, "expected": "Begin.\nEnd.\n", "template": "Begin.\n {{=@ @=}}\nEnd.\n", "desc": "Indented standalone lines should be removed from the template." }, { "name": "Pair with Padding", "data": {}, "expected": "||", "template": "|{{= @ @ =}}|", "desc": "Superfluous in-tag whitespace should be ignored." } ] } cfengine-3.6.2/tests/unit/data/body_edit_xml_common_constraints.cf0000664000175100017510000000012112243421446025177 0ustar00a10038a1003800000000000000bundle edit_xml test { build_xpath: "foo" select_xpath => "abc"; } cfengine-3.6.2/tests/unit/data/constraint_lval_invalid.cf0000664000175100017510000000020112243421446023265 0ustar00a10038a1003800000000000000bundle agent test { files: "$(G.testdir)/shouldnotexist" create => "true", nonexistant_attribute => "abc"; } cfengine-3.6.2/tests/unit/data/bundle_args_forgot_cp.cf0000664000175100017510000000004312243421446022710 0ustar00a10038a1003800000000000000bundle agent foo(a { } cfengine-3.6.2/tests/unit/data/body_invalid_type.cf0000664000175100017510000000005612243421446022071 0ustar00a10038a1003800000000000000body invalid foo { ifelapsed => "60"; } cfengine-3.6.2/tests/unit/data/no_bundle_or_body_keyword.cf0000664000175100017510000000011312243421446023605 0ustar00a10038a1003800000000000000bunndle agent foo { report: any:: "Hello World"; } cfengine-3.6.2/tests/unit/data/rval_wrong_input_type.cf0000664000175100017510000000013412243421446023022 0ustar00a10038a1003800000000000000bundle agent my_commands { vars: any:: "lastname" string => 'vandervlies ; } cfengine-3.6.2/tests/unit/data/bundle_redefinition.cf0000664000175100017510000000021312243421446022370 0ustar00a10038a1003800000000000000bundle agent foo { reports: cfengine3:: "hello world"; } bundle agent foo { reports: cfengine3:: "other stuff"; } cfengine-3.6.2/tests/unit/data/body_executor_control_full.cf0000644000175100017510000000062412316547775024040 0ustar00a10038a1003800000000000000body executor control { splaytime => "1"; mailto => "cfengine_mail@example.org"; mailfrom => "cfengine@example.org"; mailsubject => "Test [localhost/127.0.0.1]"; smtpserver => "localhost"; mailmaxlines => "50"; schedule => { "Min00_05", "Min05_10" }; executorfacility => "LOG_LOCAL6"; agent_expireafter => "120"; exec_command => "/bin/echo"; } cfengine-3.6.2/tests/unit/data/constraint_ifvarclass_invalid.cf0000664000175100017510000000010712243421446024471 0ustar00a10038a1003800000000000000bundle agent foo { reports: "hello" ifvarclass => "*"; } cfengine-3.6.2/tests/unit/data/body_body_forget_cb_bundle.cf0000664000175100017510000000014012243421446023674 0ustar00a10038a1003800000000000000body classes repaired(x) { promise_repaired => { "$(x)_repaired" }; bundle agent foo { } cfengine-3.6.2/tests/unit/data/bundle_body_promiser_statement_contains_colon.cf0000664000175100017510000000014412243421446027745 0ustar00a10038a1003800000000000000bundle agent foo { reports: "This is a test", comment => "will report an error"; } cfengine-3.6.2/tests/unit/data/promise_duplicate_handle.cf0000664000175100017510000000020312243421446023402 0ustar00a10038a1003800000000000000bundle agent foo { reports: cfengine3:: "hello world" handle => "stuff"; "quux" handle => "stuff"; } cfengine-3.6.2/tests/unit/data/benchmark.cf0000664000175100017510000000104712243421446020320 0ustar00a10038a1003800000000000000# This file is intended to have as much feature variation as possible, # while still being correct. body common control { bundlesequence => { "main" }; } bundle agent main { reports: cfengine:: "Hello, CFEngine" friend_pattern => hash("abc", "md5"); any:: "Hello, world" friend_pattern => hash("abc", "md5"); files: "/tmp/stuff" -> { "stakeholder" } create => "true", perms => myperms; processes: "/bin/stuff" -> { "stakeholder" }; } body perms myperms { mode => "555"; } cfengine-3.6.2/tests/unit/data/body_executor_control_agent_expireafter_only.cf0000664000175100017510000000007412243421446027615 0ustar00a10038a1003800000000000000body executor control { agent_expireafter => "121"; } cfengine-3.6.2/tests/unit/generic_agent_test.c0000664000175100017510000000556512400110676021144 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include #include /* xsnprintf */ void test_load_masterfiles(void) { EvalContext *ctx = EvalContextNew(); DiscoverVersion(ctx); GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON); GenericAgentConfigSetInputFile(config, NULL, ABS_TOP_SRCDIR "/masterfiles/promises.cf"); Policy *masterfiles = LoadPolicy(ctx, config); assert_true(masterfiles); PolicyDestroy(masterfiles); GenericAgentFinalize(ctx, config); } void test_resolve_absolute_input_path(void) { assert_string_equal("/abs/aux.cf", GenericAgentResolveInputPath(NULL, "/abs/aux.cf")); } void test_resolve_non_anchored_base_path(void) { static char inputdir[CF_BUFSIZE] = ""; /* * Can not use GetInputDir() because that will return the configured $(sys.inputdir) as * the environment variable CFENGINE_TEST_OVERRIDE_WORKDIR is not set. */ xsnprintf(inputdir, CF_BUFSIZE, "%s%cinputs", CFWORKDIR, FILE_SEPARATOR); GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON); GenericAgentConfigSetInputFile(config, inputdir, "promises.cf"); assert_string_equal("/workdir/inputs", config->input_dir); assert_string_equal("/workdir/inputs/promises.cf", config->input_file); assert_string_equal("/workdir/inputs/aux.cf", GenericAgentResolveInputPath(config, "aux.cf")); assert_string_equal("/workdir/inputs/rel/aux.cf", GenericAgentResolveInputPath(config, "rel/aux.cf")); assert_string_equal("/workdir/inputs/./aux.cf", GenericAgentResolveInputPath(config, "./aux.cf")); assert_string_equal("/workdir/inputs/./rel/aux.cf", GenericAgentResolveInputPath(config, "./rel/aux.cf")); } void test_resolve_relative_base_path(void) { GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON); GenericAgentConfigSetInputFile(config, CFWORKDIR, "./inputs/promises.cf"); assert_string_equal("./inputs/aux.cf", GenericAgentResolveInputPath(config, "aux.cf")); assert_string_equal("./inputs/rel/aux.cf", GenericAgentResolveInputPath(config, "rel/aux.cf")); assert_string_equal("./inputs/./aux.cf", GenericAgentResolveInputPath(config, "./aux.cf")); assert_string_equal("./inputs/./rel/aux.cf", GenericAgentResolveInputPath(config, "./rel/aux.cf")); } int main() { strcpy(CFWORKDIR, "/workdir"); PRINT_TEST_BANNER(); const UnitTest tests[] = { // disabled masterfiles load test for now /* unit_test(test_load_masterfiles),*/ unit_test(test_resolve_absolute_input_path), unit_test(test_resolve_non_anchored_base_path), unit_test(test_resolve_relative_base_path), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/hashes_test.c0000664000175100017510000000346412243421446017626 0ustar00a10038a1003800000000000000#include #include #include #include char *MakeTempFileWithContent(const char *content) { char *path = tempnam(NULL, "cfengine_test"); FILE *fp = fopen(path, "w"); assert_true(fp); assert_true(fputs(content, fp) >= 0); assert_int_equal(0, fclose(fp)); return xstrdup(path); } static void test_file_checksum(void) { { char *file1 = MakeTempFileWithContent("snookie"); char *file2 = MakeTempFileWithContent("jwow"); unsigned char digest1[EVP_MAX_MD_SIZE + 1] = { 0 }; int len1 = FileChecksum(file1, digest1); unlink(file1); free(file1); unsigned char digest2[EVP_MAX_MD_SIZE + 1] = { 0 }; FileChecksum(file2, digest2); unlink(file2); free(file2); bool equal = true; for (int i = 0; i < len1; i++) { if (digest1[i] != digest2[i]) { equal = false; } } assert_false(equal); } { char *file1 = MakeTempFileWithContent("snookie"); char *file2 = MakeTempFileWithContent("snookie"); unsigned char digest1[EVP_MAX_MD_SIZE + 1] = { 0 }; int len1 = FileChecksum(file1, digest1); unlink(file1); free(file1); unsigned char digest2[EVP_MAX_MD_SIZE + 1] = { 0 }; FileChecksum(file2, digest2); unlink(file2); free(file2); bool equal = true; for (int i = 0; i < len1; i++) { if (digest1[i] != digest2[i]) { equal = false; } } assert_true(equal); } } int main() { PRINT_TEST_BANNER(); CryptoInitialize(); const UnitTest tests[] = { unit_test(test_file_checksum) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/tls_generic_test.c0000664000175100017510000011723512411001073020636 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static SSL_CTX *SSLSERVERCONTEXT = NULL; static X509 *SSLSERVERCERT = NULL; static SSL_CTX *SSLCLIENTCONTEXT = NULL; static X509 *SSLCLIENTCERT = NULL; static pid_t CHILD_PID = -1; static int server_public_key_file = -1; static int certificate_file = -1; static char TESTDIR[] = "/tmp/tls_test_XXXXXX"; static char server_name_template_public[128]; static char server_certificate_template_public[128]; /***************** CHILD PROCESS a.k.a. server ******************************/ static int always_true(X509_STORE_CTX *store_ctx ARG_UNUSED, void *arg ARG_UNUSED) { return 1; } /* Child process is the server-side in this test. */ static bool init_test_server() { /* * This is twisted. We can generate the required keys by calling RSA_generate_key, * however we cannot put the private part and the public part in the two containers. * For that we need to save each part to a file and then load each part from * the respective file. */ int ret; RSA *key = RSA_new(); BIGNUM *bignum = BN_new(); BN_set_word(bignum, 17); ret = RSA_generate_key_ex(key, 1024, bignum, NULL); if (!ret) { return false; } char name_template_private[128]; ret = snprintf(name_template_private, sizeof(name_template_private), "%s/%s", TESTDIR, "name_template_private.XXXXXX"); assert(ret > 0 && ret < sizeof(name_template_private)); int private_key_file = 0; FILE *private_key_stream = NULL; private_key_file = mkstemp(name_template_private); if (private_key_file < 0) { return false; } private_key_stream = fdopen(private_key_file, "w+"); if (!private_key_stream) { return false; } ret = PEM_write_RSAPrivateKey(private_key_stream, key, NULL, NULL, 0, 0, NULL); if (ret == 0) { return false; } fseek(private_key_stream, 0L, SEEK_SET); PRIVKEY = PEM_read_RSAPrivateKey(private_key_stream, (RSA **)NULL, NULL, NULL); if (!PRIVKEY) { return false; } fclose(private_key_stream); FILE *public_key_stream = fdopen(server_public_key_file, "w+"); if (!public_key_stream) { return false; } ret = PEM_write_RSAPublicKey(public_key_stream, key); if (ret == 0) { return false; } fflush(public_key_stream); fseek(public_key_stream, 0L, SEEK_SET); PUBKEY = PEM_read_RSAPublicKey(public_key_stream, (RSA **)NULL, NULL, NULL); if (!PUBKEY) { return false; } RSA_free(key); assert_true(SSLSERVERCONTEXT == NULL); SSLSERVERCONTEXT = SSL_CTX_new(SSLv23_server_method()); if (SSLSERVERCONTEXT == NULL) { Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s", TLSErrorString(ERR_get_error())); goto err1; } TLSSetDefaultOptions(SSLSERVERCONTEXT); /* Override one of the default options: always accept peer's certificate, * this is a dummy server. */ SSL_CTX_set_cert_verify_callback(SSLSERVERCONTEXT, always_true, NULL); /* * Create cert into memory and load it into SSL context. */ if (PRIVKEY == NULL || PUBKEY == NULL) { Log(LOG_LEVEL_ERR, "No public/private key pair is loaded, create one with cf-key"); goto err2; } assert_true(SSLSERVERCERT == NULL); /* Generate self-signed cert valid from now to 50 years later. */ { X509 *x509 = X509_new(); X509_gmtime_adj(X509_get_notBefore(x509), 0); X509_time_adj(X509_get_notAfter(x509), 60*60*24*365*50, NULL); EVP_PKEY *pkey = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pkey, PRIVKEY); X509_NAME *name = X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const char *) "", -1, -1, 0); X509_set_issuer_name(x509, name); X509_set_pubkey(x509, pkey); const EVP_MD *md = EVP_get_digestbyname("sha384"); if (md == NULL) { Log(LOG_LEVEL_ERR, "Uknown digest algorithm %s", "sha384"); return false; } ret = X509_sign(x509, pkey, md); EVP_PKEY_free(pkey); SSLSERVERCERT = x509; if (ret <= 0) { Log(LOG_LEVEL_ERR, "Couldn't sign the public key for the TLS handshake: %s", TLSErrorString(ERR_get_error())); goto err3; } FILE *certificate_stream = fdopen(certificate_file, "w+"); if (!certificate_stream) { return false; } PEM_write_X509(certificate_stream, x509); fflush(certificate_stream); } SSL_CTX_use_certificate(SSLSERVERCONTEXT, SSLSERVERCERT); ret = SSL_CTX_use_RSAPrivateKey(SSLSERVERCONTEXT, PRIVKEY); if (ret != 1) { Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s", TLSErrorString(ERR_get_error())); goto err3; } /* Verify cert consistency. */ ret = SSL_CTX_check_private_key(SSLSERVERCONTEXT); if (ret != 1) { Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s", TLSErrorString(ERR_get_error())); goto err3; } return true; err3: X509_free(SSLSERVERCERT); SSLSERVERCERT = NULL; err2: SSL_CTX_free(SSLSERVERCONTEXT); SSLSERVERCONTEXT = NULL; err1: return false; } static void child_mainloop(int channel) { int message = 0; int result = 0; int local_socket = 0; int remote_socket = 0; struct sockaddr_in my_addr, peer_addr; socklen_t peer_addr_size = 0; memset(&my_addr, 0, sizeof(struct sockaddr_in)); memset(&peer_addr, 0, sizeof(struct sockaddr_in)); if (!init_test_server()) { message = -1; result = write(channel, &message, sizeof(int)); exit(EXIT_FAILURE); } /* Create a unix socket. */ local_socket = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = INADDR_ANY; my_addr.sin_port = htons(8035); /* Avoid spurious failures when rerunning the test due to socket not yet * being released. */ int opt = 1; setsockopt(local_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); /* * Bind it */ result = bind(local_socket, (struct sockaddr *)&my_addr, sizeof(struct sockaddr_in)); if (result < 0) { message = -1; result = write(channel, &message, sizeof(int)); exit(EXIT_FAILURE); } /* * Start listening for connections */ result = listen(local_socket, 5); if (result < 0) { message = -1; result = write(channel, &message, sizeof(int)); exit(EXIT_FAILURE); } /* * Signal the parent that we are ok. */ result = write(channel, &message, sizeof(int)); /* * If this did not work, then we abort. */ if (result < 0) { exit(EXIT_FAILURE); } /* * Send the name of the public key file. */ result = write(channel, server_name_template_public, strlen(server_name_template_public)); if (result < 0) { exit(EXIT_FAILURE); } /* * Send the name of the certificate file. */ result = write(channel, server_certificate_template_public, strlen(server_certificate_template_public)); if (result < 0) { exit(EXIT_FAILURE); } /* * Now wait until somebody calls. */ peer_addr_size = sizeof(struct sockaddr_in); while (true) { remote_socket = accept(local_socket, (struct sockaddr *)&peer_addr, &peer_addr_size); if (remote_socket < 0) { Log (LOG_LEVEL_CRIT, "Could not accept connection"); exit(EXIT_FAILURE); } /* * We are not testing the server, we are testing the functions to send and receive data * over TLS. We do not need a full fletched server for that, we just need to send and * receive data and try the error conditions. */ SSL *ssl = SSL_new(SSLSERVERCONTEXT); if (!ssl) { Log(LOG_LEVEL_CRIT, "Could not create SSL structure on the server side"); SSL_free(ssl); close (remote_socket); remote_socket = -1; exit(EXIT_FAILURE); } SSL_set_fd(ssl, remote_socket); result = SSL_accept(ssl); if (result < 0) { Log(LOG_LEVEL_CRIT, "Could not accept a TLS connection"); close (remote_socket); remote_socket = -1; exit(EXIT_FAILURE); } /* * Our mission is pretty simple, receive data and send it back. */ int received = 0; int sent = 0; char buffer[4096]; do { received = SSL_read(ssl, buffer, 4096); if (received < 0) { Log(LOG_LEVEL_CRIT, "Failure while receiving data over TLS"); exit(EXIT_FAILURE); } sent = SSL_write(ssl, buffer, received); if (sent < 0) { Log(LOG_LEVEL_CRIT, "Failure while sending data over TLS"); exit(EXIT_FAILURE); } } while (received > 0); /* * Mission completed, start again. */ SSL_shutdown(ssl); SSL_free(ssl); remote_socket = -1; } ServerTLSDeInitialize(); exit(EXIT_SUCCESS); } static bool start_child_process() { int result = 0; int channel[2]; result = pipe(channel); if (result < 0) { return false; } CHILD_PID = fork(); if (CHILD_PID < 0) { return false; } else if (CHILD_PID == 0) /* CHILD a.k.a server */ { close (channel[0]); child_mainloop(channel[1]); } else /* PARENT a.k.a client */ { close (channel[1]); int message = 0; result = read(channel[0], &message, sizeof(int)); if ((result < 0) || (message < 0)) { close (channel[0]); if (result < 0) { perror("Failed to read() from child"); } if (message < 0) { Log(LOG_LEVEL_ERR, "Child responded with -1!"); } /* * Wait for child process */ wait(NULL); CHILD_PID = -1; return false; } /* * Get the name of the public key file */ result = read(channel[0], server_name_template_public, strlen(server_name_template_public)); if (result < 0) { close (channel[0]); /* * Wait for child process */ wait(NULL); CHILD_PID = -1; return false; } server_name_template_public[result] = '\0'; /* * Get the name of the certificate file */ result = read(channel[0], server_certificate_template_public, strlen(server_certificate_template_public)); if (result < 0) { close (channel[0]); /* * Wait for child process */ wait(NULL); CHILD_PID = -1; return false; } server_certificate_template_public[result] = '\0'; } return true; } /************* END CHILD PROCESS ********************************************/ /* Parent process is the client-side in this test. */ static bool init_test_client() { /* * This is twisted. We can generate the required keys by calling RSA_generate_key, * however we cannot put the private part and the public part in the two containers. * For that we need to save each part to a file and then load each part from * the respective file. */ int ret; RSA *key = RSA_new(); BIGNUM *bignum = BN_new(); BN_set_word(bignum, 17); ret = RSA_generate_key_ex(key, 1024, bignum, NULL); if (!ret) { return false; } char name_template_private[128]; char name_template_public[128]; ret = snprintf(name_template_private, sizeof(name_template_private), "%s/%s", TESTDIR, "name_template_private.XXXXXX"); assert(ret > 0 && ret < sizeof(name_template_private)); int private_key_file = mkstemp(name_template_private); if (private_key_file < 0) { return false; } FILE *private_key_stream = fdopen(private_key_file, "w+"); if (!private_key_stream) { return false; } ret = PEM_write_RSAPrivateKey(private_key_stream, key, NULL, NULL, 0, 0, NULL); if (ret == 0) { return false; } fseek(private_key_stream, 0L, SEEK_SET); PRIVKEY = PEM_read_RSAPrivateKey(private_key_stream, (RSA **)NULL, NULL, NULL); if (!PRIVKEY) { return false; } fclose(private_key_stream); ret = snprintf(name_template_public, sizeof(name_template_public), "%s/%s", TESTDIR, "name_template_public.XXXXXX"); assert(ret > 0 && ret < sizeof(name_template_public)); int public_key_file = mkstemp(name_template_public); if (public_key_file < 0) { perror("mkstemp"); return false; } FILE *public_key_stream = fdopen(public_key_file, "w+"); if (!public_key_stream) { return false; } ret = PEM_write_RSAPublicKey(public_key_stream, key); if (ret == 0) { return false; } fseek(public_key_stream, 0L, SEEK_SET); PUBKEY = PEM_read_RSAPublicKey(public_key_stream, (RSA **)NULL, NULL, NULL); if (!PUBKEY) { return false; } fclose(public_key_stream); RSA_free(key); SSLCLIENTCONTEXT = SSL_CTX_new(SSLv23_client_method()); if (SSLCLIENTCONTEXT == NULL) { Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s", TLSErrorString(ERR_get_error())); goto err1; } TLSSetDefaultOptions(SSLCLIENTCONTEXT); /* * Create cert into memory and load it into SSL context. */ if (PRIVKEY == NULL || PUBKEY == NULL) { return false; } /* Generate self-signed cert valid from now to 50 years later. */ { X509 *x509 = X509_new(); X509_gmtime_adj(X509_get_notBefore(x509), 0); X509_time_adj(X509_get_notAfter(x509), 60*60*24*365*50, NULL); EVP_PKEY *pkey = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pkey, PRIVKEY); X509_NAME *name = X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const char *) "", -1, -1, 0); X509_set_issuer_name(x509, name); X509_set_pubkey(x509, pkey); const EVP_MD *md = EVP_get_digestbyname("sha384"); if (md == NULL) { return false; } ret = X509_sign(x509, pkey, md); EVP_PKEY_free(pkey); SSLCLIENTCERT = x509; if (ret <= 0) { Log(LOG_LEVEL_ERR, "Couldn't sign the public key for the TLS handshake: %s", TLSErrorString(ERR_get_error())); goto err3; } } SSL_CTX_use_certificate(SSLCLIENTCONTEXT, SSLCLIENTCERT); ret = SSL_CTX_use_RSAPrivateKey(SSLCLIENTCONTEXT, PRIVKEY); if (ret != 1) { Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s", TLSErrorString(ERR_get_error())); goto err3; } /* Verify cert consistency. */ ret = SSL_CTX_check_private_key(SSLCLIENTCONTEXT); if (ret != 1) { Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s", TLSErrorString(ERR_get_error())); goto err3; } return true; err3: X509_free(SSLCLIENTCERT); SSLCLIENTCERT = NULL; SSL_CTX_free(SSLCLIENTCONTEXT); SSLCLIENTCONTEXT = NULL; err1: return false; } static bool create_temps() { int ret; char *retp = mkdtemp(TESTDIR); if (retp == NULL) { perror("mkdtemp"); return false; } ret = snprintf(server_name_template_public, sizeof(server_name_template_public), "%s/%s", TESTDIR, "server_name_template_public.XXXXXX"); assert(ret > 0 && ret < sizeof(server_name_template_public)); server_public_key_file = mkstemp(server_name_template_public); if (server_public_key_file < 0) { perror("mkstemp"); return false; } ret = snprintf(server_certificate_template_public, sizeof(server_certificate_template_public), "%s/%s", TESTDIR, "server_certificate_template_public.XXXXXX"); assert(ret > 0 && ret < sizeof(server_certificate_template_public)); certificate_file = mkstemp(server_certificate_template_public); if (certificate_file < 0) { perror("mkstemp"); return false; } return true; } static bool tests_setup(void) { CryptoInitialize(); if (!TLSGenericInitialize()) { return false; } if (!create_temps()) { return false; } /* First we start a new process to have a server for our tests. */ if (!start_child_process()) { return false; } /* If the initialization went without problems, then at this point there * is a second process waiting for connections. */ if (!init_test_client()) { return false; } return true; } static void tests_teardown(void) { TLSDeInitialize(); if (server_public_key_file != -1) { close(server_public_key_file); } if (certificate_file != -1) { close(server_public_key_file); } if (CHILD_PID > 0) /* kill child */ { kill(CHILD_PID, SIGTERM); } /* Delete temporary folder and files */ DIR *folder = opendir(TESTDIR); if (folder) { struct dirent *entry = NULL; for (entry = readdir(folder); entry; entry = readdir(folder)) { if (entry->d_name[0] == '.') { /* Skip . and .. */ continue; } char *name; xasprintf(&name, "%s/%s", TESTDIR, entry->d_name); unlink(name); free (name); } closedir(folder); rmdir(TESTDIR); } } /* * Functions to mock * int SSL_write(SSL *s, const void *buf, int num) * int SSL_read(SSL *s, void *buf, int num) * int SSL_get_shutdown(SSL *s) * X509 *SSL_get_peer_certificate(const SSL *ssl) * EVP_PKEY *X509_get_pubkey(X509_PUBKEY *key) */ static bool original_function_SSL_write = true; static bool original_function_SSL_read = true; static bool original_function_SSL_get_shutdown = true; static bool original_function_SSL_get_peer_certificate = true; static bool original_function_X509_get_pubkey = true; static bool original_function_EVP_PKEY_type = true; static bool original_function_HavePublicKey = true; static bool original_function_EVP_PKEY_cmp = true; static int SSL_write_result = -1; static int SSL_read_result = -1; static char *SSL_read_buffer = NULL; static int SSL_get_shutdown_result = -1; static X509 *SSL_get_peer_certificate_result = NULL; static EVP_PKEY *X509_get_pubkey_result = NULL; static int EVP_PKEY_type_result = -1; static RSA *HavePublicKey_result = NULL; static int EVP_PKEY_cmp_result = -1; #define RESET_STATUS \ original_function_SSL_write = true; \ original_function_SSL_read = true; \ original_function_SSL_get_shutdown = true; \ original_function_SSL_get_peer_certificate = true; \ original_function_X509_get_pubkey = true; \ original_function_EVP_PKEY_type = true; \ original_function_HavePublicKey = true; \ original_function_EVP_PKEY_cmp = true; \ SSL_write_result = -1; \ SSL_read_result = -1; \ SSL_get_shutdown_result = -1; \ X509_get_pubkey_result = NULL; \ EVP_PKEY_type_result = -1; \ HavePublicKey_result = NULL; \ EVP_PKEY_cmp_result = -1; /* * These macros are used to control each function separatedly. */ #define USE_ORIGINAL(f) \ original_function_ ## f = true #define USE_MOCK(f) \ original_function_ ## f = false #define USING(f) \ original_function_ ## f #define SSL_WRITE_RETURN(x) \ SSL_write_result = x #define SSL_GET_SHUTDOWN_RETURN(x) \ SSL_get_shutdown_result = x #define SSL_READ_RETURN(x) \ SSL_read_result = x #define SSL_READ_USE_BUFFER(x) \ SSL_read_buffer = xstrdup(x) #define SSL_READ_REMOVE_BUFFER \ if (SSL_read_buffer) \ { \ free (SSL_read_buffer); \ SSL_read_buffer = NULL; \ } #define SSL_GET_PEER_CERTIFICATE_RETURN(x) \ SSL_get_peer_certificate_result = x #define X509_GET_PUBKEY_RETURN(x) \ if (x) ((EVP_PKEY *) x)->references++; \ X509_get_pubkey_result = x #define EVP_PKEY_TYPE_RETURN(x) \ EVP_PKEY_type_result = x #define HAVEPUBLICKEY_RETURN(x) \ if (x) ((RSA *) x)->references++; \ HavePublicKey_result = x #define EVP_PKEY_CMP_RETURN(x) \ EVP_PKEY_cmp_result = x /* * We keep a copy of the original functions, so we can simulate * the real behavior if needed. * This is risky since we need to keep these functions up to date * in case OpenSSL decides to change them. */ int original_SSL_write(SSL *s, const void *buf, int num) { if (s->handshake_func == 0) { SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED); return -1; } if (s->shutdown & SSL_SENT_SHUTDOWN) { s->rwstate=SSL_NOTHING; SSLerr(SSL_F_SSL_WRITE,SSL_R_PROTOCOL_IS_SHUTDOWN); return(-1); } return(s->method->ssl_write(s,buf,num)); } int original_SSL_read(SSL *s, void *buf, int num) { if (s->handshake_func == 0) { SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED); return -1; } if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { s->rwstate=SSL_NOTHING; return(0); } return(s->method->ssl_read(s,buf,num)); } int original_SSL_get_shutdown(const SSL *ssl) { return(ssl->shutdown); } X509 *original_SSL_get_peer_certificate(const SSL *ssl) { X509 *r; if ((ssl == NULL) || (ssl->session == NULL)) r=NULL; else r=ssl->session->peer; if (r == NULL) return(r); CRYPTO_add(&r->references,1,CRYPTO_LOCK_X509); return(r); } EVP_PKEY *original_X509_get_pubkey(X509 *x) { if ((x == NULL) || (x->cert_info == NULL)) return(NULL); return(X509_PUBKEY_get(x->cert_info->key)); } int original_EVP_PKEY_type(int type) { switch (type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: return(EVP_PKEY_RSA); case EVP_PKEY_DSA: case EVP_PKEY_DSA1: case EVP_PKEY_DSA2: case EVP_PKEY_DSA3: case EVP_PKEY_DSA4: return(EVP_PKEY_DSA); case EVP_PKEY_DH: return(EVP_PKEY_DH); case EVP_PKEY_EC: return(EVP_PKEY_EC); default: return(NID_undef); } return(NID_undef); } RSA *original_HavePublicKey(const char *username, const char *ipaddress, const char *digest) { char keyname[CF_MAXVARSIZE], newname[CF_BUFSIZE], oldname[CF_BUFSIZE]; struct stat statbuf; static char *passphrase = "public"; unsigned long err; FILE *fp; RSA *newkey = NULL; snprintf(keyname, CF_MAXVARSIZE, "%s-%s", username, digest); snprintf(newname, CF_BUFSIZE, "%s/ppkeys/%s.pub", CFWORKDIR, keyname); MapName(newname); if (stat(newname, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "Did not find new key format '%s'", newname); snprintf(oldname, CF_BUFSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, username, ipaddress); MapName(oldname); Log(LOG_LEVEL_VERBOSE, "Trying old style '%s'", oldname); if (stat(oldname, &statbuf) == -1) { Log(LOG_LEVEL_DEBUG, "Did not have old-style key '%s'", oldname); return NULL; } if (strlen(digest) > 0) { Log(LOG_LEVEL_INFO, "Renaming old key from '%s' to '%s'", oldname, newname); if (rename(oldname, newname) != 0) { Log(LOG_LEVEL_ERR, "Could not rename from old key format '%s' to new '%s'. (rename: %s)", oldname, newname, GetErrorStr()); } } else { /* We don't know the digest (e.g. because we are a client and have no lastseen-map yet), so we're using old file format (root-IP.pub). */ Log(LOG_LEVEL_VERBOSE, "We have no digest yet, using old keyfile name: %s", oldname); snprintf(newname, sizeof(newname), "%s", oldname); } } if ((fp = fopen(newname, "r")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't find a public key '%s'. (fopen: %s)", newname, GetErrorStr()); return NULL; } if ((newkey = PEM_read_RSAPublicKey(fp, NULL, NULL, passphrase)) == NULL) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Error reading public key. (PEM_read_RSAPublicKey: %s)", TLSErrorString(err)); fclose(fp); return NULL; } fclose(fp); if ((BN_num_bits(newkey->e) < 2) || (!BN_is_odd(newkey->e))) { Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd"); RSA_free(newkey); return NULL; } return newkey; } int original_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { if (a->type != b->type) return -1; if (EVP_PKEY_cmp_parameters(a, b) == 0) return 0; switch (a->type) { case EVP_PKEY_RSA: if (BN_cmp(b->pkey.rsa->n,a->pkey.rsa->n) != 0 || BN_cmp(b->pkey.rsa->e,a->pkey.rsa->e) != 0) return 0; break; default: return -2; } return 1; } /* * Mock'ed functions */ int SSL_write(SSL *ssl, const void *buf, int num) { if (USING(SSL_write)) return original_SSL_write(ssl, buf, num); return (SSL_write_result > num) ? num : SSL_write_result; } int SSL_read(SSL *ssl, void *buf, int num) { if (USING(SSL_read)) return original_SSL_read(ssl, buf, num); if (SSL_read_buffer) { char *temp = buf; int i = 0; for (i = 0; SSL_read_buffer[i] != '\0'; ++i) temp[i] = SSL_read_buffer[i]; return i; } return (SSL_read_result > num) ? num : SSL_read_result; } int SSL_get_shutdown(const SSL *ssl) { if (USING(SSL_get_shutdown)) return original_SSL_get_shutdown(ssl); return SSL_get_shutdown_result; } X509 *SSL_get_peer_certificate(const SSL *ssl) { if (USING(SSL_get_peer_certificate)) { return original_SSL_get_peer_certificate(ssl); } return SSL_get_peer_certificate_result; } EVP_PKEY *X509_get_pubkey(X509 *cert) { if (USING(X509_get_pubkey)) { return original_X509_get_pubkey(cert); } return X509_get_pubkey_result; } int EVP_PKEY_type(int type) { if (USING(EVP_PKEY_type)) { return original_EVP_PKEY_type(type); } return EVP_PKEY_type_result; } RSA *HavePublicKey(const char *username, const char *ipaddress, const char *digest) { if (USING(HavePublicKey)) { return original_HavePublicKey(username, ipaddress, digest); } return HavePublicKey_result; } int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) { if (USING(EVP_PKEY_cmp)) { return original_EVP_PKEY_cmp(a, b); } return EVP_PKEY_cmp_result; } /* * Functions to test: * int TLSVerifyCallback(X509_STORE_CTX *ctx ARG_UNUSED, void *arg ARG_UNUSED) * int TLSVerifyPeer(ConnectionInfo *conn_info, const char *remoteip, const char *username); * int TLSSend(SSL *ssl, const char *buffer, int length); * int TLSRecv(SSL *ssl, char *buffer, int length); * int TLSRecvLines(SSL *ssl, char *buf, size_t buf_size); */ /*static void test_TLSVerifyCallback(void) { RESET_STATUS; // TODO test that TLSVerifyCallback returns 0 in case certificate changes // during renegotiation. Must initialise a connection, and then trigger // renegotiation with and without the certificate changing. RESET_STATUS; } */ #define REREAD_CERTIFICATE(f, c) \ rewind(f); \ c = PEM_read_X509(f, (X509 **)NULL, NULL, NULL) #define REREAD_PUBLIC_KEY(f, k, e) \ rewind(f); \ k = PEM_read_RSAPublicKey(f, (RSA **)NULL, NULL, NULL); \ e = EVP_PKEY_new(); \ EVP_PKEY_assign_RSA(e, k) static void test_TLSVerifyPeer(void) { #ifdef __sun return; //redmine 6398 #endif RESET_STATUS; SSL *ssl = NULL; ConnectionInfo *conn_info = NULL; /* * Open a socket and establish a tcp connection. */ struct sockaddr_in server_addr; int server = 0; int result = 0; conn_info = ConnectionInfoNew(); memset(&server_addr, 0, sizeof(struct sockaddr_in)); server = socket(AF_INET, SOCK_STREAM, 0); assert_int_not_equal(-1, server); server_addr.sin_family = AF_INET; ConnectionInfoSetSocket(conn_info, server); /* We should not use inet_addr, but it is easier for this particular case. */ server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(8035); /* * Connect */ result = connect(server, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)); assert_int_not_equal(-1, result); /* * Create a SSL instance */ ssl = SSL_new(SSLCLIENTCONTEXT); assert_true(ssl != NULL); SSL_set_fd(ssl, server); /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn_info); /* * Establish the TLS connection over the socket. */ result = SSL_connect(ssl); assert_int_not_equal(-1, result); /* * Fill the remaining fields on ConnectionInfo */ ConnectionInfoSetProtocolVersion(conn_info, CF_PROTOCOL_TLS); ConnectionInfoSetSSL(conn_info, ssl); /* * Fill in the structures we need for testing. */ X509 *certificate = NULL; FILE *certificate_stream = fopen(server_certificate_template_public, "r"); assert_true(certificate_stream != NULL); certificate = PEM_read_X509(certificate_stream, (X509 **)NULL, NULL, NULL); assert_true(certificate != NULL); /* * Start testing */ /* Certificate is mocked to return NULL. */ USE_MOCK(SSL_get_peer_certificate); assert_int_equal(-1, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); /* Certificate is properly returned, but pubkey is mocked to NULL. */ SSL_GET_PEER_CERTIFICATE_RETURN(certificate); USE_MOCK(X509_get_pubkey); X509_GET_PUBKEY_RETURN(NULL); assert_int_equal(-1, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); EVP_PKEY *server_pubkey = NULL; RSA *pubkey = NULL; FILE *stream = fopen(server_name_template_public, "r"); /* * Due to the cleaning up we do after failing, we need to re read the * certificate after very failure. The same is true for the public key. */ REREAD_CERTIFICATE(certificate_stream, certificate); SSL_GET_PEER_CERTIFICATE_RETURN(certificate); REREAD_PUBLIC_KEY(stream, pubkey, server_pubkey); X509_GET_PUBKEY_RETURN(server_pubkey); USE_MOCK(EVP_PKEY_type); EVP_PKEY_TYPE_RETURN(EVP_PKEY_DSA); assert_int_equal(-1, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); EVP_PKEY_free(server_pubkey); EVP_PKEY_TYPE_RETURN(EVP_PKEY_RSA); USE_MOCK(HavePublicKey); HAVEPUBLICKEY_RETURN(NULL); REREAD_CERTIFICATE(certificate_stream, certificate); SSL_GET_PEER_CERTIFICATE_RETURN(certificate); REREAD_PUBLIC_KEY(stream, pubkey, server_pubkey); X509_GET_PUBKEY_RETURN(server_pubkey); assert_int_equal(0, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); /* TODO: Since TLSVerifyPeer() returned 0 or 1 it has put a valid key in * conn_info, so we have to free it. */ // RSA_free(KeyRSA(ConnectionInfoKey(conn_info))); EVP_PKEY_free(server_pubkey); USE_MOCK(EVP_PKEY_cmp); EVP_PKEY_CMP_RETURN(-1); REREAD_CERTIFICATE(certificate_stream, certificate); SSL_GET_PEER_CERTIFICATE_RETURN(certificate); REREAD_PUBLIC_KEY(stream, pubkey, server_pubkey); X509_GET_PUBKEY_RETURN(server_pubkey); HAVEPUBLICKEY_RETURN(pubkey); assert_int_equal(0, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); /* TODO: Since TLSVerifyPeer() returned 0 or 1 it has put a valid key in * conn_info, so we have to free it. */ // RSA_free(KeyRSA(ConnectionInfoKey(conn_info))); EVP_PKEY_free(server_pubkey); EVP_PKEY_CMP_RETURN(0); REREAD_CERTIFICATE(certificate_stream, certificate); SSL_GET_PEER_CERTIFICATE_RETURN(certificate); REREAD_PUBLIC_KEY(stream, pubkey, server_pubkey); X509_GET_PUBKEY_RETURN(server_pubkey); HAVEPUBLICKEY_RETURN(pubkey); assert_int_equal(0, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); /* TODO: Since TLSVerifyPeer() returned 0 or 1 it has put a valid key in * conn_info, so we have to free it. */ // RSA_free(KeyRSA(ConnectionInfoKey(conn_info))); EVP_PKEY_free(server_pubkey); EVP_PKEY_CMP_RETURN(-2); REREAD_CERTIFICATE(certificate_stream, certificate); SSL_GET_PEER_CERTIFICATE_RETURN(certificate); REREAD_PUBLIC_KEY(stream, pubkey, server_pubkey); X509_GET_PUBKEY_RETURN(server_pubkey); HAVEPUBLICKEY_RETURN(pubkey); assert_int_equal(-1, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); EVP_PKEY_free(server_pubkey); EVP_PKEY_CMP_RETURN(1); REREAD_CERTIFICATE(certificate_stream, certificate); SSL_GET_PEER_CERTIFICATE_RETURN(certificate); REREAD_PUBLIC_KEY(stream, pubkey, server_pubkey); X509_GET_PUBKEY_RETURN(server_pubkey); HAVEPUBLICKEY_RETURN(pubkey); assert_int_equal(1, TLSVerifyPeer(conn_info, "127.0.0.1", "root")); /* TODO: Since TLSVerifyPeer() returned 0 or 1 it has put a valid key in * conn_info, so we have to free it. */ // RSA_free(KeyRSA(ConnectionInfoKey(conn_info))); EVP_PKEY_free(server_pubkey); /* * Shutting down is not as easy as it seems. */ do { result = SSL_shutdown(ssl); assert_int_not_equal(-1, result); } while (result != 1); ConnectionInfoDestroy(&conn_info); RESET_STATUS; } /* * This test checks for the three basic operations: * - TLSSend * - TLSRecv * - TLSRecvLines * It is difficult to test each one separatedly, so we test all at once. * The test consists on establishing a connection to our child process and then * sending and receiving data. We switch between the original functions and the * mock functions. * We do not test SSL_new, SSL_accept and such because those will be covered by either * the client or server tests. */ static void test_TLSBasicIO(void) { #ifdef __sun return; //redmine 6398 #endif RESET_STATUS; SSL *ssl = NULL; char output_buffer[] = "this is a buffer"; int output_buffer_length = strlen(output_buffer); char input_buffer[4096]; int result = 0; /* * Open a socket and establish a tcp connection. */ struct sockaddr_in server_addr; int server = 0; memset(&server_addr, 0, sizeof(struct sockaddr_in)); server = socket(AF_INET, SOCK_STREAM, 0); assert_int_not_equal(-1, server); server_addr.sin_family = AF_INET; /* We should not use inet_addr, but it is easier for this particular case. */ server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); server_addr.sin_port = htons(8035); /* * Connect */ result = connect(server, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in)); assert_int_not_equal(-1, result); /* * Create a SSL instance */ ssl = SSL_new(SSLCLIENTCONTEXT); assert_true(ssl != NULL); SSL_set_fd(ssl, server); /* Pass dummy conn_info inside the ssl struct for TLSVerifyCallback(), not * needed for anything else in here. */ ConnectionInfo *conn_info = ConnectionInfoNew(); SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn_info); /* * Establish the TLS connection over the socket. */ result = SSL_connect(ssl); assert_int_not_equal(-1, result); /* * Start testing. The first obvious thing to test is to send data. */ result = TLSSend(ssl, output_buffer, output_buffer_length); assert_int_equal(result, output_buffer_length); /* * Good we sent data and the data was sent. Let's check what we get back * by using TLSRecv. */ result = TLSRecv(ssl, input_buffer, output_buffer_length); assert_int_equal(output_buffer_length, result); input_buffer[output_buffer_length] = '\0'; assert_string_equal(output_buffer, input_buffer); /* * Brilliant! We transmitted and received data using simple communication. * Let's try the line sending. */ char output_line_buffer[] = "hello\ngoodbye\n"; int output_line_buffer_length = strlen(output_line_buffer); result = TLSSend(ssl, output_line_buffer, output_line_buffer_length); assert_int_equal(result, output_line_buffer_length); result = TLSRecvLines(ssl, input_buffer, sizeof(input_buffer)); /* The reply should be both lines, hello and goodbye. */ assert_int_equal(result, output_line_buffer_length); assert_string_equal(input_buffer, output_line_buffer); /* * Basic check */ USE_MOCK(SSL_write); USE_MOCK(SSL_read); assert_int_equal(-1, TLSSend(ssl, output_buffer, output_buffer_length)); assert_int_equal(-1, TLSRecv(ssl, input_buffer, output_buffer_length)); RESET_STATUS; /* * Start replacing the functions inside to check that the logic works * We start by testing TLSSend, then TLSRead and at last TLSRecvLine. */ USE_MOCK(SSL_write); SSL_WRITE_RETURN(0); assert_int_equal(0, TLSSend(ssl, output_buffer, output_buffer_length)); USE_MOCK(SSL_get_shutdown); SSL_GET_SHUTDOWN_RETURN(1); assert_int_equal(0, TLSSend(ssl, output_buffer, output_buffer_length)); SSL_WRITE_RETURN(-1); assert_int_equal(-1, TLSSend(ssl, output_buffer, output_buffer_length)); USE_MOCK(SSL_read); SSL_READ_RETURN(0); SSL_GET_SHUTDOWN_RETURN(0); assert_int_equal(0, TLSRecv(ssl, input_buffer, output_buffer_length)); SSL_GET_SHUTDOWN_RETURN(1); assert_int_equal(0, TLSRecv(ssl, input_buffer, output_buffer_length)); SSL_READ_RETURN(-1); assert_int_equal(-1, TLSRecv(ssl, input_buffer, output_buffer_length)); USE_ORIGINAL(SSL_write); SSL_READ_RETURN(0); assert_int_equal(-1, TLSRecvLines(ssl, input_buffer, sizeof(input_buffer))); SSL_READ_RETURN(-1); assert_int_equal(-1, TLSRecvLines(ssl, input_buffer, sizeof(input_buffer))); SSL_READ_RETURN(5); assert_int_equal(-1, TLSRecvLines(ssl, input_buffer, 10)); SSL_READ_USE_BUFFER(output_line_buffer); assert_int_equal(output_line_buffer_length, TLSRecvLines(ssl, input_buffer, sizeof(input_buffer))); assert_string_equal(input_buffer, output_line_buffer); result = SSL_shutdown(ssl); if (ssl) { SSL_free(ssl); } ConnectionInfoDestroy(&conn_info); RESET_STATUS; } int main() { PRINT_TEST_BANNER(); if (!tests_setup()) { fprintf(stderr, "Test failed to initialise!\n"); exit(EXIT_FAILURE); } atexit(tests_teardown); const UnitTest tests[] = { /* unit_test(test_TLSVerifyCallback), */ unit_test(test_TLSVerifyPeer), unit_test(test_TLSBasicIO) }; int result = run_tests(tests); return result; } cfengine-3.6.2/tests/unit/parser_test.c0000664000175100017510000001662412400110676017644 0ustar00a10038a1003800000000000000#include #include #include /* xsnprintf */ #include static Policy *TestParsePolicy(const char *filename) { char path[PATH_MAX]; xsnprintf(path, sizeof(path), "%s/%s", TESTDATADIR, filename); return ParserParseFile(AGENT_TYPE_COMMON, path, PARSER_WARNING_ALL, PARSER_WARNING_ALL); } void test_benchmark(void) { Policy *p = TestParsePolicy("benchmark.cf"); assert_true(p); PolicyDestroy(p); } void test_no_bundle_or_body_keyword(void) { assert_false(TestParsePolicy("no_bundle_or_body_keyword.cf")); } void test_bundle_invalid_type(void) { assert_false(TestParsePolicy("bundle_invalid_type.cf")); } void test_body_invalid_type(void) { assert_false(TestParsePolicy("body_invalid_type.cf")); } void test_constraint_ifvarclass_invalid(void) { Policy *p = TestParsePolicy("constraint_ifvarclass_invalid.cf"); assert_false(p); } void test_bundle_args_invalid_type(void) { assert_false(TestParsePolicy("bundle_args_invalid_type.cf")); } void test_bundle_args_forgot_cp(void) { assert_false(TestParsePolicy("bundle_args_forgot_cp.cf")); } void test_bundle_body_forgot_ob(void) { assert_false(TestParsePolicy("bundle_body_forgot_ob.cf")); } void test_bundle_invalid_promise_type(void) { assert_false(TestParsePolicy("bundle_invalid_promise_type.cf")); } void test_bundle_body_wrong_promise_type_token(void) { assert_false(TestParsePolicy("bundle_body_wrong_promise_type_token.cf")); } void test_bundle_body_wrong_statement(void) { assert_false(TestParsePolicy("bundle_body_wrong_statement.cf")); } void test_bundle_body_forgot_semicolon(void) { assert_false(TestParsePolicy("bundle_body_forgot_semicolon.cf")); } void test_bundle_body_promiser_statement_contains_colon(void) { assert_false(TestParsePolicy("bundle_body_promiser_statement_contains_colon.cf")); } void test_bundle_body_promiser_statement_missing_assign(void) { assert_false(TestParsePolicy("bundle_body_promiser_statement_missing_assign.cf")); } void test_bundle_body_promisee_missing_arrow(void) { assert_false(TestParsePolicy("bundle_body_promise_missing_arrow.cf")); } void test_bundle_body_promiser_wrong_constraint_token(void) { assert_false(TestParsePolicy("bundle_body_promiser_wrong_constraint_token.cf")); } void test_bundle_body_promiser_unknown_constraint_id(void) { assert_false(TestParsePolicy("bundle_body_promiser_unknown_constraint_id.cf")); } void test_body_edit_line_common_constraints(void) { assert_true(TestParsePolicy("body_edit_line_common_constraints.cf")); } void test_body_edit_xml_common_constraints(void) { assert_true(TestParsePolicy("body_edit_xml_common_constraints.cf")); } void test_promise_promiser_nonscalar(void) { assert_false(TestParsePolicy("promise_promiser_nonscalar.cf")); } void test_bundle_body_promiser_forgot_colon(void) { assert_false(TestParsePolicy("bundle_body_promiser_forgot_colon.cf")); } void test_bundle_body_promisee_no_colon_allowed(void) { assert_false(TestParsePolicy("bundle_body_promisee_no_colon_allowed.cf")); } void test_bundle_body_forget_cb_eof(void) { assert_false(TestParsePolicy("bundle_body_forget_cb_eof.cf")); } void test_bundle_body_forget_cb_body(void) { assert_false(TestParsePolicy("bundle_body_forget_cb_body.cf")); } void test_bundle_body_forget_cb_bundle(void) { assert_false(TestParsePolicy("bundle_body_forget_cb_bundle.cf")); } void test_body_selection_wrong_token(void) { assert_false(TestParsePolicy("body_selection_wrong_token.cf")); } void test_body_selection_forgot_semicolon(void) { assert_false(TestParsePolicy("body_selection_forgot_semicolon.cf")); } void test_body_selection_unknown_selection_id(void) { assert_false(TestParsePolicy("body_selection_unknown_selection_id.cf")); } void test_body_body_forget_cb_eof(void) { assert_false(TestParsePolicy("body_body_forget_cb_eof.cf")); } void test_body_body_forget_cb_body(void) { assert_false(TestParsePolicy("body_body_forget_cb_body.cf")); } void test_body_body_forget_cb_bundle(void) { assert_false(TestParsePolicy("body_body_forget_cb_bundle.cf")); } void test_rval_list_forgot_colon(void) { assert_false(TestParsePolicy("rval_list_forgot_colon.cf")); } void test_rval_list_wrong_input_type(void) { assert_false(TestParsePolicy("rval_list_wrong_input_type.cf")); } void test_rval_function_forgot_colon(void) { assert_false(TestParsePolicy("rval_function_forgot_colon.cf")); } void test_rval_function_wrong_input_type(void) { assert_false(TestParsePolicy("rval_function_wrong_input_type.cf")); } void test_rval_wrong_input_type(void) { assert_false(TestParsePolicy("rval_wrong_input_type.cf")); } void test_rval_list_forgot_cb_semicolon(void) { assert_false(TestParsePolicy("rval_list_forgot_cb_semicolon.cf")); } void test_rval_list_forgot_cb_colon(void) { assert_false(TestParsePolicy("rval_list_forgot_cb_colon.cf")); } void test_rval_function_forgot_cp_semicolon(void) { assert_false(TestParsePolicy("rval_function_forgot_cp_semicolon.cf")); } void test_rval_function_forgot_cp_colon(void) { assert_false(TestParsePolicy("rval_function_forgot_cp_colon.cf")); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_benchmark), unit_test(test_bundle_invalid_type), unit_test(test_bundle_args_invalid_type), unit_test(test_bundle_args_forgot_cp), unit_test(test_bundle_body_forgot_ob), unit_test(test_bundle_invalid_promise_type), unit_test(test_bundle_body_wrong_promise_type_token), unit_test(test_bundle_body_wrong_statement), unit_test(test_bundle_body_forgot_semicolon), unit_test(test_bundle_body_promiser_statement_contains_colon), unit_test(test_bundle_body_promiser_statement_missing_assign), unit_test(test_bundle_body_promisee_missing_arrow), unit_test(test_bundle_body_promiser_wrong_constraint_token), unit_test(test_bundle_body_promiser_unknown_constraint_id), unit_test(test_bundle_body_promiser_forgot_colon), unit_test(test_bundle_body_promisee_no_colon_allowed), unit_test(test_bundle_body_forget_cb_eof), unit_test(test_bundle_body_forget_cb_body), unit_test(test_bundle_body_forget_cb_bundle), unit_test(test_body_edit_line_common_constraints), unit_test(test_body_edit_xml_common_constraints), unit_test(test_body_invalid_type), unit_test(test_body_selection_wrong_token), unit_test(test_body_selection_forgot_semicolon), unit_test(test_body_selection_unknown_selection_id), unit_test(test_body_body_forget_cb_eof), unit_test(test_body_body_forget_cb_body), unit_test(test_body_body_forget_cb_bundle), unit_test(test_promise_promiser_nonscalar), unit_test(test_constraint_ifvarclass_invalid), unit_test(test_rval_list_forgot_colon), unit_test(test_rval_list_wrong_input_type), unit_test(test_rval_list_forgot_cb_semicolon), unit_test(test_rval_list_forgot_cb_colon), unit_test(test_rval_function_forgot_colon), unit_test(test_rval_function_wrong_input_type), unit_test(test_rval_function_forgot_cp_semicolon), unit_test(test_rval_function_forgot_cp_colon), unit_test(test_rval_wrong_input_type), unit_test(test_no_bundle_or_body_keyword) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/variable_test.c0000644000175100017510000002251512316547775020153 0ustar00a10038a1003800000000000000#include #include #include static bool PutVar(VariableTable *table, char *var_str) { VarRef *ref = VarRefParse(var_str); Rval rval = (Rval) { var_str, RVAL_TYPE_SCALAR }; bool ret = VariableTablePut(table, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL); VarRefDestroy(ref); return ret; } static VariableTable *ReferenceTable(void) { VariableTable *t = VariableTableNew(); assert_false(PutVar(t, "scope1.lval1")); assert_false(PutVar(t, "scope1.lval2")); assert_false(PutVar(t, "scope2.lval1")); { VarRef *ref = VarRefParse("scope1.array[one]"); Rval rval = (Rval) { "scope1.array[one]", RVAL_TYPE_SCALAR }; assert_false(VariableTablePut(t, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL)); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("scope1.array[two]"); Rval rval = (Rval) { "scope1.array[two]", RVAL_TYPE_SCALAR }; assert_false(VariableTablePut(t, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL)); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("scope1.array[two][three]"); Rval rval = (Rval) { "scope1.array[two][three]", RVAL_TYPE_SCALAR }; assert_false(VariableTablePut(t, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL)); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("scope1.array[two][four]"); Rval rval = (Rval) { "scope1.array[two][four]", RVAL_TYPE_SCALAR }; assert_false(VariableTablePut(t, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL)); VarRefDestroy(ref); } assert_false(PutVar(t, "ns1:scope1.lval1")); assert_false(PutVar(t, "ns1:scope1.lval2")); assert_false(PutVar(t, "ns1:scope2.lval1")); return t; } static void TestGet(VariableTable *t, const char *ref_str) { VarRef *ref = VarRefParse(ref_str); Variable *v = VariableTableGet(t, ref); assert_true(v != NULL); assert_int_equal(0, VarRefCompare(ref, v->ref)); assert_string_equal(ref_str, RvalScalarValue(v->rval)); VarRefDestroy(ref); } static void test_get_in_default_namespace(void) { VariableTable *t = ReferenceTable(); TestGet(t, "scope1.lval1"); TestGet(t, "scope1.lval2"); TestGet(t, "scope2.lval1"); VariableTableDestroy(t); } static void test_get_different_namespaces(void) { VariableTable *t = ReferenceTable(); TestGet(t, "scope1.lval1"); TestGet(t, "ns1:scope1.lval1"); VariableTableDestroy(t); } static void test_get_indices(void) { VariableTable *t = ReferenceTable(); TestGet(t, "scope1.array[one]"); TestGet(t, "scope1.array[two]"); VariableTableDestroy(t); } static void test_replace(void) { VariableTable *t = ReferenceTable(); VarRef *ref = VarRefParse("scope1.lval1"); TestGet(t, "scope1.lval1"); Rval rval = (Rval) { "foo", RVAL_TYPE_SCALAR }; assert_true(VariableTablePut(t, ref, &rval, CF_DATA_TYPE_STRING, NULL, NULL)); Variable *v = VariableTableGet(t, ref); assert_true(v != NULL); assert_string_equal("foo", RvalScalarValue(v->rval)); VarRefDestroy(ref); VariableTableDestroy(t); } static void test_remove(void) { VariableTable *t = ReferenceTable(); { VarRef *ref = VarRefParse("scope1.array[one]"); assert_true(VariableTableRemove(t, ref)); assert_true(VariableTableGet(t, ref) == NULL); assert_false(VariableTableRemove(t, ref)); assert_int_equal(9, VariableTableCount(t, NULL, NULL, NULL)); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("ns1:scope1.lval1"); assert_true(VariableTableRemove(t, ref)); assert_true(VariableTableGet(t, ref) == NULL); assert_false(VariableTableRemove(t, ref)); assert_int_equal(8, VariableTableCount(t, NULL, NULL, NULL)); VarRefDestroy(ref); } VariableTableDestroy(t); } static void test_clear(void) { { VariableTable *t = ReferenceTable(); assert_false(VariableTableClear(t, "xxx", NULL, NULL)); assert_false(VariableTableClear(t, NULL, "xxx", NULL)); assert_false(VariableTableClear(t, NULL, NULL, "xxx")); assert_int_equal(10, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, NULL, NULL, NULL)); assert_int_equal(0, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "default", NULL, NULL)); assert_int_equal(3, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "default", "scope1", NULL)); assert_int_equal(4, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "default", NULL, "array")); assert_int_equal(6, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "ns1", NULL, NULL)); assert_int_equal(7, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "ns1", "scope2", NULL)); assert_int_equal(9, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "default", "scope1", "lval1")); assert_int_equal(9, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } { VariableTable *t = ReferenceTable(); assert_true(VariableTableClear(t, "default", "scope1", "lval1")); assert_int_equal(9, VariableTableCount(t, NULL, NULL, NULL)); VariableTableDestroy(t); } } static void test_counting(void) { VariableTable *t = ReferenceTable(); assert_int_equal(10, VariableTableCount(t, NULL, NULL, NULL)); assert_int_equal(7, VariableTableCount(t, "default", NULL, NULL)); assert_int_equal(8, VariableTableCount(t, NULL, "scope1", NULL)); assert_int_equal(6, VariableTableCount(t, "default", "scope1", NULL)); assert_int_equal(4, VariableTableCount(t, NULL, NULL, "lval1")); assert_int_equal(3, VariableTableCount(t, "ns1", NULL, NULL)); assert_int_equal(2, VariableTableCount(t, "ns1", "scope1", NULL)); assert_int_equal(4, VariableTableCount(t, NULL, NULL, "array")); assert_int_equal(1, VariableTableCount(t, "default", "scope1", "lval1")); VariableTableDestroy(t); } static void test_iterate_indices(void) { VariableTable *t = ReferenceTable(); { VarRef *ref = VarRefParse("default:scope1.array"); VariableTableIterator *iter = VariableTableIteratorNewFromVarRef(t, ref); Variable *v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(2, v->ref->num_indices); assert_string_equal("two", v->ref->indices[0]); assert_string_equal("three", v->ref->indices[1]); v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(1, v->ref->num_indices); assert_string_equal("one", v->ref->indices[0]); v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(1, v->ref->num_indices); assert_string_equal("two", v->ref->indices[0]); v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(2, v->ref->num_indices); assert_string_equal("two", v->ref->indices[0]); assert_string_equal("four", v->ref->indices[1]); assert_false(VariableTableIteratorNext(iter) != NULL); VariableTableIteratorDestroy(iter); VarRefDestroy(ref); } { VarRef *ref = VarRefParse("default:scope1.array[two]"); VariableTableIterator *iter = VariableTableIteratorNewFromVarRef(t, ref); Variable *v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(2, v->ref->num_indices); assert_string_equal("two", v->ref->indices[0]); assert_string_equal("three", v->ref->indices[1]); v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(1, v->ref->num_indices); assert_string_equal("two", v->ref->indices[0]); v = VariableTableIteratorNext(iter); assert_true(v != NULL); assert_int_equal(2, v->ref->num_indices); assert_string_equal("two", v->ref->indices[0]); assert_string_equal("four", v->ref->indices[1]); assert_false(VariableTableIteratorNext(iter) != NULL); VariableTableIteratorDestroy(iter); VarRefDestroy(ref); } VariableTableDestroy(t); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_get_in_default_namespace), unit_test(test_get_different_namespaces), unit_test(test_get_indices), unit_test(test_replace), unit_test(test_remove), unit_test(test_clear), unit_test(test_counting), unit_test(test_iterate_indices), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/parsemode_test.c0000664000175100017510000000267212411001073020315 0ustar00a10038a1003800000000000000#include #include typedef struct { char *string; mode_t plus; mode_t minus; } mode_definition; mode_definition modes[] = { { "666", S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH, S_IXUSR|S_IXGRP|S_IXOTH|S_ISUID|S_ISGID|S_ISVTX }, { "g+w", S_IWGRP, 0 }, { "u+r,u+w,g-w,o-rw", S_IRUSR|S_IWUSR, S_IWGRP|S_IWOTH|S_IROTH }, { NULL, 0, 0 } // last case, still tested }; void test_mode(void) { int ret = false; mode_t plus = 0; mode_t minus = 0; int mode = 0; do { ret = ParseModeString(modes[mode].string, &plus, &minus); assert_true(ret); assert_int_equal(modes[mode].plus, plus); assert_int_equal(modes[mode].minus, minus); } while (modes[mode++].string); } typedef struct { char *string; bool valid; } validation_mode; validation_mode validation_modes[] = { { "", false }, { "abc", false }, { "222222", false }, { "22222", true }, { NULL, true } // last case, still tested }; void test_validation(void) { int ret = false; mode_t minus = 0; mode_t plus = 0; int mode = 0; do { ret = ParseModeString( validation_modes[mode].string, &plus, &minus); assert_int_equal(validation_modes[mode].valid, ret); } while (validation_modes[mode++].string); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_validation), unit_test(test_mode) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/evalfunction_test.c0000664000175100017510000000312212400110676021032 0ustar00a10038a1003800000000000000#include #include #include static bool netgroup_more = false; #if SETNETGRENT_RETURNS_INT int #else void #endif setnetgrent(const char *netgroup) { if (strcmp(netgroup, "valid_netgroup") == 0) { netgroup_more = true; #if SETNETGRENT_RETURNS_INT return 1; #else return; #endif } netgroup_more = false; #if SETNETGRENT_RETURNS_INT return 0; #endif } int getnetgrent(char **hostp, char **userp, char **domainp) { if (netgroup_more) { *hostp = NULL; *userp = "user"; *domainp = NULL; netgroup_more = false; return 1; } else { return 0; } } static void test_hostinnetgroup_found(void) { #ifdef _AIX return; //redmine6318 #endif EvalContext *ctx = EvalContextNew(); FnCallResult res; Rlist *args = NULL; RlistAppendScalar(&args, "valid_netgroup"); res = FnCallHostInNetgroup(ctx, NULL, NULL, args); assert_string_equal("any", (char *) res.rval.item); EvalContextDestroy(ctx); } static void test_hostinnetgroup_not_found(void) { EvalContext *ctx = EvalContextNew(); FnCallResult res; Rlist *args = NULL; RlistAppendScalar(&args, "invalid_netgroup"); res = FnCallHostInNetgroup(ctx, NULL, NULL, args); assert_string_equal("!any", (char *) res.rval.item); EvalContextDestroy(ctx); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_hostinnetgroup_found), unit_test(test_hostinnetgroup_not_found), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/sequence_test.c0000664000175100017510000002334012400110676020151 0ustar00a10038a1003800000000000000#include #include #include static Seq *SequenceCreateRange(size_t initialCapacity, size_t start, size_t end) { Seq *seq = SeqNew(initialCapacity, free); for (size_t i = start; i <= end; i++) { size_t *item = xmalloc(sizeof(size_t)); *item = i; SeqAppend(seq, item); } return seq; } static void test_create_destroy(void) { Seq *seq = SeqNew(5, NULL); SeqDestroy(seq); } static void test_append(void) { Seq *seq = SeqNew(2, free); for (size_t i = 0; i < 1000; i++) { SeqAppend(seq, xstrdup("snookie")); } assert_int_equal(seq->length, 1000); for (size_t i = 0; i < 1000; i++) { assert_string_equal(seq->data[i], "snookie"); } SeqDestroy(seq); } static int CompareNumbers(const void *a, const void *b, ARG_UNUSED void *_user_data) { return *(size_t *) a - *(size_t *) b; } static void test_lookup(void) { Seq *seq = SequenceCreateRange(10, 0, 9); size_t *key = xmalloc(sizeof(size_t)); *key = 5; size_t *result = SeqLookup(seq, key, CompareNumbers); assert_int_equal(*result, *key); *key = 17; result = SeqLookup(seq, key, CompareNumbers); assert_int_equal(result, NULL); SeqDestroy(seq); free(key); } static void test_binary_lookup(void) { size_t *key = xmalloc(sizeof(size_t)); size_t *result; // Even numbered length. Seq *seq = SequenceCreateRange(10, 0, 9); for (size_t i = 0; i <= 9; i++) { *key = i; result = SeqBinaryLookup(seq, key, CompareNumbers); assert_int_equal(*result, *key); } *key = 17; result = SeqBinaryLookup(seq, key, CompareNumbers); assert_int_equal(result, NULL); // Odd numbered length. SeqDestroy(seq); seq = SequenceCreateRange(10, 0, 10); for (size_t i = 0; i <= 10; i++) { *key = i; result = SeqBinaryLookup(seq, key, CompareNumbers); assert_int_equal(*result, *key); } *key = 17; result = SeqBinaryLookup(seq, key, CompareNumbers); assert_int_equal(result, NULL); // Zero-length. SeqDestroy(seq); seq = SeqNew(0, free); *key = 0; result = SeqBinaryLookup(seq, key, CompareNumbers); assert_int_equal(result, NULL); SeqDestroy(seq); free(key); } static void test_index_of(void) { Seq *seq = SequenceCreateRange(10, 0, 9); size_t *key = xmalloc(sizeof(size_t)); *key = 5; ssize_t index = SeqIndexOf(seq, key, CompareNumbers); assert_int_equal(index, 5); *key = 17; index = SeqIndexOf(seq, key, CompareNumbers); assert_true(index == -1); SeqDestroy(seq); free(key); } static void test_binary_index_of(void) { size_t *key = xmalloc(sizeof(size_t)); ssize_t result; // Even numbered length. Seq *seq = SequenceCreateRange(10, 0, 9); for (size_t i = 0; i <= 9; i++) { *key = i; result = SeqBinaryIndexOf(seq, key, CompareNumbers); assert_int_equal(result, i); } *key = 17; result = SeqBinaryIndexOf(seq, key, CompareNumbers); assert_true(result == -1); // Odd numbered length. SeqDestroy(seq); seq = SequenceCreateRange(10, 0, 10); for (size_t i = 0; i <= 10; i++) { *key = i; result = SeqBinaryIndexOf(seq, key, CompareNumbers); assert_int_equal(result, i); } *key = 17; result = SeqBinaryIndexOf(seq, key, CompareNumbers); assert_true(result == -1); // Zero-length. SeqDestroy(seq); seq = SeqNew(0, free); *key = 0; result = SeqBinaryIndexOf(seq, key, CompareNumbers); assert_true(result == -1); seq = SeqNew(5, free); SeqAppend(seq, xmalloc(sizeof(size_t))); *(size_t *)SeqAt(seq, 0) = 3; SeqAppend(seq, xmalloc(sizeof(size_t))); *(size_t *)SeqAt(seq, 1) = 3; SeqAppend(seq, xmalloc(sizeof(size_t))); *(size_t *)SeqAt(seq, 2) = 3; SeqAppend(seq, xmalloc(sizeof(size_t))); *(size_t *)SeqAt(seq, 3) = 3; SeqAppend(seq, xmalloc(sizeof(size_t))); *(size_t *)SeqAt(seq, 4) = 3; *key = 3; result = SeqBinaryIndexOf(seq, key, CompareNumbers); // Any number within the range is ok. assert_true(result >= 0 && result < 5); SeqDestroy(seq); free(key); } static void test_sort(void) { Seq *seq = SeqNew(5, NULL); size_t one = 1; size_t two = 2; size_t three = 3; size_t four = 4; size_t five = 5; SeqAppend(seq, &three); SeqAppend(seq, &two); SeqAppend(seq, &five); SeqAppend(seq, &one); SeqAppend(seq, &four); SeqSort(seq, CompareNumbers, NULL); assert_int_equal(seq->data[0], &one); assert_int_equal(seq->data[1], &two); assert_int_equal(seq->data[2], &three); assert_int_equal(seq->data[3], &four); assert_int_equal(seq->data[4], &five); SeqDestroy(seq); } static void test_soft_sort(void) { Seq *seq = SeqNew(5, NULL); size_t one = 1; size_t two = 2; size_t three = 3; size_t four = 4; size_t five = 5; SeqAppend(seq, &three); SeqAppend(seq, &two); SeqAppend(seq, &five); SeqAppend(seq, &one); SeqAppend(seq, &four); Seq *new_seq = SeqSoftSort(seq, CompareNumbers, NULL); assert_int_equal(seq->data[0], &three); assert_int_equal(seq->data[1], &two); assert_int_equal(seq->data[2], &five); assert_int_equal(seq->data[3], &one); assert_int_equal(seq->data[4], &four); assert_int_equal(new_seq->data[0], &one); assert_int_equal(new_seq->data[1], &two); assert_int_equal(new_seq->data[2], &three); assert_int_equal(new_seq->data[3], &four); assert_int_equal(new_seq->data[4], &five); // This is a soft destroy, but normal destroy should also work. SeqDestroy(new_seq); SeqDestroy(seq); } static void test_remove_range(void) { Seq *seq = SequenceCreateRange(10, 0, 9); SeqRemoveRange(seq, 3, 9); assert_int_equal(seq->length, 3); assert_int_equal(*(size_t *) seq->data[0], 0); assert_int_equal(*(size_t *) seq->data[1], 1); assert_int_equal(*(size_t *) seq->data[2], 2); SeqDestroy(seq); seq = SequenceCreateRange(10, 0, 9); SeqRemoveRange(seq, 0, 2); assert_int_equal(seq->length, 7); assert_int_equal(*(size_t *) seq->data[0], 3); SeqDestroy(seq); seq = SequenceCreateRange(10, 0, 9); SeqRemoveRange(seq, 5, 5); assert_int_equal(seq->length, 9); assert_int_equal(*(size_t *) seq->data[5], 6); SeqDestroy(seq); } static void test_remove(void) { Seq *seq = SequenceCreateRange(10, 0, 9); SeqRemove(seq, 5); assert_int_equal(seq->length, 9); assert_int_equal(*(size_t *) seq->data[5], 6); SeqDestroy(seq); seq = SequenceCreateRange(10, 0, 9); SeqRemove(seq, 0); assert_int_equal(seq->length, 9); assert_int_equal(*(size_t *) seq->data[0], 1); SeqDestroy(seq); seq = SequenceCreateRange(10, 0, 9); SeqRemove(seq, 9); assert_int_equal(seq->length, 9); assert_int_equal(*(size_t *) seq->data[8], 8); SeqDestroy(seq); } static void test_reverse(void) { { Seq *seq = SequenceCreateRange(2, 0, 1); assert_int_equal(0, *(size_t *)seq->data[0]); assert_int_equal(1, *(size_t *)seq->data[1]); SeqReverse(seq); assert_int_equal(1, *(size_t *)seq->data[0]); assert_int_equal(0, *(size_t *)seq->data[1]); SeqDestroy(seq); } { Seq *seq = SequenceCreateRange(3, 0, 2); SeqReverse(seq); assert_int_equal(2, *(size_t *)seq->data[0]); assert_int_equal(1, *(size_t *)seq->data[1]); assert_int_equal(0, *(size_t *)seq->data[2]); SeqDestroy(seq); } } static void test_len(void) { Seq *seq = SeqNew(5, NULL); size_t one = 1; size_t two = 2; size_t three = 3; size_t four = 4; size_t five = 5; SeqAppend(seq, &three); SeqAppend(seq, &two); SeqAppend(seq, &five); SeqAppend(seq, &one); SeqAppend(seq, &four); assert_int_equal(SeqLength(seq),5); SeqDestroy(seq); } static void test_get_range(void) { Seq *seq = SeqNew(5, NULL); size_t one = 1; size_t two = 2; size_t three = 3; size_t four = 4; size_t five = 5; SeqAppend(seq, &three); SeqAppend(seq, &two); SeqAppend(seq, &five); SeqAppend(seq, &one); SeqAppend(seq, &four); assert_int_equal(SeqLength(seq),5); { Seq *sub_1 = SeqGetRange(seq, 0, 4); assert_true (sub_1 != NULL); assert_int_equal (sub_1->length, seq->length); assert_int_equal (SeqAt(sub_1, 0), SeqAt(seq, 0)); assert_int_equal (SeqAt(sub_1, 1), SeqAt(seq, 1)); assert_int_equal (SeqAt(sub_1, 2), SeqAt(seq, 2)); assert_int_equal (SeqAt(sub_1, 3), SeqAt(seq, 3)); assert_int_equal (SeqAt(sub_1, 4), SeqAt(seq, 4)); SeqSoftDestroy(sub_1); } { Seq *sub_1 = SeqGetRange(seq, 2, 4); assert_true (sub_1 != NULL); assert_int_equal (sub_1->length, 4 - 2 + 1); assert_int_equal (SeqAt(sub_1, 0), SeqAt(seq, 2)); assert_int_equal (SeqAt(sub_1, 1), SeqAt(seq, 3)); assert_int_equal (SeqAt(sub_1, 2), SeqAt(seq, 4)); SeqSoftDestroy(sub_1); } assert_true (!SeqGetRange(seq, 3, 6)); assert_true (!SeqGetRange(seq, 3, 2)); SeqDestroy(seq); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_create_destroy), unit_test(test_append), unit_test(test_lookup), unit_test(test_binary_lookup), unit_test(test_index_of), unit_test(test_binary_index_of), unit_test(test_sort), unit_test(test_soft_sort), unit_test(test_remove_range), unit_test(test_remove), unit_test(test_reverse), unit_test(test_len), unit_test(test_get_range) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/domainname_test.c0000664000175100017510000000531512243421446020460 0ustar00a10038a1003800000000000000#include #include char fqname[CF_BUFSIZE]; char uqname[CF_BUFSIZE]; char domain[CF_BUFSIZE]; void CalculateDomainName(const char *nodename, const char *dnsname, char *fqname, char *uqname, char *domain); static void test_fqname(void) { const char nodename[] = "mylaptop.example.com"; const char dnsname[] = "mylaptop.example.com"; CalculateDomainName(nodename, dnsname, fqname, uqname, domain); assert_string_equal(fqname, "mylaptop.example.com"); assert_string_equal(uqname, "mylaptop"); assert_string_equal(domain, "example.com"); } static void test_uqname(void) { CalculateDomainName("mylaptop", "mylaptop.example.com", fqname, uqname, domain); assert_string_equal(fqname, "mylaptop.example.com"); assert_string_equal(uqname, "mylaptop"); assert_string_equal(domain, "example.com"); } static void test_uqname2(void) { CalculateDomainName("user.laptop", "user.laptop.example.com", fqname, uqname, domain); assert_string_equal(fqname, "user.laptop.example.com"); assert_string_equal(uqname, "user.laptop"); assert_string_equal(domain, "example.com"); } static void test_fqname_not_really_fq(void) { CalculateDomainName("user.laptop", "user.laptop", fqname, uqname, domain); assert_string_equal(fqname, "user.laptop"); assert_string_equal(uqname, "user"); assert_string_equal(domain, "laptop"); } static void test_fqname_not_really_fq2(void) { CalculateDomainName("laptop", "laptop", fqname, uqname, domain); assert_string_equal(fqname, "laptop"); assert_string_equal(uqname, "laptop"); assert_string_equal(domain, ""); } static void test_fqname_unresolvable(void) { CalculateDomainName("laptop", "", fqname, uqname, domain); assert_string_equal(fqname, "laptop"); assert_string_equal(uqname, "laptop"); assert_string_equal(domain, ""); } static void test_no_names(void) { CalculateDomainName("", "", fqname, uqname, domain); assert_string_equal(fqname, ""); assert_string_equal(uqname, ""); assert_string_equal(domain, ""); } static void test_wrong_fqname(void) { CalculateDomainName("laptop", "a1006.cfengine.com", fqname, uqname, domain); assert_string_equal(fqname, "a1006.cfengine.com"); assert_string_equal(uqname, "laptop"); assert_string_equal(domain, ""); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_fqname), unit_test(test_uqname), unit_test(test_uqname2), unit_test(test_fqname_not_really_fq), unit_test(test_fqname_not_really_fq2), unit_test(test_fqname_unresolvable), unit_test(test_no_names), unit_test(test_wrong_fqname), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/alloc_test.c0000664000175100017510000000142312243421446017436 0ustar00a10038a1003800000000000000#include #include #include #include #include void test_xasprintf(void) { char *s; int res = xasprintf(&s, "Foo%d%s", 123, "17"); assert_int_equal(res, 8); assert_string_equal(s, "Foo12317"); free(s); } void test_xvasprintf_sub(const char *fmt, ...) { char *s; va_list ap; va_start(ap, fmt); int res = xvasprintf(&s, fmt, ap); va_end(ap); assert_int_equal(res, 8); assert_string_equal(s, "Foo12317"); free(s); } void test_xvasprintf(void) { test_xvasprintf_sub("Foo%d%s", 123, "17"); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_xasprintf), unit_test(test_xvasprintf), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/string_writer_test.c0000664000175100017510000000373712400110676021253 0ustar00a10038a1003800000000000000#include #include #include void test_empty_string_buffer(void) { Writer *w = StringWriter(); assert_int_equal(StringWriterLength(w), 0); assert_string_equal(StringWriterData(w), ""); WriterClose(w); } void test_write_empty_string_buffer(void) { Writer *w = StringWriter(); WriterWrite(w, ""); assert_int_equal(StringWriterLength(w), 0); assert_string_equal(StringWriterData(w), ""); WriterClose(w); } void test_write_string_buffer(void) { Writer *w = StringWriter(); WriterWrite(w, "123"); assert_int_equal(StringWriterLength(w), 3); assert_string_equal(StringWriterData(w), "123"); WriterClose(w); } void test_multiwrite_string_buffer(void) { Writer *w = StringWriter(); WriterWrite(w, "123"); WriterWrite(w, "456"); assert_int_equal(StringWriterLength(w), 6); assert_string_equal(StringWriterData(w), "123456"); WriterClose(w); } void test_write_char_string_buffer(void) { Writer *w = StringWriter(); WriterWriteChar(w, '1'); WriterWriteChar(w, '2'); WriterWriteChar(w, '3'); assert_string_equal(StringWriterData(w), "123"); WriterClose(w); } void test_release_string(void) { Writer *w = StringWriter(); WriterWrite(w, "123"); WriterWrite(w, "456"); char *ret = StringWriterClose(w); assert_string_equal(ret, "123456"); free(ret); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_empty_string_buffer), unit_test(test_write_empty_string_buffer), unit_test(test_write_string_buffer), unit_test(test_multiwrite_string_buffer), unit_test(test_write_char_string_buffer), unit_test(test_release_string), }; return run_tests(tests); } // STUBS void __ProgrammingError(ARG_UNUSED const char *file, ARG_UNUSED int lineno, ARG_UNUSED const char *format, ...) { fail(); exit(42); } cfengine-3.6.2/tests/unit/sysinfo_test.c0000664000175100017510000000110612400110676020027 0ustar00a10038a1003800000000000000#include #include static void test_uptime(void) { /* * Assume we have been online at least five minutes, and less than two years. * If two years is not long enough, stop watching that uptime counter and * reboot the machine, dammit! :-) */ int uptime = GetUptimeMinutes(time(NULL)); printf("Uptime: %.2f days\n", uptime / (60.0 * 24)); assert_in_range(uptime, 5, 60*24*365*2); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_uptime) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/dynamic_dependency_test.sh0000775000175100017510000000461012400110676022355 0ustar00a10038a1003800000000000000#!/bin/bash # Tests that the symbols in our static libraries do not occur twice in the # output binaries. Most platforms don't warn about this, but it has potential # ill effects. # # How it can happen: It can happen if we list a static library as a dependency # for libpromises, and then we list the same static library as a dependency for # a binary that depends on libpromises. Then the symbol will be included both # in the library and in the binary. # # What effects does it have: Exactly how the symbols are resolved appears to be # platform dependent, but what can happen is this: At any point, when you call # a duplicate symbol, depending on where you call it from, you will either call # the version in the binary or in the library. This is fine, since they both # contain exactly the same code. However, they do not refer to the same global # symbols. They each have their own set. This means that something that was # initialized in the binary may not be initialized in the library, even though # the symbol name is the same. This has weird effects, like a symbol suddenly # switching from a valid value to zero when the stack trace crosses a library # boundary. # # The problem has been observed on AIX, where the log level randomly switches # between verbose and non-verbose, depending on where the Log() function was # called from. It has also been observed on certain Linux versions (Ubuntu # 12.04). # # How do we test for it: By making sure that functions that are known to be in # the static libraries are undefined in the binaries, which means that they # will link to the shared library version, instead of using their own version. cd ../.. # libutils.a libenv.a libcfnet.a # v v v for symbol in LogSetGlobalLevel GetInterfacesInfo ConnectionInfoNew; do for binary in cf-*; do if test -e "$binary/.libs/$binary"; then LOC="$binary/.libs/$binary" else LOC="$binary/$binary" fi if nm "$LOC" | grep "$symbol" >/dev/null 2>&1 && ! nm -u "$LOC" | grep "$symbol" >/dev/null 2>&1; then echo "$symbol is defined in $binary, but should be undefined." echo "Most likely a static library is listed in the Makefile.am which shouldn't be." echo "Check the *_LDADD statements in $binary/Makefile.am." exit 1 fi done done exit 0 cfengine-3.6.2/tests/unit/expand_test.c0000664000175100017510000004460112400110676017623 0ustar00a10038a1003800000000000000#include #include #include #include #include #include static void test_extract_scalar_prefix() { Buffer *b = BufferNew(); assert_int_equal(sizeof("hello ") - 1, ExtractScalarPrefix(b, "hello $(world) xy", sizeof("hello $(world) xy") -1)); assert_string_equal("hello ", BufferData(b)); BufferClear(b); assert_int_equal(sizeof("hello (world) xy") -1, ExtractScalarPrefix(b, "hello (world) xy", sizeof("hello (world) xy") -1)); assert_string_equal("hello (world) xy", BufferData(b)); BufferClear(b); assert_int_equal(sizeof("hello$)") -1, ExtractScalarPrefix(b, "hello$)$(world)xy", sizeof("hello$)$(world)xy") -1)); assert_string_equal("hello$)", BufferData(b)); BufferClear(b); assert_int_equal(0, ExtractScalarPrefix(b, "", 0)); assert_string_equal("", BufferData(b)); BufferDestroy(b); } static void test_extract_reference_(const char *scalar, bool expect_success, const char *outer, const char *inner) { Buffer *b = BufferNew(); size_t len = strlen(scalar); bool success = ExtractScalarReference(b, scalar, len, false); assert_true(success == expect_success); assert_string_equal(outer, BufferData(b)); BufferClear(b); success = ExtractScalarReference(b, scalar, len, true); assert_true(success == expect_success); assert_string_equal(inner, BufferData(b)); BufferDestroy(b); } static void test_extract_reference(void) { test_extract_reference_("${stuff}", true, "${stuff}", "stuff"); test_extract_reference_("$(stuff)", true, "$(stuff)", "stuff"); test_extract_reference_("abc $def ${x} y", true, "${x}", "x"); test_extract_reference_("${stuff)", false, "", ""); test_extract_reference_("abc $def", false, "", ""); test_extract_reference_("stuff", false, "", ""); test_extract_reference_("", false, "", ""); test_extract_reference_("abc $xa ", false, "", ""); test_extract_reference_("${}", false, "", ""); test_extract_reference_("x$()a", false, "", ""); test_extract_reference_("$($(x))", true, "$($(x))", "$(x)"); test_extract_reference_("$(x${$(y)})", true, "$(x${$(y)})", "x${$(y)}"); test_extract_reference_("$(x${$(y)}) $(y) ${x${z}}", true, "$(x${$(y)})", "x${$(y)}"); } static void test_map_iterators_from_rval_empty(void **state) { EvalContext *ctx = *state; Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "default", "none", "agent", NULL, NULL); Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; MapIteratorsFromRval(ctx, bp, (Rval) { "", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_int_equal(0, RlistLen(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); PolicyDestroy(p); } static void test_map_iterators_from_rval_literal(void **state) { EvalContext *ctx = *state; Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "default", "none", "agent", NULL, NULL); Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; MapIteratorsFromRval(ctx, bp, (Rval) { "snookie", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_int_equal(0, RlistLen(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); PolicyDestroy(p); } static void test_map_iterators_from_rval_naked_list_var(void **state) { EvalContext *ctx = *state; Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "default", "scope", "agent", NULL, NULL); { Rlist *list = NULL; RlistAppend(&list, "jersey", RVAL_TYPE_SCALAR); VarRef *lval = VarRefParse("scope.jwow"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); VarRefDestroy(lval); RlistDestroy(list); } EvalContextStackPushBundleFrame(ctx, bp, NULL, false); { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; MapIteratorsFromRval(ctx, bp, (Rval) { "${jwow}", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_int_equal(1, RlistLen(lists)); assert_string_equal("jwow", RlistScalarValue(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); RlistDestroy(lists); } { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; char *str = xstrdup("${scope.jwow}"); MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_string_equal("${scope#jwow}", str); free(str); assert_int_equal(1, RlistLen(lists)); assert_string_equal("scope#jwow", RlistScalarValue(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); RlistDestroy(lists); } { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; char *str = xstrdup("${default:scope.jwow}"); MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_string_equal("${default*scope#jwow}", str); free(str); assert_int_equal(1, RlistLen(lists)); assert_string_equal("default*scope#jwow", RlistScalarValue(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); RlistDestroy(lists); } EvalContextStackPopFrame(ctx); PolicyDestroy(p); } static void test_map_iterators_from_rval_naked_list_var_namespace(void **state) { EvalContext *ctx = *state; Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "ns", "scope", "agent", NULL, NULL); { Rlist *list = NULL; RlistAppend(&list, "jersey", RVAL_TYPE_SCALAR); VarRef *lval = VarRefParse("ns:scope.jwow"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); VarRefDestroy(lval); RlistDestroy(list); } EvalContextStackPushBundleFrame(ctx, bp, NULL, false); { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; MapIteratorsFromRval(ctx, bp, (Rval) { "${jwow}", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_int_equal(1, RlistLen(lists)); assert_string_equal("jwow", RlistScalarValue(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); RlistDestroy(lists); } { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; char *str = xstrdup("${scope.jwow}"); MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_string_equal("${scope#jwow}", str); free(str); assert_int_equal(1, RlistLen(lists)); assert_string_equal("scope#jwow", RlistScalarValue(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); RlistDestroy(lists); } { Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; char *str = xstrdup("${ns:scope.jwow}"); MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); assert_string_equal("${ns*scope#jwow}", str); free(str); assert_int_equal(1, RlistLen(lists)); assert_string_equal("ns*scope#jwow", RlistScalarValue(lists)); assert_int_equal(0, RlistLen(scalars)); assert_int_equal(0, RlistLen(containers)); RlistDestroy(lists); } EvalContextStackPopFrame(ctx); PolicyDestroy(p); } static void test_expand_scalar_two_scalars_concat(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.one"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.two"); EvalContextVariablePut(ctx, lval, "second", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Buffer *res = BufferNew(); ExpandScalar(ctx, "default", "bundle", "a $(one) b $(two)c", res); assert_string_equal("a first b secondc", BufferData(res)); BufferDestroy(res); } static void test_expand_scalar_two_scalars_nested(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.one"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.two"); EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Buffer *res = BufferNew(); ExpandScalar(ctx, "default", "bundle", "a $($(two))b", res); assert_string_equal("a firstb", BufferData(res)); BufferDestroy(res); } static void test_expand_scalar_array_concat(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.foo[one]"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.foo[two]"); EvalContextVariablePut(ctx, lval, "second", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Buffer *res = BufferNew(); ExpandScalar(ctx, "default", "bundle", "a $(foo[one]) b $(foo[two])c", res); assert_string_equal("a first b secondc", BufferData(res)); BufferDestroy(res); } static void test_expand_scalar_array_with_scalar_arg(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.foo[one]"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.bar"); EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Buffer *res = BufferNew(); ExpandScalar(ctx, "default", "bundle", "a$(foo[$(bar)])b", res); assert_string_equal("afirstb", BufferData(res)); BufferDestroy(res); } static void test_expand_scalar_undefined(void **state) { EvalContext *ctx = *state; Buffer *res = BufferNew(); ExpandScalar(ctx, "default", "bundle", "a$(undefined)b", res); assert_string_equal("a$(undefined)b", BufferData(res)); BufferDestroy(res); } static void test_expand_scalar_nested_inner_undefined(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.foo[one]"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Buffer *res = BufferNew(); ExpandScalar(ctx, "default", "bundle", "a$(foo[$(undefined)])b", res); assert_string_equal("a$(foo[$(undefined)])b", BufferData(res)); BufferDestroy(res); } static void test_expand_list_nested(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.i"); EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.inner[one]"); Rlist *list = NULL; RlistAppendScalar(&list, "foo"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); RlistDestroy(list); VarRefDestroy(lval); } Rlist *outer = NULL; RlistAppendScalar(&outer, "@{inner[$(i)]}"); Rlist *expanded = ExpandList(ctx, "default", "bundle", outer, true); assert_int_equal(1, RlistLen(expanded)); assert_string_equal("foo", RlistScalarValue(expanded)); RlistDestroy(outer); RlistDestroy(expanded); } static PromiseResult actuator_expand_promise_array_with_scalar_arg( ARG_UNUSED EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert_string_equal("first", pp->promiser); return PROMISE_RESULT_NOOP; } static void test_expand_promise_array_with_scalar_arg(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.foo[one]"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.bar"); EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Policy *policy = PolicyNew(); Bundle *bundle = PolicyAppendBundle(policy, NamespaceDefault(), "bundle", "agent", NULL, NULL); PromiseType *promise_type = BundleAppendPromiseType(bundle, "dummy"); Promise *promise = PromiseTypeAppendPromise(promise_type, "$(foo[$(bar)])", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any"); EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); EvalContextStackPushPromiseTypeFrame(ctx, promise_type); ExpandPromise(ctx, promise, actuator_expand_promise_array_with_scalar_arg, NULL); EvalContextStackPopFrame(ctx); EvalContextStackPopFrame(ctx); PolicyDestroy(policy); } static int actuator_state = 0; static PromiseResult actuator_expand_promise_slist( ARG_UNUSED EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { if (strcmp("a", pp->promiser) == 0) { assert_int_equal(0, actuator_state); actuator_state++; } else if (strcmp("b", pp->promiser) == 0) { assert_int_equal(1, actuator_state); actuator_state++; } else { fail(); } return PROMISE_RESULT_NOOP; } static void test_expand_promise_slist(void **state) { actuator_state = 0; EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.foo"); Rlist *list = NULL; RlistAppendScalar(&list, "a"); RlistAppendScalar(&list, "b"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); RlistDestroy(list); VarRefDestroy(lval); } Policy *policy = PolicyNew(); Bundle *bundle = PolicyAppendBundle(policy, NamespaceDefault(), "bundle", "agent", NULL, NULL); PromiseType *promise_type = BundleAppendPromiseType(bundle, "dummy"); Promise *promise = PromiseTypeAppendPromise(promise_type, "$(foo)", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any"); EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); EvalContextStackPushPromiseTypeFrame(ctx, promise_type); ExpandPromise(ctx, promise, actuator_expand_promise_slist, NULL); EvalContextStackPopFrame(ctx); EvalContextStackPopFrame(ctx); assert_int_equal(2, actuator_state); PolicyDestroy(policy); } static PromiseResult actuator_expand_promise_array_with_slist_arg( ARG_UNUSED EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { if (strcmp("first", pp->promiser) == 0) { assert_int_equal(0, actuator_state); actuator_state++; } else if (strcmp("second", pp->promiser) == 0) { assert_int_equal(1, actuator_state); actuator_state++; } else { fprintf(stderr, "Got promiser: '%s'\n", pp->promiser); fail(); } return PROMISE_RESULT_NOOP; } static void test_expand_promise_array_with_slist_arg(void **state) { actuator_state = 0; EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.keys"); Rlist *list = NULL; RlistAppendScalar(&list, "one"); RlistAppendScalar(&list, "two"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); RlistDestroy(list); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.arr[one]"); EvalContextVariablePut(ctx, lval, "first", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.arr[two]"); EvalContextVariablePut(ctx, lval, "second", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } Policy *policy = PolicyNew(); Bundle *bundle = PolicyAppendBundle(policy, NamespaceDefault(), "bundle", "agent", NULL, NULL); PromiseType *promise_type = BundleAppendPromiseType(bundle, "dummy"); Promise *promise = PromiseTypeAppendPromise(promise_type, "$(arr[$(keys)])", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any"); EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); EvalContextStackPushPromiseTypeFrame(ctx, promise_type); ExpandPromise(ctx, promise, actuator_expand_promise_array_with_slist_arg, NULL); EvalContextStackPopFrame(ctx); EvalContextStackPopFrame(ctx); assert_int_equal(2, actuator_state); PolicyDestroy(policy); } static void test_setup(void **state) { *state = EvalContextNew(); } static void test_teardown(void **state) { EvalContext *ctx = *state; EvalContextDestroy(ctx); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_extract_scalar_prefix), unit_test(test_extract_reference), unit_test_setup_teardown(test_map_iterators_from_rval_empty, test_setup, test_teardown), unit_test_setup_teardown(test_map_iterators_from_rval_literal, test_setup, test_teardown), unit_test_setup_teardown(test_map_iterators_from_rval_naked_list_var, test_setup, test_teardown), unit_test_setup_teardown(test_map_iterators_from_rval_naked_list_var_namespace, test_setup, test_teardown), unit_test_setup_teardown(test_expand_scalar_two_scalars_concat, test_setup, test_teardown), unit_test_setup_teardown(test_expand_scalar_two_scalars_nested, test_setup, test_teardown), unit_test_setup_teardown(test_expand_scalar_array_concat, test_setup, test_teardown), unit_test_setup_teardown(test_expand_scalar_array_with_scalar_arg, test_setup, test_teardown), unit_test_setup_teardown(test_expand_scalar_undefined, test_setup, test_teardown), unit_test_setup_teardown(test_expand_scalar_nested_inner_undefined, test_setup, test_teardown), unit_test_setup_teardown(test_expand_list_nested, test_setup, test_teardown), unit_test_setup_teardown(test_expand_promise_array_with_scalar_arg, test_setup, test_teardown), unit_test_setup_teardown(test_expand_promise_slist, test_setup, test_teardown), unit_test_setup_teardown(test_expand_promise_array_with_slist_arg, test_setup, test_teardown) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/json_test.c0000664000175100017510000010334512400110676017316 0ustar00a10038a1003800000000000000#include #include #include #include /* xsnprintf */ #include static const char *OBJECT_ARRAY = "{\n" " \"first\": [\n" " \"one\",\n" " \"two\"\n" " ]\n" "}"; static const char *OBJECT_COMPOUND = "{\n" " \"first\": \"one\",\n" " \"second\": {\n" " \"third\": \"three\"\n" " },\n" " \"fourth\": {\n" " \"fifth\": \"five\"\n" " }\n" "}"; static const char *OBJECT_SIMPLE = "{\n" " \"first\": \"one\",\n" " \"second\": \"two\"\n" "}"; static const char *OBJECT_NUMERIC = "{\n" " \"real\": 1234.5678,\n" " \"int\": -1234567890\n" "}"; static const char *OBJECT_BOOLEAN = "{\n" " \"bool_value\": true\n" "}"; static const char *OBJECT_ESCAPED = "{\n" " \"escaped\": \"quote\\\"stuff \\t \\n\\n\"\n" "}"; static const char *ARRAY_SIMPLE = "[\n" " \"one\",\n" " \"two\"\n" "]"; static const char *ARRAY_NUMERIC = "[\n" " 123,\n" " 123.1234\n" "]"; static const char *ARRAY_OBJECT = "[\n" " {\n" " \"first\": \"one\"\n" " }\n" "]"; static JsonElement *LoadTestFile(const char *filename) { char path[PATH_MAX]; xsnprintf(path, sizeof(path), "%s/%s", TESTDATADIR, filename); Writer *w = FileRead(path, SIZE_MAX, NULL); if (!w) { return NULL; } JsonElement *json = NULL; const char *data = StringWriterData(w); if (JsonParse(&data, &json) != JSON_PARSE_OK) { WriterClose(w); return NULL; } WriterClose(w); return json; } static void test_new_delete(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendString(json, "first", "one"); JsonDestroy(json); } static void test_object_duplicate_key(void) { JsonElement *a = JsonObjectCreate(1); JsonObjectAppendString(a, "a", "a"); JsonObjectAppendString(a, "a", "a"); assert_int_equal(1, JsonLength(a)); JsonDestroy(a); } static void test_show_string(void) { JsonElement *str = JsonStringCreate("snookie"); Writer *writer = StringWriter(); JsonWrite(writer, str, 0); char *output = StringWriterClose(writer); assert_string_equal("\"snookie\"", output); JsonDestroy(str); free(output); } static void test_show_object_simple(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendString(json, "first", "one"); JsonObjectAppendString(json, "second", "two"); Writer *writer = StringWriter(); JsonWrite(writer, json, 0); char *output = StringWriterClose(writer); assert_string_equal(OBJECT_SIMPLE, output); JsonDestroy(json); free(output); } static void test_show_object_escaped(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendString(json, "escaped", "quote\"stuff \t \n\n"); Writer *writer = StringWriter(); JsonWrite(writer, json, 0); char *output = StringWriterClose(writer); assert_string_equal(OBJECT_ESCAPED, output); JsonDestroy(json); free(output); } static void test_show_object_numeric(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendReal(json, "real", 1234.5678); JsonObjectAppendInteger(json, "int", -1234567890); Writer *writer = StringWriter(); JsonWrite(writer, json, 0); char *output = StringWriterClose(writer); assert_string_equal(OBJECT_NUMERIC, output); JsonDestroy(json); free(output); } static void test_show_object_boolean(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendBool(json, "bool_value", true); Writer *writer = StringWriter(); JsonWrite(writer, json, 0); char *output = StringWriterClose(writer); assert_string_equal(OBJECT_BOOLEAN, output); JsonDestroy(json); free(output); } static void test_show_object_compound(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendString(json, "first", "one"); { JsonElement *inner = JsonObjectCreate(10); JsonObjectAppendString(inner, "third", "three"); JsonObjectAppendObject(json, "second", inner); } { JsonElement *inner = JsonObjectCreate(10); JsonObjectAppendString(inner, "fifth", "five"); JsonObjectAppendObject(json, "fourth", inner); } Writer *writer = StringWriter(); JsonWrite(writer, json, 0); char *output = StringWriterClose(writer); assert_string_equal(OBJECT_COMPOUND, output); JsonDestroy(json); free(output); } static void test_show_object_compound_compact(void) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendString(json, "first", "one"); { JsonElement *inner = JsonObjectCreate(10); JsonObjectAppendString(inner, "third", "three"); JsonObjectAppendObject(json, "second", inner); } { JsonElement *inner = JsonObjectCreate(10); JsonObjectAppendString(inner, "fifth", "five"); JsonObjectAppendObject(json, "fourth", inner); } Writer *writer = StringWriter(); JsonWriteCompact(writer, json); char *output = StringWriterClose(writer); assert_string_equal("{\"first\":\"one\",\"second\":{\"third\":\"three\"},\"fourth\":{\"fifth\":\"five\"}}", output); JsonDestroy(json); free(output); } static void test_show_object_array(void) { JsonElement *json = JsonObjectCreate(10); JsonElement *array = JsonArrayCreate(10); JsonArrayAppendString(array, "one"); JsonArrayAppendString(array, "two"); JsonObjectAppendArray(json, "first", array); Writer *writer = StringWriter(); JsonWrite(writer, json, 0); char *output = StringWriterClose(writer); assert_string_equal(OBJECT_ARRAY, output); JsonDestroy(json); free(output); } static void test_show_array(void) { JsonElement *array = JsonArrayCreate(10); JsonArrayAppendString(array, "one"); JsonArrayAppendString(array, "two"); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal(ARRAY_SIMPLE, output); JsonDestroy(array); free(output); } static void test_show_array_compact(void) { JsonElement *array = JsonArrayCreate(10); JsonArrayAppendString(array, "one"); JsonArrayAppendString(array, "two"); Writer *writer = StringWriter(); JsonWriteCompact(writer, array); char *output = StringWriterClose(writer); assert_string_equal("[\"one\",\"two\"]", output); JsonDestroy(array); free(output); } static void test_show_array_boolean(void) { JsonElement *array = JsonArrayCreate(10); JsonArrayAppendBool(array, true); JsonArrayAppendBool(array, false); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal("[\n" " true,\n" " false\n" "]", output); JsonDestroy(array); free(output); } static void test_show_array_numeric(void) { JsonElement *array = JsonArrayCreate(10); JsonArrayAppendInteger(array, 123); JsonArrayAppendReal(array, 123.1234); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal(ARRAY_NUMERIC, output); JsonDestroy(array); free(output); } static void test_show_array_object(void) { JsonElement *array = JsonArrayCreate(10); JsonElement *object = JsonObjectCreate(10); JsonObjectAppendString(object, "first", "one"); JsonArrayAppendObject(array, object); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal(ARRAY_OBJECT, output); JsonDestroy(array); free(output); } static void test_show_array_empty(void) { JsonElement *array = JsonArrayCreate(10); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal("[]", output); JsonDestroy(array); free(output); } static void test_show_array_nan(void) { JsonElement *array = JsonArrayCreate(10); JsonArrayAppendReal(array, sqrt(-1)); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal("[\n 0.0000\n]", output); JsonDestroy(array); free(output); } #ifndef INFINITY #define INFINITY (1.0/0.0) #endif static void test_show_array_infinity(void) { JsonElement *array = JsonArrayCreate(10); JsonArrayAppendReal(array, INFINITY); Writer *writer = StringWriter(); JsonWrite(writer, array, 0); char *output = StringWriterClose(writer); assert_string_equal("[\n 0.0000\n]", output); JsonDestroy(array); free(output); } static void test_object_get_string(void) { JsonElement *obj = JsonObjectCreate(10); JsonObjectAppendString(obj, "first", "one"); JsonObjectAppendString(obj, "second", "two"); assert_string_equal(JsonObjectGetAsString(obj, "second"), "two"); assert_string_equal(JsonObjectGetAsString(obj, "first"), "one"); JsonDestroy(obj); } static void test_object_get_array(void) { JsonElement *arr = JsonArrayCreate(10); JsonArrayAppendString(arr, "one"); JsonArrayAppendString(arr, "two"); JsonElement *obj = JsonObjectCreate(10); JsonObjectAppendArray(obj, "array", arr); JsonElement *arr2 = JsonObjectGetAsArray(obj, "array"); assert_string_equal(JsonArrayGetAsString(arr2, 1), "two"); JsonDestroy(obj); } static void test_object_iterator(void) { JsonElement *obj = JsonObjectCreate(10); JsonObjectAppendString(obj, "first", "one"); JsonObjectAppendString(obj, "second", "two"); JsonObjectAppendInteger(obj, "third", 3); JsonObjectAppendBool(obj, "fourth", true); JsonObjectAppendBool(obj, "fifth", false); { JsonIterator it = JsonIteratorInit(obj); assert_true(JsonIteratorHasMore(&it)); assert_string_equal("first", JsonIteratorNextKey(&it)); assert_string_equal("second", JsonIteratorNextKey(&it)); assert_string_equal("third", JsonIteratorNextKey(&it)); assert_string_equal("fourth", JsonIteratorNextKey(&it)); assert_true(JsonIteratorHasMore(&it)); assert_string_equal("fifth", JsonIteratorNextKey(&it)); assert_false(JsonIteratorHasMore(&it)); assert_false(JsonIteratorNextKey(&it)); } { JsonIterator it = JsonIteratorInit(obj); assert_true(JsonIteratorHasMore(&it)); assert_string_equal("one", JsonPrimitiveGetAsString(JsonIteratorNextValue(&it))); assert_string_equal("two", JsonPrimitiveGetAsString(JsonIteratorNextValue(&it))); assert_int_equal(3, JsonPrimitiveGetAsInteger(JsonIteratorNextValue(&it))); assert_true(JsonPrimitiveGetAsBool(JsonIteratorNextValue(&it))); assert_true(JsonIteratorHasMore(&it)); assert_false(JsonPrimitiveGetAsBool(JsonIteratorNextValue(&it))); assert_false(JsonIteratorHasMore(&it)); assert_false(JsonIteratorNextValue(&it)); } JsonDestroy(obj); } static void test_array_get_string(void) { JsonElement *arr = JsonArrayCreate(10); JsonArrayAppendString(arr, "first"); JsonArrayAppendString(arr, "second"); assert_string_equal(JsonArrayGetAsString(arr, 1), "second"); assert_string_equal(JsonArrayGetAsString(arr, 0), "first"); JsonDestroy(arr); } static void test_array_iterator(void) { JsonElement *arr = JsonArrayCreate(10); JsonArrayAppendString(arr, "first"); JsonArrayAppendString(arr, "second"); { JsonIterator it = JsonIteratorInit(arr); assert_true(JsonIteratorHasMore(&it)); assert_string_equal("first", JsonPrimitiveGetAsString(JsonIteratorNextValue(&it))); assert_true(JsonIteratorHasMore(&it)); assert_string_equal("second", JsonPrimitiveGetAsString(JsonIteratorNextValue(&it))); assert_false(JsonIteratorHasMore(&it)); assert_false(JsonIteratorNextValue(&it)); } JsonDestroy(arr); } static void test_copy_compare(void) { JsonElement *bench = LoadTestFile("benchmark.json"); assert_true(bench != NULL); JsonElement *copy = JsonCopy(bench); assert_true(copy != NULL); assert_int_equal(0, JsonCompare(copy, bench)); JsonDestroy(bench); JsonDestroy(copy); } static void test_select(void) { const char *data = OBJECT_ARRAY; JsonElement *obj = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj)); assert_true(obj == JsonSelect(obj, 0, NULL)); { char *indices[] = { "first" }; assert_int_equal(JSON_CONTAINER_TYPE_ARRAY, JsonGetContainerType(JsonSelect(obj, 1, indices))); } { char *indices[] = { "first", "0" }; assert_string_equal("one", JsonPrimitiveGetAsString(JsonSelect(obj, 2, indices))); } { char *indices[] = { "first", "1" }; assert_string_equal("two", JsonPrimitiveGetAsString(JsonSelect(obj, 2, indices))); } { char *indices[] = { "first", "2" }; assert_true(JsonSelect(obj, 2, indices) == NULL); } { char *indices[] = { "first", "x" }; assert_true(JsonSelect(obj, 2, indices) == NULL); } { char *indices[] = { "first", "0", "x" }; assert_true(JsonSelect(obj, 3, indices) == NULL); } { char *indices[] = { "second" }; assert_true(JsonSelect(obj, 1, indices) == NULL); } JsonDestroy(obj); } static void test_merge_array(void) { JsonElement *a = JsonArrayCreate(2); JsonArrayAppendString(a, "a"); JsonArrayAppendString(a, "b"); JsonElement *b = JsonArrayCreate(2); JsonArrayAppendString(b, "c"); JsonArrayAppendString(b, "d"); JsonElement *c = JsonMerge(a, b); assert_int_equal(2, JsonLength(a)); assert_int_equal(2, JsonLength(b)); assert_int_equal(4, JsonLength(c)); assert_string_equal("a", JsonArrayGetAsString(c, 0)); assert_string_equal("b", JsonArrayGetAsString(c, 1)); assert_string_equal("c", JsonArrayGetAsString(c, 2)); assert_string_equal("d", JsonArrayGetAsString(c, 3)); JsonDestroy(a); JsonDestroy(b); JsonDestroy(c); } static void test_merge_object(void) { JsonElement *a = JsonObjectCreate(2); JsonObjectAppendString(a, "a", "a"); JsonObjectAppendString(a, "b", "b"); JsonElement *b = JsonObjectCreate(2); JsonObjectAppendString(b, "b", "b"); JsonObjectAppendString(b, "c", "c"); JsonElement *c = JsonMerge(a, b); assert_int_equal(2, JsonLength(a)); assert_int_equal(2, JsonLength(b)); assert_int_equal(3, JsonLength(c)); assert_string_equal("a", JsonObjectGetAsString(c, "a")); assert_string_equal("b", JsonObjectGetAsString(c, "b")); assert_string_equal("c", JsonObjectGetAsString(c, "c")); JsonDestroy(a); JsonDestroy(b); JsonDestroy(c); } static void test_parse_empty_containers(void) { { const char *data = "{}"; JsonElement *obj = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj)); assert_true(obj != NULL); assert_int_equal(JSON_ELEMENT_TYPE_CONTAINER, JsonGetElementType(obj)); assert_int_equal(JSON_CONTAINER_TYPE_OBJECT, JsonGetContainerType(obj)); assert_int_equal(0, JsonLength(obj)); JsonDestroy(obj); } { const char *data = "[]"; JsonElement *arr = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &arr)); assert_true(arr != NULL); assert_int_equal(JSON_ELEMENT_TYPE_CONTAINER, JsonGetElementType(arr)); assert_int_equal(JSON_CONTAINER_TYPE_ARRAY, JsonGetContainerType(arr)); assert_int_equal(0, JsonLength(arr)); JsonDestroy(arr); } } static void test_parse_object_simple(void) { const char *data = OBJECT_SIMPLE; JsonElement *obj = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj)); assert_string_equal(JsonObjectGetAsString(obj, "second"), "two"); assert_string_equal(JsonObjectGetAsString(obj, "first"), "one"); assert_int_equal(JsonObjectGetAsString(obj, "third"), NULL); JsonDestroy(obj); } static void test_parse_object_escaped(void) { const char *decoded = "\"/var/cfenigne/bin/cf-know\" "; const char *json_string = "{\n \"key\": \"\\\"/var/cfenigne/bin/cf-know\\\" \"\n}"; JsonElement *obj = NULL; const char *data = json_string; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj)); assert_int_not_equal(obj, NULL); assert_string_equal(JsonObjectGetAsString(obj, "key"), decoded); { Writer *w = StringWriter(); JsonWrite(w, obj, 0); assert_string_equal(json_string, StringWriterData(w)); WriterClose(w); } JsonDestroy(obj); } static void test_parse_tzz_evil_key(void) { const char *data = "{ \"third key! can? be$ anything&\": [ \"a\", \"b\", \"c\" ]}"; JsonElement *obj = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj)); assert_string_equal("b", JsonArrayGetAsString(JsonObjectGetAsArray(obj, "third key! can? be$ anything&"), 1)); JsonDestroy(obj); } static void test_parse_primitives(void) { JsonElement *pri = NULL; const char *data = "\"foo\""; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &pri)); assert_string_equal("foo", JsonPrimitiveGetAsString(pri)); JsonDestroy(pri); data = "-123"; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &pri)); assert_true(-123 == JsonPrimitiveGetAsInteger(pri)); JsonDestroy(pri); data = "1.23"; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &pri)); assert_double_close(1.23, JsonPrimitiveGetAsReal(pri)); JsonDestroy(pri); data = "true"; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &pri)); assert_true(JsonPrimitiveGetAsBool(pri)); JsonDestroy(pri); } static void test_parse_array_simple(void) { const char *data = ARRAY_SIMPLE; JsonElement *arr = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &arr)); assert_string_equal(JsonArrayGetAsString(arr, 1), "two"); assert_string_equal(JsonArrayGetAsString(arr, 0), "one"); JsonDestroy(arr); } static void test_parse_object_compound(void) { const char *data = OBJECT_COMPOUND; JsonElement *obj = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj)); assert_string_equal(JsonObjectGetAsString(obj, "first"), "one"); JsonElement *second = JsonObjectGetAsObject(obj, "second"); assert_string_equal(JsonObjectGetAsString(second, "third"), "three"); JsonElement *fourth = JsonObjectGetAsObject(obj, "fourth"); assert_string_equal(JsonObjectGetAsString(fourth, "fifth"), "five"); JsonDestroy(obj); } static void test_parse_object_diverse(void) { { const char *data = "{ \"a\": 1, \"b\": \"snookie\", \"c\": 1.0, \"d\": {}, \"e\": [], \"f\": true, \"g\": false, \"h\": null }"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "{\"a\":1,\"b\":\"snookie\",\"c\":1.0,\"d\":{},\"e\":[],\"f\":true,\"g\":false,\"h\":null}"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } } static void test_parse_array_object(void) { const char *data = ARRAY_OBJECT; JsonElement *arr = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &arr)); JsonElement *first = JsonArrayGetAsObject(arr, 0); assert_string_equal(JsonObjectGetAsString(first, "first"), "one"); JsonDestroy(arr); } static void test_iterator_current(void) { const char *data = ARRAY_SIMPLE; JsonElement *arr = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &arr)); JsonElement *json = JsonObjectCreate(1); JsonObjectAppendArray(json, "array", arr); JsonIterator it = JsonIteratorInit(json); while (JsonIteratorNextValue(&it) != NULL) { assert_int_equal((int)JsonIteratorCurrentElementType(&it), (int)JSON_ELEMENT_TYPE_CONTAINER); assert_int_equal((int)JsonIteratorCurrentContainerType(&it), (int)JSON_CONTAINER_TYPE_ARRAY); assert_string_equal(JsonIteratorCurrentKey(&it), "array"); } JsonDestroy(json); } static void test_parse_empty_string(void) { const char *data = ""; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); data = "\"\""; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_string_equal("", JsonPrimitiveGetAsString(json)); JsonDestroy(json); } static char *JsonToString(const JsonElement *json) { Writer *w = StringWriter(); JsonWriteCompact(w, json); return StringWriterClose(w); } static void test_parse_escaped_string(void) { { const char *data = "\"\\\\\""; const char *original = data; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_string_equal("\\", JsonPrimitiveGetAsString(json)); char *out = JsonToString(json); assert_string_equal(original, out); free(out); JsonDestroy(json); } { // included by paranoia from Redmine #5773 const char *data = "\"/\\\\//\\\\/\\\\\""; const char *original = data; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_string_equal("/\\//\\/\\", JsonPrimitiveGetAsString(json)); char *out = JsonToString(json); assert_string_equal(original, out); free(out); JsonDestroy(json); } { const char *data = "\"x\\tx\""; const char *original = data; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_string_equal("x\tx", JsonPrimitiveGetAsString(json)); char *out = JsonToString(json); assert_string_equal(original, out); free(out); JsonDestroy(json); } } static void test_parse_good_numbers(void) { { const char *data = "[0.1]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[0.1234567890123456789]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[0.1234e10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[0.1234e+10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[0.1234e-10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[1203e10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[1203e+10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[123e-10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[0e-10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[0.0e-10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[-0.0e-10]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } } static void test_parse_bad_numbers(void) { { const char *data = "[01]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[01.1]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[1.]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[e10]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[-e10]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[+2]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[1e]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } { const char *data = "[e10]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); } } static void test_parse_trim(void) { const char *data = " [] "; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } static void test_parse_array_extra_closing(void) { const char *data = " []]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } static void test_parse_array_diverse(void) { { const char *data = "[1, \"snookie\", 1.0, {}, [], true, false, null ]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } { const char *data = "[1,\"snookie\",1.0,{},[],true,false,null]"; JsonElement *json = NULL; assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_true(json); JsonDestroy(json); } } static void test_parse_bad_apple2(void) { const char *data = "]["; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } static void test_parse_object_garbage(void) { { const char *data = "{ \"first\": 1, garbage \"second\": 2 }"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "{ \"first\": 1 garbage \"second\": 2 }"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "{ \"first\": garbage, \"second\": 2 }"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "{ \"first\": garbage \"second\": 2 }"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } } static void test_parse_object_nested_garbage(void) { { const char *data = "{ \"first\": { garbage } }"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "{ \"first\": [ garbage ] }"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } } static void test_parse_array_garbage(void) { { const char *data = "[1, garbage]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "[1 garbage]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "[garbage]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "[garbage, 1]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } } static void test_parse_array_nested_garbage(void) { { const char *data = "[1, [garbage]]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } { const char *data = "[1, { garbage }]"; JsonElement *json = NULL; assert_int_not_equal(JSON_PARSE_OK, JsonParse(&data, &json)); assert_false(json); } } static void test_array_remove_range(void) { { // remove whole JsonElement *arr = JsonArrayCreate(5); JsonArrayAppendString(arr, "one"); JsonArrayAppendString(arr, "two"); JsonArrayAppendString(arr, "three"); JsonArrayRemoveRange(arr, 0, 2); assert_int_equal(JsonLength(arr), 0); JsonDestroy(arr); } { // remove middle JsonElement *arr = JsonArrayCreate(5); JsonArrayAppendString(arr, "one"); JsonArrayAppendString(arr, "two"); JsonArrayAppendString(arr, "three"); JsonArrayRemoveRange(arr, 1, 1); assert_int_equal(JsonLength(arr), 2); assert_string_equal(JsonArrayGetAsString(arr, 0), "one"); assert_string_equal(JsonArrayGetAsString(arr, 1), "three"); JsonDestroy(arr); } { // remove rest JsonElement *arr = JsonArrayCreate(5); JsonArrayAppendString(arr, "one"); JsonArrayAppendString(arr, "two"); JsonArrayAppendString(arr, "three"); JsonArrayRemoveRange(arr, 1, 2); assert_int_equal(JsonLength(arr), 1); assert_string_equal(JsonArrayGetAsString(arr, 0), "one"); JsonDestroy(arr); } { // remove but last JsonElement *arr = JsonArrayCreate(5); JsonArrayAppendString(arr, "one"); JsonArrayAppendString(arr, "two"); JsonArrayAppendString(arr, "three"); JsonArrayRemoveRange(arr, 0, 1); assert_int_equal(JsonLength(arr), 1); assert_string_equal(JsonArrayGetAsString(arr, 0), "three"); JsonDestroy(arr); } } static void test_remove_key_from_object(void) { JsonElement *object = JsonObjectCreate(3); JsonObjectAppendInteger(object, "one", 1); JsonObjectAppendInteger(object, "two", 2); JsonObjectAppendInteger(object, "three", 3); JsonObjectRemoveKey(object, "two"); assert_int_equal(2, JsonLength(object)); JsonDestroy(object); } static void test_detach_key_from_object(void) { JsonElement *object = JsonObjectCreate(3); JsonObjectAppendInteger(object, "one", 1); JsonObjectAppendInteger(object, "two", 2); JsonObjectAppendInteger(object, "three", 3); JsonElement *detached = JsonObjectDetachKey(object, "two"); assert_int_equal(2, JsonLength(object)); JsonDestroy(object); assert_int_equal(1, JsonLength(detached)); JsonDestroy(detached); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_new_delete), unit_test(test_object_duplicate_key), unit_test(test_show_string), unit_test(test_show_object_simple), unit_test(test_show_object_escaped), unit_test(test_show_object_numeric), unit_test(test_show_object_boolean), unit_test(test_show_object_compound), unit_test(test_show_object_compound_compact), unit_test(test_show_object_array), unit_test(test_show_array), unit_test(test_show_array_compact), unit_test(test_show_array_boolean), unit_test(test_show_array_numeric), unit_test(test_show_array_object), unit_test(test_show_array_empty), unit_test(test_show_array_nan), unit_test(test_show_array_infinity), unit_test(test_object_get_string), unit_test(test_object_get_array), unit_test(test_object_iterator), unit_test(test_iterator_current), unit_test(test_array_get_string), unit_test(test_array_iterator), unit_test(test_copy_compare), unit_test(test_select), unit_test(test_merge_array), unit_test(test_merge_object), unit_test(test_parse_empty_string), unit_test(test_parse_escaped_string), unit_test(test_parse_empty_containers), unit_test(test_parse_object_simple), unit_test(test_parse_array_simple), unit_test(test_parse_object_compound), unit_test(test_parse_object_diverse), unit_test(test_parse_array_object), unit_test(test_parse_good_numbers), unit_test(test_parse_bad_numbers), unit_test(test_parse_trim), unit_test(test_parse_array_extra_closing), unit_test(test_parse_array_diverse), unit_test(test_parse_bad_apple2), unit_test(test_parse_object_garbage), unit_test(test_parse_object_nested_garbage), unit_test(test_parse_array_garbage), unit_test(test_parse_array_nested_garbage), unit_test(test_parse_object_escaped), unit_test(test_parse_tzz_evil_key), unit_test(test_parse_primitives), unit_test(test_array_remove_range), unit_test(test_remove_key_from_object), unit_test(test_detach_key_from_object), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/dbm_migration_bundles_test.c0000664000175100017510000001004212400110676022663 0ustar00a10038a1003800000000000000#include #include #include #include #include /* xsnprintf */ char CFWORKDIR[CF_BUFSIZE]; static void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/persistent_lock_test.XXXXXX"); mkdtemp(CFWORKDIR); } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } static const Event dummy_event = { .t = 1, .Q = { 2.0, 3.0, 4.0, 5.0 } }; /* * Provides empty lastseen DB */ static DBHandle *setup(bool clean) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'/*", CFWORKDIR); system(cmd); DBHandle *db; OpenDB(&db, dbid_bundles); if (clean) { /* There is no way to disable hook in OpenDB yet, so just undo * everything */ DBCursor *cursor; if (!NewDBCursor(db, &cursor)) { return NULL; } char *key; void *value; int ksize, vsize; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { DBCursorDeleteEntry(cursor); } if (!DeleteDBCursor(cursor)) { return NULL; } } return db; } static void test_no_migration(void) { DBHandle *db = setup(true); CloseDB(db); /* Migration on empty DB should produce single "version" key */ assert_int_equal(OpenDB(&db, dbid_lastseen), true); DBCursor *cursor; assert_int_equal(NewDBCursor(db, &cursor), true); char *key; void *value; int ksize, vsize; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { assert_int_equal(ksize, strlen("version") + 1); assert_string_equal(key, "version"); assert_int_equal(vsize, 2); assert_string_equal(value, "1"); } assert_int_equal(DeleteDBCursor(cursor), true); CloseDB(db); } static void test_up_to_date(void) { /* Test that upgrade is not performed if there is already a version * marker */ DBHandle *db = setup(false); assert_int_equal(WriteDB(db, "foo", &dummy_event, sizeof(dummy_event)), true); CloseDB(db); /* Test that manually inserted key still has unqalified name the next time the DB is opened, which is an indicator of the DB not being upgraded */ assert_int_equal(OpenDB(&db, dbid_bundles), true); Event read_value; assert_int_equal(ReadDB(db, "foo", &read_value, sizeof(read_value)), true); assert_int_equal(read_value.t, 1); CloseDB(db); } void test_migrate_unqualified_names(void) { DBHandle *db = setup(true); assert_int_equal(WriteDB(db, "foo", &dummy_event, sizeof(dummy_event)), true); assert_int_equal(WriteDB(db, "q.bar", &dummy_event, sizeof(dummy_event)), true); CloseDB(db); assert_int_equal(OpenDB(&db, dbid_bundles), true); /* Old entry migrated */ assert_int_equal(HasKeyDB(db, "foo", strlen("foo") + 1), false); assert_int_equal(HasKeyDB(db, "default.foo", strlen("default.foo") + 1), true); Event read_value = { 0 }; ReadDB(db, "default.foo", &read_value, sizeof(read_value)); assert_memory_equal(&read_value, &dummy_event, sizeof(dummy_event)); /* New entry preserved */ assert_int_equal(HasKeyDB(db, "q.bar", strlen("q.bar") + 1), true); memset(&read_value, 0, sizeof(read_value)); ReadDB(db, "q.bar", &read_value, sizeof(read_value)); assert_memory_equal(&read_value, &dummy_event, sizeof(dummy_event)); /* Version marker */ assert_int_equal(HasKeyDB(db, "version", strlen("version") + 1), true); CloseDB(db); } int main() { #ifdef LMDB return 0; #else tests_setup(); const UnitTest tests[] = { unit_test(test_no_migration), unit_test(test_up_to_date), unit_test(test_migrate_unqualified_names), }; PRINT_TEST_BANNER(); int ret = run_tests(tests); tests_teardown(); return ret; #endif } /* STUBS */ void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } cfengine-3.6.2/tests/unit/avahi_config_test.c0000644000175100017510000000316312316547775021001 0ustar00a10038a1003800000000000000#include #include #include #include static void generateTestFile() { FILE *fp = fopen("/tmp/test_file", "w+"); assert_int_not_equal(fp, NULL); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); FprintAvahiCfengineTag(fp); fprintf(fp, "\n"); fprintf(fp, "_cfenginehub._tcp\n"); DetermineCfenginePort(); fprintf(fp, "\n"); fprintf(fp, "5308\n"); fprintf(fp, "\n"); fprintf(fp, "\n"); fclose(fp); } static void test_generateAvahiConfig(void) { generateTestFile(); assert_int_equal(GenerateAvahiConfig("/tmp/avahi_config"), 0); FILE *testfile = fopen("/tmp/test_file", "r+"); assert_int_not_equal(testfile, NULL); FILE *optfile = fopen("/tmp/avahi_config", "r+"); assert_int_not_equal(optfile, NULL); char buffer1[256], buffer2[256]; while (!feof(testfile) && !feof(optfile)) { memset(buffer1, 0, sizeof(buffer1)); memset(buffer2, 0, sizeof(buffer2)); fgets(buffer1, sizeof(buffer1), testfile); fgets(buffer2, sizeof(buffer2), optfile); assert_int_equal(strcmp(buffer1, buffer2), 0); } fclose(testfile); fclose(optfile); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_generateAvahiConfig) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/test.c0000664000175100017510000000214012400110676016254 0ustar00a10038a1003800000000000000#include #include #include #include #include char *file_read_string(FILE *in) { fpos_t pos; long size; char *buffer; assert_int_equal(fgetpos(in, &pos), 0); assert_int_equal(fseek(in, 0, SEEK_END), 0); size = ftell(in); assert_true(size >= 0); assert_int_equal(fseek(in, 0, SEEK_SET), 0); buffer = xcalloc(size + 1L, sizeof(char)); assert_int_equal(fread(buffer, 1, size, in), size); assert_int_equal(fsetpos(in, &pos), 0); return buffer; } void assert_file_equal(FILE *a, FILE *b) { char *a_buffer = file_read_string(a); char *b_buffer = file_read_string(b); if (strcmp(a_buffer, b_buffer) != 0) { printf("\n=====\n%s != \n=====\n%s\n", a_buffer, b_buffer); fail(); } free(a_buffer); free(b_buffer); } #define SMALL_DIFF 1e-14 void _assert_double_close(double left, double right, const char *const file, const int line) { if (fabs(left - right) > SMALL_DIFF) { print_error("%f != %f (+- 1e-14)\n", left, right); _fail(file, line); } } cfengine-3.6.2/tests/unit/cmockery.h0000664000175100017510000005315112400110676017126 0ustar00a10038a1003800000000000000/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CMOCKERY_H_ # define CMOCKERY_H_ /* * These headers or their equivalents should be included prior to including * this header file. * * #include * #include * #include * * This allows test applications to use custom definitions of C standard * library functions and types. */ # if defined(__GNUC__) && (__GNUC__ * 100 >= 3) # define FUNC_ATTR_NORETURN __attribute__((noreturn)) # else/* not gcc >= 3.0 */ # define FUNC_ATTR_NORETURN # endif // For those who are used to __func__ from gcc. # ifndef __func__ # define __func__ __FUNCTION__ # endif /* Largest integral type. This type should be large enough to hold any * pointer or integer supported by the compiler. */ # ifndef LargestIntegralType # define LargestIntegralType unsigned long long # endif// LargestIntegralType // Printf format used to display LargestIntegralType. # ifndef LargestIntegralTypePrintfFormat # ifdef _WIN32 # define LargestIntegralTypePrintfFormat "%I64x" # define LargestIntegralTypePrintfDecimal "%I64d" # else # define LargestIntegralTypePrintfFormat "%llx" # define LargestIntegralTypePrintfDecimal "%lld" # endif // _WIN32 # endif// LargestIntegralTypePrintfFormat // Perform an unsigned cast to LargestIntegralType. # define cast_to_largest_integral_type(value) \ _cast_to_largest_integral_type(sizeof(value), value) // Retrieves a return value for the current function. # define mock() _mock(__func__, __FILE__, __LINE__) /* Stores a value to be returned by the specified function later. * The count parameter returns the number of times the value should be returned * by mock(). If count is set to -1 the value will always be returned. */ # define will_return(function, value) \ _will_return(#function, __FILE__, __LINE__, \ cast_to_largest_integral_type(value), 1) # define will_return_count(function, value, count) \ _will_return(#function, __FILE__, __LINE__, \ cast_to_largest_integral_type(value), count) /* Add a custom parameter checking function. If the event parameter is NULL * the event structure is allocated internally by this function. If event * parameter is provided it must be allocated on the heap and doesn't need to * be deallocated by the caller. */ # define expect_check(function, parameter, check_function, check_data) \ _expect_check(#function, #parameter, __FILE__, __LINE__, check_function, \ cast_to_largest_integral_type(check_data), NULL, 0) /* Add an event to check a parameter, using check_expected(), against a set of * values. See will_return() for a description of the count parameter. */ # define expect_in_set(function, parameter, value_array) \ expect_in_set_count(function, parameter, value_array, 1) # define expect_in_set_count(function, parameter, value_array, count) \ _expect_in_set(#function, #parameter, __FILE__, __LINE__, value_array, \ sizeof(value_array) / sizeof((value_array)[0]), count) # define expect_not_in_set(function, parameter, value_array) \ expect_not_in_set_count(function, parameter, value_array, 1) # define expect_not_in_set_count(function, parameter, value_array, count) \ _expect_not_in_set( \ #function, #parameter, __FILE__, __LINE__, value_array, \ sizeof(value_array) / sizeof((value_array)[0]), count) /* Add an event to check a parameter, using check_expected(), against a * signed range. Where range is minimum <= value <= maximum. * See will_return() for a description of the count parameter. */ # define expect_in_range(function, parameter, minimum, maximum) \ expect_in_range_count(function, parameter, minimum, maximum, 1) # define expect_in_range_count(function, parameter, minimum, maximum, count) \ _expect_in_range(#function, #parameter, __FILE__, __LINE__, minimum, \ maximum, count) /* Add an event to check a parameter, using check_expected(), against a * signed range. Where range is value < minimum or value > maximum. * See will_return() for a description of the count parameter. */ # define expect_not_in_range(function, parameter, minimum, maximum) \ expect_not_in_range_count(function, parameter, minimum, maximum, 1) # define expect_not_in_range_count(function, parameter, minimum, maximum, \ count) \ _expect_not_in_range(#function, #parameter, __FILE__, __LINE__, \ minimum, maximum, count) /* Add an event to check whether a parameter, using check_expected(), is or * isn't a value. See will_return() for a description of the count parameter. */ # define expect_value(function, parameter, value) \ expect_value_count(function, parameter, value, 1) # define expect_value_count(function, parameter, value, count) \ _expect_value(#function, #parameter, __FILE__, __LINE__, \ cast_to_largest_integral_type(value), count) # define expect_not_value(function, parameter, value) \ expect_not_value_count(function, parameter, value, 1) # define expect_not_value_count(function, parameter, value, count) \ _expect_not_value(#function, #parameter, __FILE__, __LINE__, \ cast_to_largest_integral_type(value), count) /* Add an event to check whether a parameter, using check_expected(), * is or isn't a string. See will_return() for a description of the count * parameter. */ # define expect_string(function, parameter, string) \ expect_string_count(function, parameter, string, 1) # define expect_string_count(function, parameter, string, count) \ _expect_string(#function, #parameter, __FILE__, __LINE__, \ (const char*)(string), count) # define expect_not_string(function, parameter, string) \ expect_not_string_count(function, parameter, string, 1) # define expect_not_string_count(function, parameter, string, count) \ _expect_not_string(#function, #parameter, __FILE__, __LINE__, \ (const char*)(string), count) /* Add an event to check whether a parameter, using check_expected() does or * doesn't match an area of memory. See will_return() for a description of * the count parameter. */ # define expect_memory(function, parameter, memory, size) \ expect_memory_count(function, parameter, memory, size, 1) # define expect_memory_count(function, parameter, memory, size, count) \ _expect_memory(#function, #parameter, __FILE__, __LINE__, \ (const void*)(memory), size, count) # define expect_not_memory(function, parameter, memory, size) \ expect_not_memory_count(function, parameter, memory, size, 1) # define expect_not_memory_count(function, parameter, memory, size, count) \ _expect_not_memory(#function, #parameter, __FILE__, __LINE__, \ (const void*)(memory), size, count) /* Add an event to allow any value for a parameter checked using * check_expected(). See will_return() for a description of the count * parameter. */ # define expect_any(function, parameter) \ expect_any_count(function, parameter, 1) # define expect_any_count(function, parameter, count) \ _expect_any(#function, #parameter, __FILE__, __LINE__, count) /* Determine whether a function parameter is correct. This ensures the next * value queued by one of the expect_*() macros matches the specified variable. */ # define check_expected(parameter) \ _check_expected(__func__, #parameter, __FILE__, __LINE__, \ cast_to_largest_integral_type(parameter)) // Assert that the given expression is true. # define assert_true(c) _assert_true(cast_to_largest_integral_type(c), #c, \ __FILE__, __LINE__) // Assert that the given expression is false. # define assert_false(c) _assert_true(!(cast_to_largest_integral_type(c)), #c, \ __FILE__, __LINE__) // Assert that the two given integers are equal, otherwise fail. # define assert_int_equal(a, b) \ _assert_int_equal(cast_to_largest_integral_type(a), \ cast_to_largest_integral_type(b), \ __FILE__, __LINE__) // Assert that the two given integers are not equal, otherwise fail. # define assert_int_not_equal(a, b) \ _assert_int_not_equal(cast_to_largest_integral_type(a), \ cast_to_largest_integral_type(b), \ __FILE__, __LINE__) // Assert that the two given strings are equal, otherwise fail. # define assert_string_equal(a, b) \ _assert_string_equal((const char*)(a), (const char*)(b), __FILE__, \ __LINE__) // Assert that the two given strings are not equal, otherwise fail. # define assert_string_not_equal(a, b) \ _assert_string_not_equal((const char*)(a), (const char*)(b), __FILE__, \ __LINE__) // Assert that the two given areas of memory are equal, otherwise fail. # define assert_memory_equal(a, b, size) \ _assert_memory_equal((const char*)(a), (const char*)(b), size, __FILE__, \ __LINE__) // Assert that the two given areas of memory are not equal, otherwise fail. # define assert_memory_not_equal(a, b, size) \ _assert_memory_not_equal((const char*)(a), (const char*)(b), size, \ __FILE__, __LINE__) // Assert that the specified value is >= minimum and <= maximum. # define assert_in_range(value, minimum, maximum) \ _assert_in_range( \ cast_to_largest_integral_type(value), \ cast_to_largest_integral_type(minimum), \ cast_to_largest_integral_type(maximum), __FILE__, __LINE__) // Assert that the specified value is < minumum or > maximum # define assert_not_in_range(value, minimum, maximum) \ _assert_not_in_range( \ cast_to_largest_integral_type(value), \ cast_to_largest_integral_type(minimum), \ cast_to_largest_integral_type(maximum), __FILE__, __LINE__) // Assert that the specified value is within a set. # define assert_in_set(value, values, number_of_values) \ _assert_in_set(value, values, number_of_values, __FILE__, __LINE__) // Assert that the specified value is not within a set. # define assert_not_in_set(value, values, number_of_values) \ _assert_not_in_set(value, values, number_of_values, __FILE__, __LINE__) // Forces the test to fail immediately and quit. # define fail() _fail(__FILE__, __LINE__) // Generic method to kick off testing # define run_test(f) _run_test(#f, f, NULL, UNIT_TEST_FUNCTION_TYPE_TEST, NULL) // Initializes a UnitTest structure. # define unit_test(func) { .name = #func, .f = { .function = func }, .function_type = UNIT_TEST_FUNCTION_TYPE_TEST } # define unit_test_with_state(func) { .name = #func, .f = { .function_with_state = func }, .function_type = UNIT_TEST_FUNCTION_TYPE_TEST_WITH_STATE } # define unit_test_setup(test, setup) \ { .name = #test "_" #setup, .f = { .function_with_state = setup }, .function_type = UNIT_TEST_FUNCTION_TYPE_SETUP } # define unit_test_teardown(test, teardown) \ { .name = #test "_" #teardown, .f = { .function_with_state = teardown }, .function_type = UNIT_TEST_FUNCTION_TYPE_TEARDOWN } /* Initialize an array of UnitTest structures with a setup function for a test * and a teardown function. Either setup or teardown can be NULL. */ # define unit_test_setup_teardown(test, setup, teardown) \ unit_test_setup(test, setup), \ unit_test_with_state(test), \ unit_test_teardown(test, teardown) /* * Run tests specified by an array of UnitTest structures. The following * example illustrates this macro's use with the unit_test macro. * * void Test0(); * void Test1(); * * int main(int argc, char* argv[]) { * const UnitTest tests[] = { * unit_test(Test0); * unit_test(Test1); * }; * return run_tests(tests); * } */ # define run_tests(tests) _run_tests(tests, sizeof(tests) / sizeof(tests)[0], __FILE__) // Dynamic allocators # define test_malloc(size) _test_malloc(size, __FILE__, __LINE__) # define test_calloc(num, size) _test_calloc(num, size, __FILE__, __LINE__) # define test_free(ptr) _test_free(ptr, __FILE__, __LINE__) // Redirect malloc, calloc and free to the unit test allocators. # if UNIT_TESTING # define malloc test_malloc # define calloc test_calloc # define free test_free # endif// UNIT_TESTING /* * Ensure mock_assert() is called. If mock_assert() is called the assert * expression string is returned. * For example: * * #define assert mock_assert * * void showmessage(const char *message) { * assert(message); * } * * int main(int argc, const char* argv[]) { * expect_assert_failure(show_message(NULL)); * printf("succeeded\n"); * return 0; * } */ # define expect_assert_failure(function_call) \ { \ const int has_expression = setjmp(global_expect_assert_env); \ global_expecting_assert = 1; \ if (has_expression) { \ print_message("Expected assertion %s occurred\n", \ global_expect_assert_expression); \ global_expecting_assert = 0; \ } else { \ function_call ; \ global_expecting_assert = 0; \ print_error("Expected assert in %s\n", #function_call); \ _fail(__FILE__, __LINE__); \ } \ } // Function prototype for setup, test and teardown functions. typedef void (*UnitTestFunction) (void); typedef void (*UnitTestFunctionWithState) (void **state); // Function that determines whether a function parameter value is correct. typedef int (*CheckParameterValue) (const LargestIntegralType value, const LargestIntegralType check_value_data); // Type of the unit test function. typedef enum UnitTestFunctionType { UNIT_TEST_FUNCTION_TYPE_TEST = 0, UNIT_TEST_FUNCTION_TYPE_TEST_WITH_STATE, UNIT_TEST_FUNCTION_TYPE_SETUP, UNIT_TEST_FUNCTION_TYPE_TEARDOWN, } UnitTestFunctionType; /* Stores a unit test function with its name and type. * NOTE: Every setup function must be paired with a teardown function. It's * possible to specify NULL function pointers. */ typedef struct UnitTest { const char *name; union { UnitTestFunction function; UnitTestFunctionWithState function_with_state; } f; UnitTestFunctionType function_type; } UnitTest; // Location within some source code. typedef struct SourceLocation { const char *file; int line; } SourceLocation; // Event that's called to check a parameter value. typedef struct CheckParameterEvent { SourceLocation location; const char *parameter_name; CheckParameterValue check_value; LargestIntegralType check_value_data; } CheckParameterEvent; // Used by expect_assert_failure() and mock_assert(). extern int global_expecting_assert; extern const char *global_expect_assert_expression; extern jmp_buf global_expect_assert_env; LargestIntegralType _cast_to_largest_integral_type(size_t size, ...); // Retrieves a value for the given function, as set by "will_return". LargestIntegralType _mock(const char *const function, const char *const file, const int line); void _expect_check(const char *const function, const char *const parameter, const char *const file, const int line, const CheckParameterValue check_function, const LargestIntegralType check_data, CheckParameterEvent *const event, const int count); void _expect_in_set(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType values[], const size_t number_of_values, const int count); void _expect_not_in_set(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType values[], const size_t number_of_values, const int count); void _expect_in_range(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType minimum, const LargestIntegralType maximum, const int count); void _expect_not_in_range(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType minimum, const LargestIntegralType maximum, const int count); void _expect_value(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType value, const int count); void _expect_not_value(const char *const function, const char *const parameter, const char *const file, const int line, const LargestIntegralType value, const int count); void _expect_string(const char *const function, const char *const parameter, const char *const file, const int line, const char *string, const int count); void _expect_not_string(const char *const function, const char *const parameter, const char *const file, const int line, const char *string, const int count); void _expect_memory(const char *const function, const char *const parameter, const char *const file, const int line, const void *const memory, const size_t size, const int count); void _expect_not_memory(const char *const function, const char *const parameter, const char *const file, const int line, const void *const memory, const size_t size, const int count); void _expect_any(const char *const function, const char *const parameter, const char *const file, const int line, const int count); void _check_expected(const char *const function_name, const char *const parameter_name, const char *file, const int line, const LargestIntegralType value); // Can be used to replace assert in tested code so that in conjuction with // check_assert() it's possible to determine whether an assert condition has // failed without stopping a test. void mock_assert(const int result, const char *const expression, const char *const file, const int line); void _will_return(const char *const function_name, const char *const file, const int line, const LargestIntegralType value, const int count); void _assert_true(const LargestIntegralType result, const char *const expression, const char *const file, const int line); void _assert_int_equal(const LargestIntegralType a, const LargestIntegralType b, const char *const file, const int line); void _assert_int_not_equal(const LargestIntegralType a, const LargestIntegralType b, const char *const file, const int line); void _assert_string_equal(const char *const a, const char *const b, const char *const file, const int line); void _assert_string_not_equal(const char *const a, const char *const b, const char *file, const int line); void _assert_memory_equal(const void *const a, const void *const b, const size_t size, const char *const file, const int line); void _assert_memory_not_equal(const void *const a, const void *const b, const size_t size, const char *const file, const int line); void _assert_in_range(const LargestIntegralType value, const LargestIntegralType minimum, const LargestIntegralType maximum, const char *const file, const int line); void _assert_not_in_range(const LargestIntegralType value, const LargestIntegralType minimum, const LargestIntegralType maximum, const char *const file, const int line); void _assert_in_set(const LargestIntegralType value, const LargestIntegralType values[], const size_t number_of_values, const char *const file, const int line); void _assert_not_in_set(const LargestIntegralType value, const LargestIntegralType values[], const size_t number_of_values, const char *const file, const int line); void *_test_malloc(const size_t size, const char *file, const int line); void *_test_calloc(const size_t number_of_elements, const size_t size, const char *file, const int line); void _test_free(void *const ptr, const char *file, const int line); void _fail(const char *const file, const int line) FUNC_ATTR_NORETURN; int _run_test(const char *const function_name, const UnitTestFunction Function, void **const state, const UnitTestFunctionType function_type, const void *const heap_check_point); int _run_tests(const UnitTest *const tests, const size_t number_of_tests, const char *const file); // XML init and output void vinit_xml (const char *const format, va_list args); void vprint_xml(const char *const format, va_list args); void init_xml (const char *const format, ...); void print_xml(const char *const format, ...); void vinit_cunit_run_files (const char *const file, const char *const format, va_list args); void init_cunit_run_files (const char *const file, const char *const format, ...); void append_xml_tmp(const char *ofile, const char *ifile); // Standard output and error print methods. void print_message(const char *const format, ...); void print_error(const char *const format, ...); void vprint_message(const char *const format, va_list args); void vprint_error(const char *const format, va_list args); #endif cfengine-3.6.2/tests/unit/package_versions_compare_test.c0000664000175100017510000002212712400110676023374 0ustar00a10038a1003800000000000000#include #include #include #include void test_different_name(void) { EvalContext *ctx = EvalContextNew(); PromiseResult result; PackageItem pi = { .name = "pkgone", .version = "1", .arch = "arch" }; Attributes attr = { .packages = { .package_select = PACKAGE_VERSION_COMPARATOR_EQ } }; assert_int_equal(ComparePackages(ctx, "pkgtwo", "1", "arch", &pi, attr, NULL, "test", &result), VERCMP_NO_MATCH); EvalContextDestroy(ctx); } void test_wildcard_arch(void) { EvalContext *ctx = EvalContextNew(); PromiseResult result; PackageItem pi = { .name = "foobar", .version = "1", .arch = "arch" }; Attributes attr = { .packages = { .package_select = PACKAGE_VERSION_COMPARATOR_EQ } }; assert_int_equal(ComparePackages(ctx, "foobar", "1", "*", &pi, attr, NULL, "test", &result), VERCMP_MATCH); EvalContextDestroy(ctx); } void test_non_matching_arch(void) { EvalContext *ctx = EvalContextNew(); PromiseResult result; PackageItem pi = { .name = "foobar", .version = "1", .arch = "s390x" }; Attributes attr = { .packages = { .package_select = PACKAGE_VERSION_COMPARATOR_EQ } }; assert_int_equal(ComparePackages(ctx, "foobar", "1", "s390", &pi, attr, NULL, "test", &result), VERCMP_NO_MATCH); EvalContextDestroy(ctx); } VersionCmpResult DoCompare(const char *lhs, const char *rhs, PackageVersionComparator cmp) { EvalContext *ctx = EvalContextNew(); PromiseResult result; PackageItem pi = { .name = "foobar", .version = (char*)lhs, .arch = "somearch" }; Attributes a = { .packages = { .package_select = cmp, } }; VersionCmpResult cmp_result = ComparePackages(ctx, "foobar", rhs, "somearch", &pi, a, NULL, "test", &result); EvalContextDestroy(ctx); return cmp_result; } void test_wildcard_version(void) { assert_int_equal(DoCompare("1.0-1", "*", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_MATCH); } void test_eq(void) { assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_NONE), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-2", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_NO_MATCH); } void test_ne(void) { assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_NEQ), VERCMP_NO_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-2", PACKAGE_VERSION_COMPARATOR_NEQ), VERCMP_MATCH); } void test_gt_lt(void) { assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_NO_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-2", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_NO_MATCH); assert_int_equal(DoCompare("1.0-2", "1.0-1", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_NO_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-2", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-2", "1.0-1", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_NO_MATCH); } void test_gte_lte(void) { assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-2", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_NO_MATCH); assert_int_equal(DoCompare("1.0-2", "1.0-1", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-1", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-1", "1.0-2", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_MATCH); assert_int_equal(DoCompare("1.0-2", "1.0-1", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_NO_MATCH); } void wrong_separators(void) { assert_int_equal(DoCompare("1.0", "1,0", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_ERROR); } void uneven_lengths_1(void) { assert_int_equal(DoCompare("1.0.1", "1.0", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_NO_MATCH); } void uneven_lengths_2(void) { assert_int_equal(DoCompare("1.0.1", "1.0", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_MATCH); } void uneven_lengths_3(void) { assert_int_equal(DoCompare("1.0.1", "1.0", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_NO_MATCH); } void uneven_lengths_4(void) { assert_int_equal(DoCompare("1.0.1", "1.0", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_MATCH); } void uneven_lengths_5(void) { assert_int_equal(DoCompare("1.0.1", "1.0", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_NO_MATCH); } void uneven_lengths_6(void) { assert_int_equal(DoCompare("1.0", "1.0.1", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_NO_MATCH); } void uneven_lengths_7(void) { assert_int_equal(DoCompare("1.0", "1.0.1", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_NO_MATCH); } void uneven_lengths_8(void) { assert_int_equal(DoCompare("1.0", "1.0.1", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_MATCH); } void uneven_lengths_9(void) { assert_int_equal(DoCompare("1.0", "1.0.1", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_NO_MATCH); } void uneven_lengths_10(void) { assert_int_equal(DoCompare("1.0", "1.0.1", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_MATCH); } void uneven_lengths_11(void) { assert_int_equal(DoCompare("1.0-1", "1.0", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_NO_MATCH); } void uneven_lengths_12(void) { assert_int_equal(DoCompare("1.0-1", "1.0", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_MATCH); } void uneven_lengths_13(void) { assert_int_equal(DoCompare("1.0-1", "1.0", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_NO_MATCH); } void uneven_lengths_14(void) { assert_int_equal(DoCompare("1.0-1", "1.0", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_MATCH); } void uneven_lengths_15(void) { assert_int_equal(DoCompare("1.0-1", "1.0", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_NO_MATCH); } void uneven_lengths_16(void) { assert_int_equal(DoCompare("1.0", "1.0-1", PACKAGE_VERSION_COMPARATOR_EQ), VERCMP_NO_MATCH); } void uneven_lengths_17(void) { assert_int_equal(DoCompare("1.0", "1.0-1", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_NO_MATCH); } void uneven_lengths_18(void) { assert_int_equal(DoCompare("1.0", "1.0-1", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_MATCH); } void uneven_lengths_19(void) { assert_int_equal(DoCompare("1.0", "1.0-1", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_NO_MATCH); } void uneven_lengths_20(void) { assert_int_equal(DoCompare("1.0", "1.0-1", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_MATCH); } void invalid_01(void) { assert_int_equal(DoCompare("text-1.0", "1.0", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_ERROR); } void invalid_02(void) { assert_int_equal(DoCompare("text-1.0", "1.0", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_ERROR); } void invalid_03(void) { assert_int_equal(DoCompare("1.0", "text-1.0", PACKAGE_VERSION_COMPARATOR_LE), VERCMP_ERROR); } void invalid_04(void) { assert_int_equal(DoCompare("1.0", "text-1.0", PACKAGE_VERSION_COMPARATOR_GE), VERCMP_ERROR); } void invalid_05(void) { assert_int_equal(DoCompare("text-1.0", "1.0", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_ERROR); } void invalid_06(void) { assert_int_equal(DoCompare("text-1.0", "1.0", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_ERROR); } void invalid_07(void) { assert_int_equal(DoCompare("1.0", "text-1.0", PACKAGE_VERSION_COMPARATOR_LT), VERCMP_ERROR); } void invalid_08(void) { assert_int_equal(DoCompare("1.0", "text-1.0", PACKAGE_VERSION_COMPARATOR_GT), VERCMP_ERROR); } int main() { PRINT_TEST_BANNER(); LogSetGlobalLevel(LOG_LEVEL_VERBOSE); const UnitTest tests[] = { unit_test(test_different_name), unit_test(test_wildcard_arch), unit_test(test_non_matching_arch), unit_test(test_wildcard_version), unit_test(test_eq), unit_test(test_ne), unit_test(test_gt_lt), unit_test(test_gte_lte), unit_test(wrong_separators), unit_test(uneven_lengths_1), unit_test(uneven_lengths_2), unit_test(uneven_lengths_3), unit_test(uneven_lengths_4), unit_test(uneven_lengths_5), unit_test(uneven_lengths_6), unit_test(uneven_lengths_7), unit_test(uneven_lengths_8), unit_test(uneven_lengths_9), unit_test(uneven_lengths_10), unit_test(uneven_lengths_11), unit_test(uneven_lengths_12), unit_test(uneven_lengths_13), unit_test(uneven_lengths_14), unit_test(uneven_lengths_15), unit_test(uneven_lengths_16), unit_test(uneven_lengths_17), unit_test(uneven_lengths_18), unit_test(uneven_lengths_19), unit_test(uneven_lengths_20), unit_test(invalid_01), unit_test(invalid_02), unit_test(invalid_03), unit_test(invalid_04), unit_test(invalid_05), unit_test(invalid_06), unit_test(invalid_07), unit_test(invalid_08), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/thread_test.c0000664000175100017510000000667412243421446017630 0ustar00a10038a1003800000000000000#include #include #define NUM_THREADS 100 static void create_children(pthread_t tids[NUM_THREADS]); static void join_children(pthread_t tids[NUM_THREADS]); static void increment_shared_var(void); int SHARED_VAR; pthread_mutex_t shared_var_mutex = PTHREAD_MUTEX_INITIALIZER; void test_init_destroy(void) { pthread_mutex_t mutex_dynamic; int res_init = pthread_mutex_init(&mutex_dynamic, NULL); assert_int_equal(res_init, 0); int res_destroy = pthread_mutex_destroy(&mutex_dynamic); assert_int_equal(res_destroy, 0); } void test_trylock_impl(pthread_mutex_t *mutex) { int res_trylock_unlocked = pthread_mutex_trylock(mutex); assert_int_equal(res_trylock_unlocked, 0); int res_trylock_locked = pthread_mutex_trylock(mutex); if (res_trylock_locked != EBUSY && res_trylock_locked != EDEADLK) { /* Some pthread implementations return EDEADLK despite SUS saying otherwise */ fail(); } int res_unlock = pthread_mutex_unlock(mutex); assert_int_equal(res_unlock, 0); } void test_trylock_dynamic(void) { pthread_mutex_t mutex_dynamic; int res_init = pthread_mutex_init(&mutex_dynamic, NULL); assert_int_equal(res_init, 0); test_trylock_impl(&mutex_dynamic); int res_destroy = pthread_mutex_destroy(&mutex_dynamic); assert_int_equal(res_destroy, 0); } void test_trylock_static(void) { pthread_mutex_t mutex_static = PTHREAD_MUTEX_INITIALIZER; test_trylock_impl(&mutex_static); } void test_trylock_static_errorcheck(void) { pthread_mutex_t mutex_static_errorcheck = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; test_trylock_impl(&mutex_static_errorcheck); } void test_create(void) { SHARED_VAR = 0; pthread_t tid; int res_create = pthread_create(&tid, NULL, (void *) increment_shared_var, NULL); assert_int_equal(res_create, 0); int res_join = pthread_join(tid, NULL); assert_int_equal(res_join, 0); assert_int_equal(SHARED_VAR, 1); } static void increment_shared_var(void) { #define THREAD_ITERATIONS 1000 int res_lock = pthread_mutex_lock(&shared_var_mutex); assert_int_equal(res_lock, 0); for(int i = 0; i < THREAD_ITERATIONS; i++) { SHARED_VAR++; SHARED_VAR--; } SHARED_VAR++; int res_unlock = pthread_mutex_unlock(&shared_var_mutex); assert_int_equal(res_unlock, 0); } void test_lock(void) { SHARED_VAR = 0; pthread_t tids[NUM_THREADS]; create_children(tids); join_children(tids); assert_int_equal(SHARED_VAR, NUM_THREADS); } static void create_children(pthread_t tids[NUM_THREADS]) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 65536); for(int i = 0; i < NUM_THREADS; i++) { int res_create = pthread_create(&(tids[i]), &attr, (void *) increment_shared_var, NULL); assert_int_equal(res_create, 0); } } static void join_children(pthread_t tids[NUM_THREADS]) { for(int i = 0; i < NUM_THREADS; i++) { int res_join = pthread_join(tids[i], NULL); assert_int_equal(res_join, 0); } } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_init_destroy), unit_test(test_trylock_dynamic), unit_test(test_trylock_static), unit_test(test_trylock_static_errorcheck), unit_test(test_create), unit_test(test_lock), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/eval_context_test.c0000664000175100017510000000612612400110676021037 0ustar00a10038a1003800000000000000#include #include #include /* xsnprintf */ void tests_setup(void) { static char env[] = /* Needs to be static for putenv() */ "CFENGINE_TEST_OVERRIDE_WORKDIR=/tmp/CFENGINE_eval_context_test.XXXXXX"; char *workdir = strchr(env, '='); assert(workdir && workdir[1] == '/'); workdir++; mkdtemp(workdir); strlcpy(CFWORKDIR, workdir, CF_BUFSIZE); putenv(env); char state_dir[PATH_MAX]; xsnprintf(state_dir, PATH_MAX, "%s/state", workdir); mkdir(state_dir, 0766); } void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } static void test_class_persistence(void) { EvalContext *ctx = EvalContextNew(); // simulate old version { CF_DB *dbp; PersistentClassInfo i; assert_true(OpenDB(&dbp, dbid_state)); i.expires = UINT_MAX; i.policy = CONTEXT_STATE_POLICY_RESET; WriteDB(dbp, "old", &i, sizeof(PersistentClassInfo)); CloseDB(dbp); } // e.g. by monitoring EvalContextHeapPersistentSave(ctx, "class1", 3, CONTEXT_STATE_POLICY_PRESERVE, "a,b"); // e.g. by a class promise in a bundle with a namespace { Policy *p = PolicyNew(); Bundle *bp = PolicyAppendBundle(p, "ns1", "bundle1", "agent", NULL, NULL); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); EvalContextHeapPersistentSave(ctx, "class2", 5, CONTEXT_STATE_POLICY_PRESERVE, "x"); EvalContextStackPopFrame(ctx); PolicyDestroy(p); } EvalContextHeapPersistentLoadAll(ctx); { const Class *cls = EvalContextClassGet(ctx, "default", "old"); assert_true(cls != NULL); assert_string_equal("old", cls->name); assert_true(cls->tags != NULL); assert_int_equal(1, StringSetSize(cls->tags)); assert_true(StringSetContains(cls->tags, "source=persistent")); } { const Class *cls = EvalContextClassGet(ctx, "default", "class1"); assert_true(cls != NULL); assert_string_equal("class1", cls->name); assert_true(cls->tags != NULL); assert_int_equal(3, StringSetSize(cls->tags)); assert_true(StringSetContains(cls->tags, "source=persistent")); assert_true(StringSetContains(cls->tags, "a")); assert_true(StringSetContains(cls->tags, "b")); } { const Class *cls = EvalContextClassGet(ctx, "ns1", "class2"); assert_true(cls != NULL); assert_string_equal("ns1", cls->ns); assert_string_equal("class2", cls->name); assert_true(cls->tags != NULL); assert_int_equal(2, StringSetSize(cls->tags)); assert_true(StringSetContains(cls->tags, "source=persistent")); assert_true(StringSetContains(cls->tags, "x")); } EvalContextDestroy(ctx); } int main() { PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { unit_test(test_class_persistence), }; int ret = run_tests(tests); tests_teardown(); return ret; } cfengine-3.6.2/tests/unit/granules_test.c0000664000175100017510000000412612243421446020167 0ustar00a10038a1003800000000000000#include #include /* char *GenTimeKey(time_t now); const char *ShiftSlotToString(int shift_slot); int GetTimeSlot(time_t here_and_now); int GetShiftSlot(time_t here_and_now); time_t GetShiftSlotStart(time_t t); time_t MeasurementSlotStart(time_t t); time_t MeasurementSlotTime(size_t slot, size_t num_slots, time_t now); */ static void test_get_time_slot(void) { assert_int_equal(0, GetTimeSlot(1325462400)); // monday 00:00 assert_int_equal(1152, GetTimeSlot(1325808000)); // friday 00:00 assert_int_equal(2015, GetTimeSlot(1326067020)); // sunday 23:57 } static void test_measurement_slot_start(void) { assert_int_equal(1326066900, MeasurementSlotStart(1326067020)); // sunday 23:57 -> 23:55 } static void test_measurement_slot_time(void) { static const time_t now = 1326066900; // sunday 23:55 assert_int_equal(1325462400, MeasurementSlotTime(0, 2016, now)); // monday 00:00 assert_int_equal(1325808000, MeasurementSlotTime(1152, 2016, now)); // friday 00:00 assert_int_equal(1326066900, MeasurementSlotTime(2015, 2016, now)); // sunday 23:55 } static void test_gen_time_key(void) { assert_string_equal("Mon:Hr00:Min00_05", GenTimeKey(1325462400)); assert_string_equal("Mon:Hr00:Min00_05", GenTimeKey(1325462460)); assert_string_equal("Mon:Hr00:Min00_05", GenTimeKey(1325462520)); assert_string_equal("Mon:Hr00:Min00_05", GenTimeKey(1325462580)); assert_string_equal("Mon:Hr00:Min00_05", GenTimeKey(1325462640)); assert_string_equal("Mon:Hr00:Min05_10", GenTimeKey(1325462700)); assert_string_equal("Mon:Hr00:Min05_10", GenTimeKey(1325462760)); assert_string_equal("Mon:Hr00:Min05_10", GenTimeKey(1325462820)); assert_string_equal("Mon:Hr00:Min05_10", GenTimeKey(1325462880)); assert_string_equal("Mon:Hr00:Min05_10", GenTimeKey(1325462940)); } int main() { const UnitTest tests[] = { unit_test(test_get_time_slot), unit_test(test_measurement_slot_start), unit_test(test_measurement_slot_time), unit_test(test_gen_time_key) }; PRINT_TEST_BANNER(); return run_tests(tests); } cfengine-3.6.2/tests/unit/crypto_symmetric_test.c0000664000175100017510000000442712243421446021767 0ustar00a10038a1003800000000000000#include #include #include #define PLAINTEXT "123456789012345678901234567890123" #define KEY "1234567890123456789012345678901234567890123456789012345678901234" /* at least 512 bits long (to be sure) */ // use Blowfish (64-bit block size) for now #define CIPHER_TYPE_CFENGINE 'c' #define CIPHER_BLOCK_SIZE_BYTES 8 static const char CIPHERTEXT_PRECOMPUTED[] = { 0x99, 0xfd, 0x86, 0x9c, 0x17, 0xb9, 0xe4, 0x98, 0xab, 0x01, 0x17, 0x5a, 0x4a, 0xcf, 0xfc, 0x1f, 0xd4, 0xc5, 0xa3, 0xab, 0xf0, 0x1c, 0xa7, 0x39, 0xf1, 0xf4, 0x09, 0xe4, 0xac, 0xb6, 0x44, 0xbb, 0x47, 0xdd, 0xe6, 0xc4, 0x0e, 0x4a, 0x16, 0xf0 }; static int ComputeCiphertextLen(int plaintext_len, int cipher_block_size_bytes) { int last_block_offset = plaintext_len % cipher_block_size_bytes; int padding = cipher_block_size_bytes - last_block_offset; return (plaintext_len + padding); } static void test_cipher_init(void) { unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; unsigned char iv[] = {1,2,3,4,5,6,7,8}; EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, key, iv); EVP_CIPHER_CTX_cleanup(&ctx); } static void test_symmetric_encrypt(void) { char ciphertext[CF_BUFSIZE]; int plaintext_len = strlen(PLAINTEXT) + 1; int ciphertext_len = EncryptString(CIPHER_TYPE_CFENGINE, PLAINTEXT, ciphertext, KEY, plaintext_len); assert_int_equal(ciphertext_len, ComputeCiphertextLen(plaintext_len, CIPHER_BLOCK_SIZE_BYTES)); assert_memory_equal(ciphertext, CIPHERTEXT_PRECOMPUTED, ciphertext_len); } static void test_symmetric_decrypt(void) { char *ciphertext = (char *)CIPHERTEXT_PRECOMPUTED; int ciphertext_len = sizeof(CIPHERTEXT_PRECOMPUTED); char plaintext_out[CF_BUFSIZE]; int plaintext_len = DecryptString(CIPHER_TYPE_CFENGINE, ciphertext, plaintext_out, KEY, ciphertext_len); assert_int_equal(plaintext_len, strlen(PLAINTEXT) + 1); assert_string_equal(plaintext_out, PLAINTEXT); } int main() { PRINT_TEST_BANNER(); CryptoInitialize(); const UnitTest tests[] = { unit_test(test_cipher_init), unit_test(test_symmetric_encrypt), unit_test(test_symmetric_decrypt), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/buffer_test.c0000664000175100017510000005312212400110676017613 0ustar00a10038a1003800000000000000#include #include #include #include #include #include static void test_createBuffer(void) { Buffer *buffer = BufferNew(); assert_true(buffer != NULL); assert_true(buffer->buffer != NULL); assert_int_equal(buffer->mode, BUFFER_BEHAVIOR_CSTRING); assert_int_equal(buffer->capacity, DEFAULT_BUFFER_CAPACITY); assert_int_equal(buffer->used, 0); BufferDestroy(buffer); } static void test_createBufferFrom(void) { char *data = xstrdup("this is some data"); unsigned int dataLength = strlen(data); Buffer *buffer = BufferNewFrom(data, dataLength); assert_true(buffer != NULL); assert_true(buffer->buffer != NULL); assert_string_equal(data, buffer->buffer); assert_int_equal(buffer->mode, BUFFER_BEHAVIOR_CSTRING); assert_int_equal(buffer->used, dataLength); BufferDestroy(buffer); free (data); } static void test_destroyBuffer(void) { Buffer *buffer = BufferNew(); BufferDestroy(buffer); buffer = NULL; BufferDestroy(buffer); } static void test_setBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); char *element1 = (char *)xmalloc(2 * DEFAULT_BUFFER_CAPACITY + 2); unsigned int element1size = 2 * DEFAULT_BUFFER_CAPACITY + 1; Buffer *buffer = BufferNew(); assert_true(buffer != NULL); // Smaller than the allocated buffer BufferSet(buffer, element0, element0size); assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); assert_string_equal(element0, buffer->buffer); assert_string_equal(element0, BufferData(buffer)); // Larger than the allocated buffer for (int i = 0; i < element1size; ++i) { element1[i] = 'a'; } element1[element1size] = '\0'; BufferSet(buffer, element1, element1size); assert_int_equal(element1size, buffer->used); assert_string_equal(element1, buffer->buffer); assert_string_equal(element1, BufferData(buffer)); /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ Buffer *bm1 = BufferNew(); Buffer *be = BufferNew(); Buffer *bp1 = BufferNew(); char buffer_m1[DEFAULT_BUFFER_CAPACITY - 1]; char buffer_0[DEFAULT_BUFFER_CAPACITY]; char buffer_p1[DEFAULT_BUFFER_CAPACITY + 1]; unsigned int bm1_size = DEFAULT_BUFFER_CAPACITY - 1; unsigned int be_size = DEFAULT_BUFFER_CAPACITY; unsigned int bp1_size = DEFAULT_BUFFER_CAPACITY + 1; for (int i = 0; i < DEFAULT_BUFFER_CAPACITY - 1; ++i) { buffer_m1[i] = 'c'; buffer_0[i] = 'd'; buffer_p1[i] = 'e'; } /* * One shorter, that means the buffer remains the same size as before. */ buffer_m1[DEFAULT_BUFFER_CAPACITY - 2] = '\0'; BufferSet(bm1, buffer_m1, bm1_size); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_CAPACITY); /* * Same size, it should allocate one more block */ buffer_0[DEFAULT_BUFFER_CAPACITY - 1] = '\0'; BufferSet(be, buffer_0, be_size); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_CAPACITY); /* * 1 more, it should allocate one more block */ buffer_p1[DEFAULT_BUFFER_CAPACITY] = '\0'; BufferSet(bp1, buffer_p1, bp1_size); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_CAPACITY); BufferSet(buffer, element0, 0); /* * Destroy the buffer and good night. */ BufferDestroy(buffer); BufferDestroy(bm1); BufferDestroy(be); BufferDestroy(bp1); free(element0); free(element1); } static void test_zeroBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); const char *element0pointer = NULL; Buffer *buffer = BufferNew(); BufferSet(buffer, element0, element0size); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); BufferClear(buffer); assert_int_equal(DEFAULT_BUFFER_CAPACITY, buffer->capacity); assert_int_equal(0, buffer->used); assert_int_equal(0, BufferSize(buffer)); const char *data = BufferData(buffer); assert_string_equal(data, ""); assert_true(element0pointer == buffer->buffer); BufferDestroy(buffer); free(element0); } static void test_copyCompareBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); char *element1 = xstrdup("element1"); unsigned int element1size = strlen(element1); Buffer *buffer0 = NULL; Buffer *buffer1 = NULL; Buffer *buffer2 = NULL; buffer0 = BufferNew(); buffer1 = BufferNew(); assert_int_equal(0, BufferCompare(buffer0, buffer0)); assert_int_equal(0, BufferCompare(buffer0, buffer1)); buffer2 = BufferCopy(buffer0); assert_true(buffer2); assert_int_equal(0, BufferCompare(buffer0, buffer2)); // Add some flavour BufferDestroy(buffer2); BufferSet(buffer0, element0, element0size); BufferSet(buffer1, element1, element1size); assert_int_equal(0, BufferCompare(buffer0, buffer0)); assert_int_equal(-1, BufferCompare(buffer0, buffer1)); assert_int_equal(1, BufferCompare(buffer1, buffer0)); buffer2 = BufferCopy(buffer0); assert_int_equal(0, BufferCompare(buffer0, buffer2)); // Destroy the buffers BufferDestroy(buffer0); BufferDestroy(buffer1); BufferDestroy(buffer2); free (element0); free (element1); } static void test_appendBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); const char *element0pointer = NULL; char *element1 = xstrdup("element1"); unsigned int element1size = strlen(element1); const char *element1pointer = NULL; char *element2 = (char *)xmalloc(2 * DEFAULT_BUFFER_CAPACITY + 2); unsigned int element2size = 2 * DEFAULT_BUFFER_CAPACITY + 1; Buffer *buffer = BufferNew(); assert_true(buffer != NULL); // Initialize the buffer with a small string BufferAppend(buffer, element0, element0size); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); assert_string_equal(element0, buffer->buffer); assert_string_equal(element0, BufferData(buffer)); assert_int_equal(DEFAULT_BUFFER_CAPACITY, buffer->capacity); // Attach a small string to it BufferAppend(buffer, element1, element1size); assert_int_equal(element0size + element1size, BufferSize(buffer)); element1pointer = buffer->buffer; assert_true(element0pointer == element1pointer); assert_int_equal(buffer->used, element0size + element1size); assert_int_equal(BufferSize(buffer), element0size + element1size); char *shortAppend = NULL; shortAppend = (char *)xmalloc(element0size + element1size + 1); strcpy(shortAppend, element0); strcat(shortAppend, element1); assert_string_equal(shortAppend, buffer->buffer); assert_string_equal(shortAppend, BufferData(buffer)); /* * Zero the string and start again. */ BufferClear(buffer); BufferAppend(buffer, element0, element0size); assert_int_equal(element0size, BufferSize(buffer)); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); assert_string_equal(element0, buffer->buffer); assert_string_equal(element0, BufferData(buffer)); /* * Larger than the allocated buffer, this means we will allocate more memory * copy stuff into the new buffer and all that. */ int i = 0; for (i = 0; i < element2size; ++i) element2[i] = 'a'; element2[element2size] = '\0'; BufferAppend(buffer, element2, element2size); assert_int_equal(element0size + element2size, BufferSize(buffer)); assert_int_equal(buffer->used, element0size + element2size); assert_int_equal(BufferSize(buffer), element0size + element2size); char *longAppend = NULL; longAppend = (char *)xmalloc(element0size + element2size + 1); strcpy(longAppend, element0); strcat(longAppend, element2); assert_string_equal(longAppend, buffer->buffer); assert_string_equal(longAppend, BufferData(buffer)); BufferClear(buffer); /* * Destroy the buffer and good night. */ free(shortAppend); free(longAppend); BufferDestroy(buffer); free(element0); free(element1); free(element2); } static void test_append_boundaries(void) { /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ char buffer_m1[DEFAULT_BUFFER_CAPACITY - 1]; char buffer_0[DEFAULT_BUFFER_CAPACITY]; char buffer_p1[DEFAULT_BUFFER_CAPACITY + 1]; for (size_t i = 0; i < DEFAULT_BUFFER_CAPACITY - 1; ++i) { buffer_m1[i] = 'c'; buffer_0[i] = 'd'; buffer_p1[i] = 'e'; } { const unsigned int bm1_size = DEFAULT_BUFFER_CAPACITY - 1; Buffer *bm1 = BufferNew(); buffer_m1[DEFAULT_BUFFER_CAPACITY - 2] = '\0'; BufferAppend(bm1, buffer_m1, bm1_size); assert_int_equal(strlen(buffer_m1), BufferSize(bm1)); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_CAPACITY); BufferDestroy(bm1); } { const unsigned int be_size = DEFAULT_BUFFER_CAPACITY; Buffer *be = BufferNew(); buffer_0[DEFAULT_BUFFER_CAPACITY - 1] = '\0'; BufferAppend(be, buffer_0, be_size); assert_int_equal(strlen(buffer_0), BufferSize(be)); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_CAPACITY); BufferDestroy(be); } { const unsigned int bp1_size = DEFAULT_BUFFER_CAPACITY + 1; Buffer *bp1 = BufferNew(); buffer_p1[DEFAULT_BUFFER_CAPACITY] = '\0'; BufferAppend(bp1, buffer_p1, bp1_size); assert_int_equal(strlen(buffer_p1), BufferSize(bp1)); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_CAPACITY); BufferDestroy(bp1); } } static void test_printf(void) { char *char0 = xstrdup("char0"); unsigned int char0size = strlen(char0); const char *char0pointer = NULL; char *char1 = xstrdup("char1"); unsigned int char1size = strlen(char1); const char *char1pointer = NULL; char *char2 = (char *)xmalloc(2 * DEFAULT_BUFFER_CAPACITY + 2); unsigned int char2size = 2 * DEFAULT_BUFFER_CAPACITY + 1; int int0 = 123456789; char *int0char = xstrdup("123456789"); unsigned int int0charsize = strlen(int0char); double double0 = 3.1415; char *double0char = xstrdup("3.1415"); unsigned int double0charsize = strlen(double0char); char *char0int0char1double0 = xstrdup("char0 123456789 char1 3.1415"); unsigned int char0int0char1double0size = strlen(char0int0char1double0); Buffer *buffer = BufferNew(); assert_true(buffer != NULL); /* * Print the first char and compare the result */ assert_int_equal(char0size, BufferPrintf(buffer, "%s", char0)); char0pointer = buffer->buffer; assert_string_equal(char0, buffer->buffer); assert_string_equal(char0, BufferData(buffer)); assert_int_equal(char0size, buffer->used); assert_int_equal(char0size, BufferSize(buffer)); /* * Overwrite the first char with the second one */ assert_int_equal(char1size, BufferPrintf(buffer, "%s", char1)); char1pointer = buffer->buffer; assert_string_equal(char1, buffer->buffer); assert_string_equal(char1, BufferData(buffer)); assert_int_equal(char1size, buffer->used); assert_int_equal(char1size, BufferSize(buffer)); assert_true(char0pointer == char1pointer); /* * Try the int now */ assert_int_equal(int0charsize, BufferPrintf(buffer, "%d", int0)); assert_string_equal(int0char, buffer->buffer); assert_string_equal(int0char, BufferData(buffer)); assert_int_equal(int0charsize, buffer->used); assert_int_equal(int0charsize, BufferSize(buffer)); /* * Try the double now */ assert_int_equal(double0charsize, BufferPrintf(buffer, "%.4f", double0)); assert_string_equal(double0char, buffer->buffer); assert_string_equal(double0char, BufferData(buffer)); assert_int_equal(double0charsize, buffer->used); assert_int_equal(double0charsize, BufferSize(buffer)); /* * Try the combination now */ assert_int_equal(char0int0char1double0size, BufferPrintf(buffer, "%s %d %s %.4f", char0, int0, char1, double0)); assert_string_equal(char0int0char1double0, buffer->buffer); assert_string_equal(char0int0char1double0, BufferData(buffer)); assert_int_equal(char0int0char1double0size, buffer->used); assert_int_equal(char0int0char1double0size, BufferSize(buffer)); /* * Finally, try something larger than the default buffer and see if we get the right return value. */ unsigned int i = 0; for (i = 0; i < char2size; ++i) char2[i] = 'a'; char2[char2size] = '\0'; // The buffer should grow assert_int_equal(char2size, BufferPrintf(buffer, "%s", char2)); assert_string_equal(char2, buffer->buffer); assert_string_equal(char2, BufferData(buffer)); assert_int_equal(char2size, buffer->used); assert_int_equal(char2size, BufferSize(buffer)); /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ Buffer *bm1 = BufferNew(); Buffer *be = BufferNew(); Buffer *bp1 = BufferNew(); /* * The sizes are different for printf. If we have a size of X, then the string * is of length X-1, and so forth. */ char buffer_m1[DEFAULT_BUFFER_CAPACITY]; char buffer_0[DEFAULT_BUFFER_CAPACITY + 1]; char buffer_p1[DEFAULT_BUFFER_CAPACITY + 2]; unsigned int bm1_size = DEFAULT_BUFFER_CAPACITY - 1; unsigned int be_size = DEFAULT_BUFFER_CAPACITY; unsigned int bp1_size = DEFAULT_BUFFER_CAPACITY + 1; /* * Make sure the buffers are filled with 0. */ memset(buffer_m1, '\0', DEFAULT_BUFFER_CAPACITY); memset(buffer_0, '\0', DEFAULT_BUFFER_CAPACITY + 1); memset(buffer_p1, '\0', DEFAULT_BUFFER_CAPACITY + 2); /* * Write something to the buffers */ memset(buffer_m1, 'c', DEFAULT_BUFFER_CAPACITY); memset(buffer_0, 'd', DEFAULT_BUFFER_CAPACITY + 1); memset(buffer_p1, 'e', DEFAULT_BUFFER_CAPACITY + 2); /* * One shorter, that means the buffer remains the same size as before. */ buffer_m1[DEFAULT_BUFFER_CAPACITY - 1] = '\0'; assert_int_equal(bm1_size, BufferPrintf(bm1, "%s", buffer_m1)); assert_string_equal(buffer_m1, bm1->buffer); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_CAPACITY); /* * Same size, it should allocate one more block. * This means retrying the operation. */ buffer_0[DEFAULT_BUFFER_CAPACITY] = '\0'; assert_int_equal(be_size, BufferPrintf(be, "%s", buffer_0)); assert_string_equal(buffer_0, be->buffer); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_CAPACITY); /* * 1 more, it should allocate one more block * This means retrying the operation. */ buffer_p1[DEFAULT_BUFFER_CAPACITY + 1] = '\0'; assert_int_equal(bp1_size, BufferPrintf(bp1, "%s", buffer_p1)); assert_string_equal(buffer_p1, bp1->buffer); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_CAPACITY); /* * Release the resources */ BufferDestroy(buffer); BufferDestroy(bm1); BufferDestroy(be); BufferDestroy(bp1); free(char0); free(char1); free(char2); free(int0char); free(double0char); free(char0int0char1double0); } static int test_vprintf_helper(Buffer *buffer, char *fmt, ...) { va_list ap; va_start(ap, fmt); int result = 0; result = BufferVPrintf(buffer, fmt, ap); va_end(ap); return result; } static void test_vprintf(void) { char *char0 = xstrdup("char0"); unsigned int char0size = strlen(char0); const char *char0pointer = NULL; char *char1 = xstrdup("char1"); unsigned int char1size = strlen(char1); const char *char1pointer = NULL; char *char2 = (char *)xmalloc(2 * DEFAULT_BUFFER_CAPACITY + 2); unsigned int char2size = 2 * DEFAULT_BUFFER_CAPACITY + 1; int int0 = 123456789; char *int0char = xstrdup("123456789"); unsigned int int0charsize = strlen(int0char); double double0 = 3.1415; char *double0char = xstrdup("3.1415"); unsigned int double0charsize = strlen(double0char); char *char0int0char1double0 = xstrdup("char0 123456789 char1 3.1415"); unsigned int char0int0char1double0size = strlen(char0int0char1double0); Buffer *buffer = BufferNew(); assert_true(buffer != NULL); /* * Print the first char and compare the result */ assert_int_equal(char0size, test_vprintf_helper(buffer, "%s", char0)); char0pointer = buffer->buffer; assert_string_equal(char0, buffer->buffer); assert_string_equal(char0, BufferData(buffer)); assert_int_equal(char0size, buffer->used); assert_int_equal(char0size, BufferSize(buffer)); /* * Overwrite the first char with the second one */ assert_int_equal(char1size, test_vprintf_helper(buffer, "%s", char1)); char1pointer = buffer->buffer; assert_string_equal(char1, buffer->buffer); assert_string_equal(char1, BufferData(buffer)); assert_int_equal(char1size, buffer->used); assert_int_equal(char1size, BufferSize(buffer)); assert_true(char0pointer == char1pointer); /* * Try the int now */ assert_int_equal(int0charsize, test_vprintf_helper(buffer, "%d", int0)); assert_string_equal(int0char, buffer->buffer); assert_string_equal(int0char, BufferData(buffer)); assert_int_equal(int0charsize, buffer->used); assert_int_equal(int0charsize, BufferSize(buffer)); /* * Try the double now */ assert_int_equal(double0charsize, test_vprintf_helper(buffer, "%.4f", double0)); assert_string_equal(double0char, buffer->buffer); assert_string_equal(double0char, BufferData(buffer)); assert_int_equal(double0charsize, buffer->used); assert_int_equal(double0charsize, BufferSize(buffer)); /* * Try the combination now */ assert_int_equal(char0int0char1double0size, test_vprintf_helper(buffer, "%s %d %s %.4f", char0, int0, char1, double0)); assert_string_equal(char0int0char1double0, buffer->buffer); assert_string_equal(char0int0char1double0, BufferData(buffer)); assert_int_equal(char0int0char1double0size, buffer->used); assert_int_equal(char0int0char1double0size, BufferSize(buffer)); /* * Finally, try something larger than the default buffer and see if we get the right return value. */ unsigned int i = 0; for (i = 0; i < char2size; ++i) char2[i] = 'a'; char2[char2size] = '\0'; // The buffer should resize itself assert_int_equal(char2size, test_vprintf_helper(buffer, "%s", char2)); assert_string_equal(char2, buffer->buffer); assert_string_equal(char2, BufferData(buffer)); assert_int_equal(char2size, buffer->used); assert_int_equal(char2size, BufferSize(buffer)); /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ Buffer *bm1 = BufferNew(); Buffer *be = BufferNew(); Buffer *bp1 = BufferNew(); /* * The sizes are different for printf. If we have a size of X, then the string * is of length X-1, and so forth. */ char buffer_m1[DEFAULT_BUFFER_CAPACITY]; char buffer_0[DEFAULT_BUFFER_CAPACITY + 1]; char buffer_p1[DEFAULT_BUFFER_CAPACITY + 2]; unsigned int bm1_size = DEFAULT_BUFFER_CAPACITY - 1; unsigned int be_size = DEFAULT_BUFFER_CAPACITY; unsigned int bp1_size = DEFAULT_BUFFER_CAPACITY + 1; /* * Make sure the buffers are filled with 0. */ memset(buffer_m1, '\0', DEFAULT_BUFFER_CAPACITY); memset(buffer_0, '\0', DEFAULT_BUFFER_CAPACITY + 1); memset(buffer_p1, '\0', DEFAULT_BUFFER_CAPACITY + 2); /* * Write something to the buffers */ memset(buffer_m1, 'c', DEFAULT_BUFFER_CAPACITY); memset(buffer_0, 'd', DEFAULT_BUFFER_CAPACITY + 1); memset(buffer_p1, 'e', DEFAULT_BUFFER_CAPACITY + 2); /* * One shorter, that means the buffer remains the same size as before. */ buffer_m1[DEFAULT_BUFFER_CAPACITY - 1] = '\0'; assert_int_equal(bm1_size, test_vprintf_helper(bm1, "%s", buffer_m1)); assert_string_equal(buffer_m1, bm1->buffer); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_CAPACITY); /* * Same size, it should allocate one more block. * This means retrying the operation. */ buffer_0[DEFAULT_BUFFER_CAPACITY] = '\0'; assert_int_equal(be_size, test_vprintf_helper(be, "%s", buffer_0)); assert_string_equal(buffer_0, be->buffer); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_CAPACITY); /* * 1 more, it should allocate one more block * This means retrying the operation. */ buffer_p1[DEFAULT_BUFFER_CAPACITY + 1] = '\0'; assert_int_equal(bp1_size, test_vprintf_helper(bp1, "%s", buffer_p1)); assert_string_equal(buffer_p1, bp1->buffer); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_CAPACITY); /* * Release the resources */ BufferDestroy(buffer); BufferDestroy(bm1); BufferDestroy(be); BufferDestroy(bp1); free(char0); free(char1); free(char2); free(int0char); free(double0char); free(char0int0char1double0); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_createBuffer), unit_test(test_createBufferFrom), unit_test(test_destroyBuffer), unit_test(test_zeroBuffer), unit_test(test_copyCompareBuffer), unit_test(test_setBuffer), unit_test(test_appendBuffer), unit_test(test_append_boundaries), unit_test(test_printf), unit_test(test_vprintf) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/enterprise_extension_test_lib.c0000644000175100017510000000174112352022221023434 0ustar00a10038a1003800000000000000#include // Pretend we are an extension. #define BUILDING_ENTERPRISE_EXTENSION #include #include ENTERPRISE_FUNC_2ARG_DECLARE(int64_t, extension_function, int32_t, short_int, int64_t, long_int); ENTERPRISE_FUNC_3ARG_DECLARE(int64_t, extension_function_broken, int32_t, short_int, int64_t, unwanted_par, int64_t, long_int); ENTERPRISE_FUNC_2ARG_DEFINE(int64_t, extension_function, int32_t, short_int, int64_t, long_int) { return short_int * long_int; } // Notice that this function has a different signature from the one in the test .c file. ENTERPRISE_FUNC_3ARG_DEFINE(int64_t, extension_function_broken, int32_t, short_int, int64_t, unwanted_par, int64_t, long_int) { (void)unwanted_par; return short_int * long_int; } const char *GetExtensionLibraryVersion() { const char *version = getenv("CFENGINE_TEST_RETURN_VERSION"); if (version) { return version; } else { return VERSION; } } cfengine-3.6.2/tests/unit/lastseen_test.c0000664000175100017510000001343212400110676020160 0ustar00a10038a1003800000000000000#include #include #include #include #include #include /* xsnprintf */ char CFWORKDIR[CF_BUFSIZE]; void UpdateLastSawHost(const char *hostkey, const char *address, bool incoming, time_t timestamp); static void tests_setup(void) { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/lastseen_test.XXXXXX"); mkdtemp(CFWORKDIR); } static void setup(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'/*", CFWORKDIR); system(cmd); } static void tests_teardown(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } static void test_newentry(void) { setup(); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 666); DBHandle *db; OpenDB(&db, dbid_lastseen); KeyHostSeen q; assert_int_equal(ReadDB(db, "qiSHA-12345", &q, sizeof(q)), true); assert_int_equal(q.lastseen, 666); assert_double_close(q.Q.q, 0.0); assert_double_close(q.Q.dq, 0.0); assert_double_close(q.Q.expect, 0.0); assert_double_close(q.Q.var, 0.0); assert_int_equal(ReadDB(db, "qoSHA-12345", &q, sizeof(q)), false); char address[CF_BUFSIZE]; assert_int_equal(ReadDB(db, "kSHA-12345", address, sizeof(address)), true); assert_string_equal(address, "127.0.0.64"); char hostkey[CF_BUFSIZE]; assert_int_equal(ReadDB(db, "a127.0.0.64", hostkey, sizeof(hostkey)), true); assert_string_equal(hostkey, "SHA-12345"); CloseDB(db); } static void test_update(void) { setup(); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 555); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 1110); DBHandle *db; OpenDB(&db, dbid_lastseen); KeyHostSeen q; assert_int_equal(ReadDB(db, "qiSHA-12345", &q, sizeof(q)), true); assert_int_equal(q.lastseen, 1110); assert_double_close(q.Q.q, 555.0); assert_double_close(q.Q.dq, 555.0); assert_double_close(q.Q.expect, 222.0); assert_double_close(q.Q.var, 123210.0); CloseDB(db); } static void test_reverse_missing(void) { setup(); /* Check that resolution return false */ char result[CF_BUFSIZE]; assert_int_equal(Address2Hostkey(result, sizeof(result), "127.0.0.64"), false); } static void test_reverse_conflict(void) { setup(); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 555); DBHandle *db; OpenDB(&db, dbid_lastseen); assert_int_equal(WriteDB(db, "a127.0.0.64", "SHA-98765", strlen("SHA-98765") + 1), true); /* Check that resolution return false */ char result[CF_BUFSIZE]; assert_int_equal(Address2Hostkey(result, sizeof(result), "127.0.0.64"), false); /* Check that entry is removed */ assert_int_equal(HasKeyDB(db, "a127.0.0.64", strlen("a127.0.0.64") + 1), false); CloseDB(db); } static void test_reverse_missing_forward(void) { setup(); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 555); DBHandle *db; OpenDB(&db, dbid_lastseen); assert_int_equal(DeleteDB(db, "kSHA-12345"), true); /* Check that resolution return false */ char result[CF_BUFSIZE]; assert_int_equal(Address2Hostkey(result, sizeof(result), "127.0.0.64"), false); /* Check that entry is removed */ assert_int_equal(HasKeyDB(db, "a127.0.0.64", strlen("a127.0.0.64") + 1), false); CloseDB(db); } static void test_remove(void) { setup(); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 555); UpdateLastSawHost("SHA-12345", "127.0.0.64", false, 556); //RemoveHostFromLastSeen("SHA-12345"); DeleteDigestFromLastSeen("SHA-12345", NULL); DBHandle *db; OpenDB(&db, dbid_lastseen); assert_int_equal(HasKeyDB(db, "qiSHA-12345", strlen("qiSHA-12345") + 1), false); assert_int_equal(HasKeyDB(db, "qoSHA-12345", strlen("qoSHA-12345") + 1), false); assert_int_equal(HasKeyDB(db, "kSHA-12345", strlen("kSHA-12345") + 1), false); assert_int_equal(HasKeyDB(db, "a127.0.0.64", strlen("a127.0.0.64") + 1), false); CloseDB(db); } static void test_remove_ip(void) { setup(); UpdateLastSawHost("SHA-12345", "127.0.0.64", true, 555); UpdateLastSawHost("SHA-12345", "127.0.0.64", false, 556); char digest[CF_BUFSIZE]; DeleteIpFromLastSeen("127.0.0.64", digest); DBHandle *db; OpenDB(&db, dbid_lastseen); assert_int_equal(HasKeyDB(db, "qiSHA-12345", strlen("qiSHA-12345") + 1), false); assert_int_equal(HasKeyDB(db, "qoSHA-12345", strlen("qoSHA-12345") + 1), false); assert_int_equal(HasKeyDB(db, "kSHA-12345", strlen("kSHA-12345") + 1), false); assert_int_equal(HasKeyDB(db, "a127.0.0.64", strlen("a127.0.0.64") + 1), false); CloseDB(db); } int main() { tests_setup(); const UnitTest tests[] = { unit_test(test_newentry), unit_test(test_update), unit_test(test_reverse_missing), unit_test(test_reverse_conflict), unit_test(test_reverse_missing_forward), unit_test(test_remove), unit_test(test_remove_ip), }; PRINT_TEST_BANNER(); int ret = run_tests(tests); tests_teardown(); return ret; } /* STUBS */ void FatalError(ARG_UNUSED char *s, ...) { fail(); exit(42); } HashMethod CF_DEFAULT_DIGEST; pthread_mutex_t *cft_output; char VIPADDRESS[CF_MAX_IP_LEN]; RSA *PUBKEY; bool MINUSF; char *MapAddress(ARG_UNUSED char *addr) { fail(); } char *HashPrintSafe(ARG_UNUSED char *dst, ARG_UNUSED size_t dst_size, ARG_UNUSED const unsigned char *digest, ARG_UNUSED HashMethod type, ARG_UNUSED bool use_prefix) { fail(); } void HashPubKey(ARG_UNUSED RSA *key, ARG_UNUSED unsigned char digest[EVP_MAX_MD_SIZE + 1], ARG_UNUSED HashMethod type) { fail(); } cfengine-3.6.2/tests/unit/ipaddress_test.c0000664000175100017510000006006512411001073020314 0ustar00a10038a1003800000000000000#include #include #include #include #include #include static void test_ipv4(void) { /* * This test will check the ipv4 parser. We will directly call to it, we will not check * the generic frontend. * Cases to test: * 0.0.0.0 Ok * 255.255.255.255 Ok * 1.1.1.1 Ok * 1.1.1.1:1 Ok * 1.2.3.4 Ok * 5.6.7.8:9 Ok * 10.0.0.9:0 Ok * 10.0.0.10:5308 Ok * 192.168.56.10:65535 Ok * 0 Fail * 0.1 Fail * 0.1.2 Fail * 0:0 Fail * 1.1.1.260 Fail * 1.1.260.1 Fail * 1.260.1.1 Fail * 260.1.1.1 Fail * 260.260.260.260 Fail * 1.1.1.1: Fail * 2.3.4.5:65536 Fail * a.b.c.d Fail */ struct IPV4Address ipv4; memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("0.0.0.0", &ipv4)); assert_int_equal(ipv4.octets[0], 0); assert_int_equal(ipv4.octets[1], 0); assert_int_equal(ipv4.octets[2], 0); assert_int_equal(ipv4.octets[3], 0); assert_int_equal(ipv4.port, 0); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("255.255.255.255", &ipv4)); assert_int_equal(ipv4.octets[0], 255); assert_int_equal(ipv4.octets[1], 255); assert_int_equal(ipv4.octets[2], 255); assert_int_equal(ipv4.octets[3], 255); assert_int_equal(ipv4.port, 0); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("1.1.1.1", &ipv4)); assert_int_equal(ipv4.octets[0], 1); assert_int_equal(ipv4.octets[1], 1); assert_int_equal(ipv4.octets[2], 1); assert_int_equal(ipv4.octets[3], 1); assert_int_equal(ipv4.port, 0); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("1.1.1.1:1", &ipv4)); assert_int_equal(ipv4.octets[0], 1); assert_int_equal(ipv4.octets[1], 1); assert_int_equal(ipv4.octets[2], 1); assert_int_equal(ipv4.octets[3], 1); assert_int_equal(ipv4.port, 1); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("1.2.3.4", &ipv4)); assert_int_equal(ipv4.octets[0], 1); assert_int_equal(ipv4.octets[1], 2); assert_int_equal(ipv4.octets[2], 3); assert_int_equal(ipv4.octets[3], 4); assert_int_equal(ipv4.port, 0); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("5.6.7.8:9", &ipv4)); assert_int_equal(ipv4.octets[0], 5); assert_int_equal(ipv4.octets[1], 6); assert_int_equal(ipv4.octets[2], 7); assert_int_equal(ipv4.octets[3], 8); assert_int_equal(ipv4.port, 9); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("10.0.0.9:0", &ipv4)); assert_int_equal(ipv4.octets[0], 10); assert_int_equal(ipv4.octets[1], 0); assert_int_equal(ipv4.octets[2], 0); assert_int_equal(ipv4.octets[3], 9); assert_int_equal(ipv4.port, 0); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("10.0.0.10:5308", &ipv4)); assert_int_equal(ipv4.octets[0], 10); assert_int_equal(ipv4.octets[1], 0); assert_int_equal(ipv4.octets[2], 0); assert_int_equal(ipv4.octets[3], 10); assert_int_equal(ipv4.port, 5308); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(0, IPV4_parser("192.168.56.10:65535", &ipv4)); assert_int_equal(ipv4.octets[0], 192); assert_int_equal(ipv4.octets[1], 168); assert_int_equal(ipv4.octets[2], 56); assert_int_equal(ipv4.octets[3], 10); assert_int_equal(ipv4.port, 65535); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("0", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("0.1", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("0.1.2", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("0:0", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("1.1.1.260", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("1.1.260.1", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("1.260.1.1", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("260.1.1.1", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("260.260.260.260", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("1.1.1.1:", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("2.3.4.5:65536", &ipv4)); memset(&ipv4, 0, sizeof(struct IPV4Address)); assert_int_equal(-1, IPV4_parser("a.b.c.d", &ipv4)); } static void test_char2hex(void) { /* * Even if this routine is pretty simple, this is a sanity * check. This routine does not detect errors so we only * try valid conversions. * This routine does not expect the '0x' in front of numbers, * so our tests will be: * 0 .. 9 * a .. f * A .. F */ char i = '0'; for (i = '0'; i <= '9'; ++i) assert_int_equal(i - '0', Char2Hex(0, i)); for (i = 'a'; i <= 'f'; ++i) assert_int_equal(i - 'a' + 0x0A, Char2Hex(0, i)); } static void test_ipv6(void) { /* * This test will check the ipv6 parser. We will directly call to it, we will not check * the generic frontend. * Cases to test: * 0000:0000:0000:0000:0000:0000:0000:0000 Ok * 0:0:0:0:0:0:0:0 Ok * a:b:c:d::1 Ok * a:b:c:d:0:1:2:3 Ok * [a::b] Ok * [a:b:c:d:e:f:0:1]:8080 Ok * 0:1:2::4 Ok * 0::2:3:4 Ok * ::3:4 Ok * ::::::: Fail * A:B:C:D:E:F:0:1 Fail */ struct IPV6Address ipv6; memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("0000:0000:0000:0000:0000:0000:0000:0000", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0); assert_int_equal(ipv6.sixteen[1], 0); assert_int_equal(ipv6.sixteen[2], 0); assert_int_equal(ipv6.sixteen[3], 0); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 0); assert_int_equal(ipv6.sixteen[6], 0); assert_int_equal(ipv6.sixteen[7], 0); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("0:0:0:0:0:0:0:0", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0); assert_int_equal(ipv6.sixteen[1], 0); assert_int_equal(ipv6.sixteen[2], 0); assert_int_equal(ipv6.sixteen[3], 0); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 0); assert_int_equal(ipv6.sixteen[6], 0); assert_int_equal(ipv6.sixteen[7], 0); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("a:b:c:d::1", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0x0a); assert_int_equal(ipv6.sixteen[1], 0x0b); assert_int_equal(ipv6.sixteen[2], 0x0c); assert_int_equal(ipv6.sixteen[3], 0x0d); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 0); assert_int_equal(ipv6.sixteen[6], 0); assert_int_equal(ipv6.sixteen[7], 1); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("a:b:c:d:0:1:2:3", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0x0a); assert_int_equal(ipv6.sixteen[1], 0x0b); assert_int_equal(ipv6.sixteen[2], 0x0c); assert_int_equal(ipv6.sixteen[3], 0x0d); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 1); assert_int_equal(ipv6.sixteen[6], 2); assert_int_equal(ipv6.sixteen[7], 3); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("[a::b]", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0x0a); assert_int_equal(ipv6.sixteen[1], 0); assert_int_equal(ipv6.sixteen[2], 0); assert_int_equal(ipv6.sixteen[3], 0); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 0); assert_int_equal(ipv6.sixteen[6], 0); assert_int_equal(ipv6.sixteen[7], 0x0b); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("[a:b:c:d:e:f:0:1]:8080", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0x0a); assert_int_equal(ipv6.sixteen[1], 0x0b); assert_int_equal(ipv6.sixteen[2], 0x0c); assert_int_equal(ipv6.sixteen[3], 0x0d); assert_int_equal(ipv6.sixteen[4], 0x0e); assert_int_equal(ipv6.sixteen[5], 0x0f); assert_int_equal(ipv6.sixteen[6], 0); assert_int_equal(ipv6.sixteen[7], 1); assert_int_equal(ipv6.port, 8080); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("0:1:2::4", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0); assert_int_equal(ipv6.sixteen[1], 1); assert_int_equal(ipv6.sixteen[2], 2); assert_int_equal(ipv6.sixteen[3], 0); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 0); assert_int_equal(ipv6.sixteen[6], 0); assert_int_equal(ipv6.sixteen[7], 4); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("0::2:3:4", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0); assert_int_equal(ipv6.sixteen[1], 0); assert_int_equal(ipv6.sixteen[2], 0); assert_int_equal(ipv6.sixteen[3], 0); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 2); assert_int_equal(ipv6.sixteen[6], 3); assert_int_equal(ipv6.sixteen[7], 4); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(0, IPV6_parser("::3:4", &ipv6)); assert_int_equal(ipv6.sixteen[0], 0); assert_int_equal(ipv6.sixteen[1], 0); assert_int_equal(ipv6.sixteen[2], 0); assert_int_equal(ipv6.sixteen[3], 0); assert_int_equal(ipv6.sixteen[4], 0); assert_int_equal(ipv6.sixteen[5], 0); assert_int_equal(ipv6.sixteen[6], 3); assert_int_equal(ipv6.sixteen[7], 4); assert_int_equal(ipv6.port, 0); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(-1, IPV6_parser(":::::::", &ipv6)); memset(&ipv6, 0, sizeof(struct IPV6Address)); assert_int_equal(-1, IPV6_parser("A:B:C:D:E:F:0:1", &ipv6)); } static void test_generic_interface(void) { /* * This test might seem short, but it is intentional. * All the parsing tests should be implemented directly * on the corresponding parser test. Keep this test as * lean as possible. */ IPAddress *address = NULL; Buffer *buffer = NULL; buffer = BufferNew(); assert_true(buffer != NULL); BufferSet(buffer, "127.0.0.1", strlen("127.0.0.1")); address = IPAddressNew(buffer); assert_true(address != NULL); assert_int_equal(IP_ADDRESS_TYPE_IPV4, IPAddressType(address)); assert_string_equal("127.0.0.1", BufferData(IPAddressGetAddress(address))); assert_int_equal(0, IPAddressGetPort(address)); assert_int_equal(0, IPAddressDestroy(&address)); BufferSet(buffer, "127.0.0.1:8080", strlen("127.0.0.1:8080")); address = IPAddressNew(buffer); assert_true(address != NULL); assert_int_equal(IP_ADDRESS_TYPE_IPV4, IPAddressType(address)); assert_string_equal("127.0.0.1", BufferData(IPAddressGetAddress(address))); assert_int_equal(8080, IPAddressGetPort(address)); assert_int_equal(0, IPAddressDestroy(&address)); BufferSet(buffer, "0:1:2:3:4:5:6:7", strlen("0:1:2:3:4:5:6:7")); address = IPAddressNew(buffer); assert_true(address != NULL); assert_int_equal(IP_ADDRESS_TYPE_IPV6, IPAddressType(address)); assert_string_equal("0:1:2:3:4:5:6:7", BufferData(IPAddressGetAddress(address))); assert_int_equal(0, IPAddressGetPort(address)); assert_int_equal(0, IPAddressDestroy(&address)); BufferSet(buffer, "[0:1:2:3:4:5:6:7]:9090", strlen("[0:1:2:3:4:5:6:7]:9090")); address = IPAddressNew(buffer); assert_true(address != NULL); assert_int_equal(IP_ADDRESS_TYPE_IPV6, IPAddressType(address)); assert_string_equal("0:1:2:3:4:5:6:7", BufferData(IPAddressGetAddress(address))); assert_int_equal(9090, IPAddressGetPort(address)); assert_int_equal(0, IPAddressDestroy(&address)); BufferDestroy(buffer); } static void test_ipv4_address_comparison(void) { /* * We test different IPV4 combinations: * 1.1.1.1 vs 1.1.1.1 -> equal * 1.2.3.4 vs 1.1.1.1 -> not equal * 1.2.3.4 vs 1.2.1.1 -> not equal * 1.2.3.4 vs 1.2.3.1 -> not equal * 2.2.3.4 vs 1.2.3.4 -> not equal * 1.2.3.4 vs 1.2.3.4 -> equal * 1.2.3.4 vs NULL -> error * 1.2.3.4 vs 1:2:3:4:5:6:7:8 -> error */ IPAddress *a = NULL; IPAddress *b = NULL; Buffer *bufferA = NULL; Buffer *bufferB = NULL; bufferA = BufferNew(); assert_true(bufferA != NULL); BufferSet(bufferA, "1.1.1.1", strlen("1.1.1.1")); a = IPAddressNew(bufferA); assert_true(a != NULL); bufferB = BufferNew(); assert_true(bufferB != NULL); BufferSet(bufferB, "1.1.1.1", strlen("1.1.1.1")); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_true(IPAddressIsEqual(a, b)); BufferSet(bufferA, "1.2.3.4", strlen("1.2.3.4")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_false(IPAddressIsEqual(a, b)); BufferSet(bufferB, "1.2.1.1", strlen("1.2.1.1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); BufferSet(bufferB, "1.2.3.1", strlen("1.2.3.1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); BufferSet(bufferA, "2.2.3.4", strlen("2.2.3.4")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); BufferSet(bufferB, "1.2.3.4", strlen("1.2.3.4")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); BufferSet(bufferA, "1.2.3.4", strlen("1.2.3.4")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_true(IPAddressIsEqual(a, b)); assert_int_equal(IPAddressIsEqual(a, NULL), -1); assert_int_equal(IPAddressIsEqual(NULL, a), -1); BufferSet(bufferA, "1:2:3:4:5:6:7:8", strlen("1:2:3:4:5:6:7:8")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_int_equal(IPAddressIsEqual(a, b), -1); assert_int_equal(IPAddressIsEqual(b, a), -1); } static void test_ipv6_address_comparison(void) { /* * We test different IPV6 combinations: * 1:1:1:1:1:1:1:1 vs 1:1:1:1:1:1:1:1 -> equal * 1:2:3:4:5:6:7:8 vs 1:1:1:1:1:1:1:1 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:1:1:1:1:1:1 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:3:1:1:1:1:1 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:3:4:1:1:1:1 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:3:4:5:1:1:1 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:3:4:5:6:1:1 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:3:4:5:6:7:1 -> not equal * 2:2:3:4:5:6:7:8 vs 1:2:3:4:5:6:7:8 -> not equal * 1:2:3:4:5:6:7:8 vs 1:2:3:4:5:6:7:8 -> equal * Exotic variants * 1:0:0:0:0:0:0:1 vs 1::1 -> equal * 1:1:0:0:0:0:0:1 vs 1::1 -> not equal * 1:1:0:0:0:0:0:1 vs 1:1::1 -> equal * 1:0:0:0:0:0:1:1 vs 1::1:1 -> equal * Error conditions * 1::1:1 vs NULL -> error * 1::1:1 vs 1.2.3.4 -> error */ IPAddress *a = NULL; IPAddress *b = NULL; Buffer *bufferA = NULL; Buffer *bufferB = NULL; bufferA = BufferNew(); assert_true(bufferA != NULL); BufferSet(bufferA, "1:1:1:1:1:1:1:1", strlen("1:1:1:1:1:1:1:1")); a = IPAddressNew(bufferA); assert_true(a != NULL); bufferB = BufferNew(); assert_true(bufferB != NULL); BufferSet(bufferB, "1:1:1:1:1:1:1:1", strlen("1:1:1:1:1:1:1:1")); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_true(IPAddressIsEqual(a, b)); assert_true(bufferA != NULL); BufferSet(bufferA, "1:2:3:4:5:6:7:8", strlen("1:1:1:1:1:1:1:1")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:2:1:1:1:1:1:1", strlen("1:2:1:1:1:1:1:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:2:3:1:1:1:1:1", strlen("1:2:3:1:1:1:1:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:2:3:4:1:1:1:1", strlen("1:2:3:4:1:1:1:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:2:3:4:5:1:1:1", strlen("1:2:3:4:5:1:1:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:2:3:4:5:6:1:1", strlen("1:2:3:4:5:6:1:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:2:3:4:5:6:7:1", strlen("1:2:3:4:5:6:7:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "2:2:3:4:5:6:7:8", strlen("2:2:3:4:5:6:7:8")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferA != NULL); BufferSet(bufferA, "1:0:0:0:0:0:0:1", strlen("1:0:0:0:0:0:0:1")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_true(bufferB != NULL); BufferSet(bufferB, "1::1", strlen("1::1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_true(IPAddressIsEqual(a, b)); assert_true(bufferA != NULL); BufferSet(bufferA, "1:1:0:0:0:0:0:1", strlen("1:1:0:0:0:0:0:1")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_false(IPAddressIsEqual(a, b)); assert_true(bufferB != NULL); BufferSet(bufferB, "1:1::1", strlen("1:1::1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_true(IPAddressIsEqual(a, b)); assert_true(bufferA != NULL); BufferSet(bufferA, "1::1:1", strlen("1::1:1")); assert_int_equal(IPAddressDestroy(&a), 0); a = IPAddressNew(bufferA); assert_true(a != NULL); assert_true(bufferB != NULL); BufferSet(bufferB, "1:0:0:0:0:0:1:1", strlen("1:0:0:0:0:0:1:1")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_true(IPAddressIsEqual(a, b)); assert_int_equal(IPAddressIsEqual(a, NULL), -1); assert_true(bufferB != NULL); BufferSet(bufferB, "1.2.3.4", strlen("1.2.3.4")); assert_int_equal(IPAddressDestroy(&b), 0); b = IPAddressNew(bufferB); assert_true(b != NULL); assert_int_equal(IPAddressIsEqual(a, b), -1); } static void test_isipaddress(void) { /* * This test is just a summary of the other tests. * We just check that this interface works accordingly, most of the * functionality has already been tested. * 1.2.3.4 -> ok * 1.2..3 -> not * 1.a.2.3 -> not * 256.255.255.255 -> not * 255.255.255.255 -> ok * 1:0:0:0:0:0:0:1 -> ok * 1:1:1:1:0:1:1:1 -> ok * a:b:c:d:e:f:0:1 -> ok * a:b:c:d:e:f:g:h -> not * ffff:ffff:fffff:0:0:0:0:1 -> not */ IPAddress *address = NULL; Buffer *bufferAddress = NULL; bufferAddress = BufferNew(); assert_true (bufferAddress != NULL); BufferSet(bufferAddress, "1.2.3.4", strlen("1.2.3.4")); assert_true(IPAddressIsIPAddress(bufferAddress, NULL)); assert_true(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address != NULL); assert_int_equal(IPAddressType(address), IP_ADDRESS_TYPE_IPV4); BufferClear(bufferAddress); assert_int_equal(IPAddressDestroy(&address), 0); BufferSet(bufferAddress, "1.2..3", strlen("1.2..3")); assert_false(IPAddressIsIPAddress(bufferAddress, NULL)); assert_false(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address == NULL); BufferClear(bufferAddress); BufferSet(bufferAddress, "1.a.2.3", strlen("1.a.2.3")); assert_false(IPAddressIsIPAddress(bufferAddress, NULL)); assert_false(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address == NULL); BufferClear(bufferAddress); BufferSet(bufferAddress, "256.255.255.255", strlen("256.255.255.255")); assert_false(IPAddressIsIPAddress(bufferAddress, NULL)); assert_false(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address == NULL); BufferClear(bufferAddress); BufferSet(bufferAddress, "255.255.255.255", strlen("255.255.255.255")); assert_true(IPAddressIsIPAddress(bufferAddress, NULL)); assert_true(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address != NULL); assert_int_equal(IPAddressType(address), IP_ADDRESS_TYPE_IPV4); BufferClear(bufferAddress); assert_int_equal(IPAddressDestroy(&address), 0); BufferSet(bufferAddress, "1:0:0:0:0:0:0:1", strlen("1:0:0:0:0:0:0:1")); assert_true(IPAddressIsIPAddress(bufferAddress, NULL)); assert_true(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address != NULL); assert_int_equal(IPAddressType(address), IP_ADDRESS_TYPE_IPV6); BufferClear(bufferAddress); assert_int_equal(IPAddressDestroy(&address), 0); BufferSet(bufferAddress, "1:1:1:1:0:1:1:1", strlen("1:1:1:1:0:1:1:1")); assert_true(IPAddressIsIPAddress(bufferAddress, NULL)); assert_true(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address != NULL); assert_int_equal(IPAddressType(address), IP_ADDRESS_TYPE_IPV6); BufferClear(bufferAddress); assert_int_equal(IPAddressDestroy(&address), 0); BufferSet(bufferAddress, "a:b:c:d:e:f:0:1", strlen("a:b:c:d:e:f:0:1")); assert_true(IPAddressIsIPAddress(bufferAddress, NULL)); assert_true(IPAddressIsIPAddress(bufferAddress, &address)); assert_true(address != NULL); assert_int_equal(IPAddressType(address), IP_ADDRESS_TYPE_IPV6); BufferClear(bufferAddress); assert_int_equal(IPAddressDestroy(&address), 0); BufferSet(bufferAddress, "a:b:c:d:e:f:g:h", strlen("a:b:c:d:e:f:g:h")); assert_false(IPAddressIsIPAddress(bufferAddress, NULL)); assert_false(IPAddressIsIPAddress(bufferAddress, &address)); BufferClear(bufferAddress); BufferSet(bufferAddress, "ffff:ffff:fffff:0:0:0:0:1", strlen("ffff:ffff:fffff:0:0:0:0:1")); assert_false(IPAddressIsIPAddress(bufferAddress, NULL)); assert_false(IPAddressIsIPAddress(bufferAddress, &address)); BufferClear(bufferAddress); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_ipv4) , unit_test(test_char2hex) , unit_test(test_ipv6) , unit_test(test_generic_interface) , unit_test(test_ipv4_address_comparison) , unit_test(test_ipv6_address_comparison) , unit_test(test_isipaddress) }; return run_tests(tests); } cfengine-3.6.2/tests/unit/atexit_test.c0000664000175100017510000000231312243421446017641 0ustar00a10038a1003800000000000000#include #include #include bool FN1; bool FN2; bool FN3; void fn1(void) { if (FN1) { fprintf(stderr, "fn1 is called twice"); _exit(255); } if (!FN2) { fprintf(stderr, "fn2 is not called fn1"); _exit(255); } if (!FN3) { fprintf(stderr, "fn3 is not called before fn1"); _exit(255); } FN1 = true; } void fn2(void) { if (FN1) { fprintf(stderr, "fn1 is called before fn2"); _exit(255); } if (FN2) { fprintf(stderr, "fn2 is called twice"); _exit(255); } if (!FN3) { fprintf(stderr, "fn3 is not called before fn2"); _exit(255); } FN2 = true; } void fn3(void) { if (FN1) { fprintf(stderr, "fn1 is called before fn3"); _exit(255); } if (FN2) { fprintf(stderr, "fn2 is called before fn3"); _exit(255); } if (FN3) { fprintf(stderr, "fn3 is called twice"); _exit(255); } FN3 = true; } int main() { PRINT_TEST_BANNER(); RegisterAtExitFunction(&fn1); atexit(&fn2); RegisterAtExitFunction(&fn3); return 0; } cfengine-3.6.2/tests/unit/mon_load_test.c0000664000175100017510000000151512243421446020136 0ustar00a10038a1003800000000000000#include "test.h" #include "generic_agent.h" #include "mon.h" void test_load_monitor(void) { double cf_this[100]; MonLoadGatherData(cf_this); double load1[2] = {0,0}; double load2[2] = {0,0}; int n1 = getloadavg(load1, 1); int n2 = getloadavg(load2, 1); if (n1==-1 || n2==-1) { assert_true(1); return; } double min = (double) (load2[0]=lower && cf_this[ob_loadavg]<=upper); } int main() { PRINT_TEST_BANNER(); const UnitTest tests[] = { unit_test(test_load_monitor), }; return run_tests(tests); } cfengine-3.6.2/tests/unit/hash_test.c0000664000175100017510000001634612400110676017274 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include /* * To test the hash implementation we need three things: * - A string * - A file * - A RSA key * We run one test for each, using two algorithms, MD5 and SHA256. */ static int initialized = 0; static char message[] = "This is a message"; static int message_length = 0; static char file[] = "/tmp/hashXXXXXX"; static int fd = -1; static RSA *rsa = NULL; void tests_setup() { int result = 0; fd = mkstemp(file); if (fd < 0) { initialized = 0; return; } message_length = strlen(message); result = write(fd, message, message_length); if (result < 0) { close (fd); unlink (file); initialized = 0; return; } rsa = RSA_new(); if (rsa) { BIGNUM *bn = NULL; bn = BN_new(); if (!bn) { close (fd); unlink (file); RSA_free(rsa); initialized = 0; return; } BN_set_word(bn, 3); RSA_generate_key_ex(rsa, 1024, bn, NULL); BN_free(bn); } OpenSSL_add_all_digests(); initialized = 1; } void tests_teardown() { if (fd >= 0) { close (fd); unlink (file); } if (rsa) { RSA_free(rsa); } initialized = 0; } #define ASSERT_IF_NOT_INITIALIZED \ assert_int_equal(1, initialized) /* * Tests * Each test does the same but from different sources, this is: * 1. Create a new hash structure using MD5 * 2. Check the length of the generated hash. * 3. Check the printable version (check that is not NULL). * 4. Destroy the hash structure. * 5. Create a new hash structure using SHA256. * 6. Check the length of the generated hash. * 7. Check the printable version (check that is not NULL). * 8. Destroy the hash structure. */ static void test_HashString(void) { ASSERT_IF_NOT_INITIALIZED; Hash *hash = NULL; unsigned int length = 0; assert_true(hash == NULL); hash = HashNew(message, message_length, HASH_METHOD_MD5); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_MD5, HashType(hash)); assert_int_equal(CF_MD5_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_MD5_LEN); assert_true(HashPrintable(hash) != NULL); const char *md5_hash = HashPrintable(hash); assert_true((md5_hash[0] == 'M') && (md5_hash[1] == 'D') && (md5_hash[2] == '5') && (md5_hash[3] == '=')); HashDestroy(&hash); assert_true(hash == NULL); hash = HashNew(message, message_length, HASH_METHOD_SHA256); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_SHA256, HashType(hash)); assert_int_equal(CF_SHA256_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_SHA256_LEN); assert_true(HashPrintable(hash) != NULL); const char *sha256_hash = HashPrintable(hash); assert_true((sha256_hash[0] == 'S') && (sha256_hash[1] == 'H') && (sha256_hash[2] == 'A') && (sha256_hash[3] == '=')); HashDestroy(&hash); /* Negative cases */ assert_true(HashNew(NULL, message_length, HASH_METHOD_MD5) == NULL); assert_true(HashNew(message, 0, HASH_METHOD_MD5) == NULL); assert_true(HashNew(message, message_length, HASH_METHOD_NONE) == NULL); assert_true(HashNew(message, 0, HASH_METHOD_NONE) == NULL); assert_true(HashNew(NULL, message_length, HASH_METHOD_NONE) == NULL); } static void test_HashDescriptor(void) { ASSERT_IF_NOT_INITIALIZED; Hash *hash = NULL; unsigned int length = 0; assert_true(hash == NULL); hash = HashNewFromDescriptor(fd, HASH_METHOD_MD5); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_MD5, HashType(hash)); assert_int_equal(CF_MD5_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_MD5_LEN); assert_true(HashPrintable(hash) != NULL); HashDestroy(&hash); assert_true(hash == NULL); hash = HashNewFromDescriptor(fd, HASH_METHOD_SHA256); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_SHA256, HashType(hash)); assert_int_equal(CF_SHA256_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_SHA256_LEN); assert_true(HashPrintable(hash) != NULL); HashDestroy(&hash); /* Negative cases */ assert_true(HashNewFromDescriptor(-1, HASH_METHOD_MD5) == NULL); assert_true(HashNewFromDescriptor(fd, HASH_METHOD_NONE) == NULL); assert_true(HashNewFromDescriptor(-1, HASH_METHOD_NONE) == NULL); } static void test_HashKey(void) { ASSERT_IF_NOT_INITIALIZED; Hash *hash = NULL; unsigned int length = 0; assert_true(hash == NULL); hash = HashNewFromKey(rsa, HASH_METHOD_MD5); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_MD5, HashType(hash)); assert_int_equal(CF_MD5_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_MD5_LEN); assert_true(HashPrintable(hash) != NULL); HashDestroy(&hash); assert_true(hash == NULL); hash = HashNewFromKey(rsa, HASH_METHOD_SHA256); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_SHA256, HashType(hash)); assert_int_equal(CF_SHA256_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_SHA256_LEN); assert_true(HashPrintable(hash) != NULL); HashDestroy(&hash); /* Negative cases */ assert_true(HashNewFromKey(NULL, HASH_METHOD_MD5) == NULL); assert_true(HashNewFromKey(rsa, HASH_METHOD_NONE) == NULL); assert_true(HashNewFromKey(NULL, HASH_METHOD_NONE) == NULL); } static void test_HashCopy(void) { ASSERT_IF_NOT_INITIALIZED; Hash *hash = NULL; Hash *copy = NULL; unsigned int length = 0; assert_true(hash == NULL); hash = HashNew(message, message_length, HASH_METHOD_MD5); assert_true(hash != NULL); assert_int_equal(HASH_METHOD_MD5, HashType(hash)); assert_int_equal(CF_MD5_LEN, HashLength(hash)); assert_true(HashData(hash, &length) != NULL); assert_int_equal(length, CF_MD5_LEN); assert_true(HashPrintable(hash) != NULL); assert_int_equal(0, HashCopy(hash, ©)); assert_int_equal(HASH_METHOD_MD5, HashType(copy)); assert_int_equal(CF_MD5_LEN, HashLength(copy)); assert_true(HashData(copy, &length) != NULL); assert_int_equal(length, CF_MD5_LEN); assert_true(HashPrintable(copy) != NULL); assert_string_equal(HashPrintable(hash), HashPrintable(copy)); HashDestroy(©); assert_true(copy == NULL); /* Negative cases */ assert_int_equal(-1, HashCopy(NULL, ©)); assert_int_equal(-1, HashCopy(hash, NULL)); assert_int_equal(-1, HashCopy(NULL, NULL)); /* Finish */ HashDestroy(&hash); assert_true(hash == NULL); } /* * Main routine * Notice the calls to both setup and teardown. */ int main() { PRINT_TEST_BANNER(); tests_setup(); const UnitTest tests[] = { unit_test(test_HashString), unit_test(test_HashDescriptor), unit_test(test_HashKey), unit_test(test_HashCopy) }; int result = run_tests(tests); tests_teardown(); return result; } cfengine-3.6.2/tests/unit/schema.h0000664000175100017510000001451012236160673016557 0ustar00a10038a1003800000000000000#ifndef SCHEMA_H_ # define SCHEMA_H_ // Printf formatting for xml CUNIT Schema #define CUNIT_INIT \ "<\?xml version=\"1.0\" \?>\n" \ "<\?xml-stylesheet type=\"text/xsl\" href=\"CUnit-Run.xsl\" \?>\n" \ "\n" \ "\n" \ " \n" \ " \n" \ " \n" \ " \n" \ " %s suite \n" #define CUNIT_RUN_TEST_SUCCESS \ " \n" \ " \n" \ " %s \n" \ " \n" \ " \n" #define CUNIT_RUN_TEST_FAILURE_START \ " \n" \ " \n" \ " %s \n" #define CUNIT_RUN_TEST_FAILURE_ASSERT \ " \n" \ " \n" \ " %s \n" \ " %s \n" \ " %d \n" \ " %s(%lld) \n" \ " \n" \ " \n" #define CUNIT_RUN_TEST_FAILURE_ASSERT_EQUALITY_LLD \ " \n" \ " \n" \ " %s \n" \ " %s \n" \ " %d \n" \ " %s(%lld, %lld) \n" \ " \n" \ " \n" #define CUNIT_RUN_TEST_FAILURE_ASSERT_EQUALITY_STRING \ " \n" \ " \n" \ " %s \n" \ " %s \n" \ " %d \n" \ " %s(%s %s) \n" \ " \n" \ " \n" #define CUNIT_RUN_TEST_FAILURE_ASSERT_RANGE_LLD \ " \n" \ " \n" \ " %s \n" \ " %s \n" \ " %d \n" \ " %s(value=%lld, min=%lld, max=%lld) \n" \ " \n" \ " \n" #define CUNIT_RUN_TEST_FAILURE_ASSERT_SET_LLD \ " \n" \ " \n" \ " %s \n" \ " %s \n" \ " %d \n" \ " %s(value=%lld, number_of_values=%lld) \n" \ " \n" \ " \n" #define CUNIT_RUN_TEST_ERROR \ " \n" \ " \n" \ " %s \n" \ " %d \n" #define CUNIT_RUN_SUMMARY \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " %s \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " \n" \ " \n" \ " %s \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " \n" \ " \n" \ " %s \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " %d \n" \ " \n" \ " \n" \ " File Generated By CUnit v2.1-2 - %s\n" \ " \n" \ "\n" // Printf formatting for xml XS Schema #define XS_INIT_TESTSUITE \ "<\?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n" \ "\n" #define XS_TESTCASE \ " \n" #define XS_RUN_TEST_FAILURE_ASSERT \ " \n" \ " \n" #define XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_LLD \ " \n" \ " \n" #define XS_RUN_TEST_FAILURE_ASSERT_EQUALITY_STRING \ " \n" \ " \n" #define XS_RUN_TEST_FAILURE_ASSERT_RANGE_LLD \ " \n" \ " \n" #define XS_RUN_TEST_FAILURE_ASSERT_SET_LLD \ " \n" \ " \n" #define XS_RUN_TEST_ERROR \ " \n" #define XS_TESTCASE_END \ " \n" #define XS_TESTSUITE_END \ "\n" #endif cfengine-3.6.2/tests/README0000664000175100017510000000052012236160673015043 0ustar00a10038a1003800000000000000============================================================================== CFEngine testsuite ============================================================================== `make check' For information on how to add acceptance tests, see tests/acceptance/README. For information on how to add unit tests, see tests/unit/README. cfengine-3.6.2/tests/acceptance/0000755000175100017510000000000012413020725016240 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/09_services/0000755000175100017510000000000012352022221020366 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/09_services/stop.cf0000644000175100017510000000232312316547775021717 0ustar00a10038a1003800000000000000####################################################### # # Test services stop keyword # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4772" }; services: "myservice" service_policy => "stop", service_method => service_test; } body service_method service_test { service_bundle => test_services("$(this.promiser)","$(this.service_policy)"); } bundle agent test_services(service, state) { vars: "service_state" string => "$(state)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("stop", "$(test_services.service_state)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 39 cfengine-3.6.2/tests/acceptance/09_services/restart.cf0000644000175100017510000000233412316547775022420 0ustar00a10038a1003800000000000000####################################################### # # Test services restart keyword # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4772" }; services: "myservice" service_policy => "restart", service_method => service_test; } body service_method service_test { service_bundle => test_services("$(this.promiser)","$(this.service_policy)"); } bundle agent test_services(service, state) { vars: "service_state" string => "$(state)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("restart", "$(test_services.service_state)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 39 cfengine-3.6.2/tests/acceptance/09_services/start.cf0000644000175100017510000000232612316547775022072 0ustar00a10038a1003800000000000000####################################################### # # Test services start keyword # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4772" }; services: "myservice" service_policy => "start", service_method => service_test; } body service_method service_test { service_bundle => test_services("$(this.promiser)","$(this.service_policy)"); } bundle agent test_services(service, state) { vars: "service_state" string => "$(state)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("start", "$(test_services.service_state)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 39 cfengine-3.6.2/tests/acceptance/09_services/reload.cf0000644000175100017510000000233112316547775022177 0ustar00a10038a1003800000000000000####################################################### # # Test services reload keyword # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4772" }; services: "myservice" service_policy => "reload", service_method => service_test; } body service_method service_test { service_bundle => test_services("$(this.promiser)","$(this.service_policy)"); } bundle agent test_services(service, state) { vars: "service_state" string => "$(state)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("reload", "$(test_services.service_state)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 39 cfengine-3.6.2/tests/acceptance/09_services/service_cannot_be_resolved.cf.sub0000644000175100017510000000054512316547775027101 0ustar00a10038a1003800000000000000body common control { inputs => { "../default.cf.sub" }; bundlesequence => { test }; } bundle agent test { services: "myservice" service_policy => "start"; } bundle agent standard_services(service, state) { reports: "$(this.bundle): bringing $(service) into desired state $(state) 4441a73c9b58ff7f2285c018ee7449f35ec89712"; } cfengine-3.6.2/tests/acceptance/09_services/service_cannot_be_resolved.cf0000644000175100017510000000314112316547775026304 0ustar00a10038a1003800000000000000####################################################### # # catch "Service ... cannot be resolved" inform message # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } bundle common test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4772" }; classes: "resolution_warning" expression => returnszero("$(command) Service | $(G.grep) 'cannot be resolved' 2>&1", "useshell"); "myservice_found" expression => returnszero("$(command) 4441a73c9b58ff7f2285c018ee7449f35ec89712 2>&1", "useshell"); vars: "command" string => "$(sys.cf_agent) -KI -f $(this.promise_filename).sub | $(G.grep)"; } ####################################################### bundle agent check { classes: "ok" and => { "!resolution_warning", "myservice_found" }; reports: DEBUG.resolution_warning:: "failure: service bundle 'cannot be resolved' error WAS found"; DEBUG.!resolution_warning:: "success: service bundle 'cannot be resolved' error was not found"; DEBUG.myservice_found:: "success: myservice report 4441a73c9b58ff7f2285c018ee7449f35ec89712 was found"; DEBUG.!myservice_found:: "failure: myservice report 4441a73c9b58ff7f2285c018ee7449f35ec89712 was NOT found"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/09_services/outcomes.cf0000644000175100017510000000273112352022221022541 0ustar00a10038a1003800000000000000body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent test { vars: "services" slist => { "single" }; "policies" slist => { "start", "stop", "restart" }; services: "$(services)" service_policy => "$(policies)", classes => scoped_classes_generic("namespace", "$(services)_$(policies)"); } bundle agent standard_services(service, state) { reports: EXTRA:: "$(this.bundle): passthrough for $(service) -> $(state)"; } bundle agent check { vars: "s" slist => { @(test.services) }; "p" slist => { @(test.policies) }; methods: "collect" usebundle => dcs_all_classes_to_string("$(s)_$(p)"), inherit => "true", useresult => "$(s)_$(p)"; EXTRA:: "" usebundle => dcs_report_generic_classes("$(s)_$(p)"), inherit => "true"; any:: "report" usebundle => dcs_passif_expected('single_start_kept,single_stop_kept,single_restart_kept', 'single_start_repaired,single_start_failed,single_start_denied,single_start_timeout,single_stop_repaired,single_stop_failed,single_stop_denied,single_stop_timeout,single_restart_repaired,single_restart_failed,single_restart_denied,single_restart_timeout', $(this.promise_filename)); reports: EXTRA:: "Class strings for service $(s), policy $(p): $($(s)_$(p)[str])"; } cfengine-3.6.2/tests/acceptance/00_basics/0000755000175100017510000000000012411001073017774 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/05_licenses/0000755000175100017510000000000012316547775022141 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/05_licenses/001.cf0000644000175100017510000000220112316547775022746 0ustar00a10038a1003800000000000000####################################################### # # Test that we do not complain about license. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "agent" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO 2>&1", "useshell"); } ####################################################### bundle agent check { classes: "fail" expression => regcmp(".*Your configuration promises no host_licenses_paid in common control.*", $(test.agent)); reports: DEBUG:: "This should only pass if $(this.promise_filename).sub does not output anything about license"; "Output from $(this.promise_filename).sub: $(test.agent)"; !fail:: "$(this.promise_filename) Pass"; fail:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/05_licenses/001.cf.sub0000644000175100017510000000127112236160673023531 0ustar00a10038a1003800000000000000####################################################### # # Test that we do not complain about license. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; host_licenses_paid => "0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/00_basics/environment/0000755000175100017510000000000012316547775022374 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/environment/hpux.cf0000644000175100017510000000265012316547775023675 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3842: ensure correct sys.flavor, sys.arch on HP-UX # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { } bundle agent check { vars: "expected[flavor]" string => ifelse("hpux", "hp-ux_.+", "unknown"); "expected[arch]" string => ifelse("hpux", "ia64", "unknown"); "checks" slist => getindices("expected"); # If the output contains the string, we fail classes: "ok_$(checks)" expression => regcmp("$(expected[$(checks)])", "$(sys.$(checks))"); "unknown_$(checks)" expression => strcmp("$(expected[$(checks)])", "unknown"); "ok" and => { "ok_flavor", "ok_arch" }; "skipped" and => { "unknown_flavor", "unknown_arch" }; reports: DEBUG:: "check $(checks) was OK" ifvarclass => "ok_$(checks)"; "check $(checks) was not OK" ifvarclass => "!ok_$(checks).!unknown_$(checks)"; "check $(checks) was unknown (skipped)" ifvarclass => "unknown_$(checks)"; ok||skipped:: "$(this.promise_filename) Pass"; !ok.!skipped:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/0000755000175100017510000000000012411001073022106 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/800.cf0000644000175100017510000000210312316547775022757 0ustar00a10038a1003800000000000000####################################################### # # Test whether parsing of /etc/issue works on Debian # (Acceptance test for redmine #2988) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } ####################################################### bundle agent test { vars: debian:: "myflavor" string => execresult("/bin/grep Debian.*GNU /etc/issue | /usr/bin/cut -d' ' -f3 | cut -d. -f1 | cut -d/ -f1", "useshell"); } ####################################################### bundle agent check { classes: debian.!ubuntu:: "ok" expression => strcmp("$(sys.flavor)", "debian_$(test.myflavor)"); ubuntu:: "ok" expression => "any"; !debian:: "ok" expression => "any"; reports: DEBUG:: "Compared $(sys.flavor) to debian_$(test.myflavor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/200.x.cf0000644000175100017510000002117012243421446023205 0ustar00a10038a1003800000000000000# # Test that overlong identifier fails # body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } # 8192 symbols bundle agent xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/025.cf0000644000175100017510000000213712243421446022746 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { report_level => "verbose"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/README0000644000175100017510000000100112236160673022777 0ustar00a10038a10038000000000000000*.cf: This suite of tests is essentially 5 different tests repeated for various attributes. 1) prove that the test case works 2) show that it fails as expected with an illegal value 3) attempt to show failure when that illegal value is a parameter to the body 4) attempt to show failure when that illegal value is a parameter to the bundle 5) attempt to show failure when that illegal value is a parameter to a method 7*.cf: These tests are slightly different, but also address issues in constraint checking cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/704.x.cf0000644000175100017510000000217112243421446023216 0ustar00a10038a1003800000000000000####################################################### # # Related to Issue 377 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: ".*" process_select => test_plain, signals => { "child" }; } body process_select test_plain { command => "should-never-find-this"; process_result => "command|bfd.pms.wtf!"; # Illegal test names } ####################################################### bundle agent check { vars: "count" string => execresult("$(G.wc) $(test.counter)", "noshell"); classes: "ok" expression => regcmp("\s*3\s.*", "$(count)"); reports: DEBUG:: "Expected to crash - illegal test names"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/105.cf0000644000175100017510000000050612243421446022743 0ustar00a10038a1003800000000000000# Check that empty bundles work (Redmine #2411) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { } bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/007.cf0000644000175100017510000000213412243421446022743 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { log_level => "verbose"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/041.x.cf0000644000175100017510000000213312332665147023215 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { promise_repaired => { "ok" }; persist_time => "$(type)"; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/040.x.cf0000644000175100017510000000170312332665147023216 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action("banana"); } body action test_action(type) { promise_repaired => { "ok" }; persist_time => "$(type)"; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/102.x.cf0000644000175100017510000000055612243421446023213 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { reports: cfengine_3:: "$()"; } bundle agent check { cfengine_3:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/103.cf0000644000175100017510000000060112243421446022735 0ustar00a10038a1003800000000000000# Check that empty input lists work body common control { inputs => { @(g.inputs) }; bundlesequence => { check }; version => "1.0"; } bundle common g { vars: "inputs" slist => { }; } bundle agent check { reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; any:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/cf-promises-common-bundles-only.cf.sub0000644000175100017510000000023712316547775031374 0ustar00a10038a1003800000000000000body common control { bundlesequence => { runme }; } bundle agent runme { vars: "x" string => execresult("/bin/echo PURPLE_DINOSAUR", "noshell"); } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/042.x.cf0000644000175100017510000000225012332665147023216 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { promise_repaired => { "ok" }; persist_time => "$(type)"; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/045.x.cf0000644000175100017510000000176012411001073023202 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 (duplicate, to with pattern of 6) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { guest_environments: "host1" environment_host => "...com._", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/cf-promises-without-ppkeys.cf0000644000175100017510000000117112332665147027705 0ustar00a10038a1003800000000000000# Test that cf-promises doesn't fail if ppkeys are missing body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { methods: "clear ppkeys" usebundle => dcs_fini("$(sys.workdir)/ppkeys"); } bundle agent test { commands: "$(sys.cf_promises) -f $(this.promise_filename)" classes => scoped_classes_generic("namespace", "validated"); } bundle agent check { reports: validated_ok:: "$(this.promise_filename) Pass"; validated_not_ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/032.x.cf0000644000175100017510000000165012243421446023211 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/104.cf0000644000175100017510000000065112243421446022743 0ustar00a10038a1003800000000000000# Check that we are not trying to load "cf_null" as an input_file body common control { inputs => { @(g.inputs) }; bundlesequence => { check }; version => "1.0"; } bundle common g { vars: "inputs" slist => { "cf_null" }; } bundle agent check { reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; any:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/008.x.cf0000644000175100017510000000177512243421446023224 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { log_level => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/014.x.cf0000644000175100017510000000200012243421446023177 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { log_priority => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/013.cf0000644000175100017510000000213512243421446022741 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { log_priority => "alert"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/033.x.cf0000644000175100017510000000172312243421446023213 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "type" string => "banana"; files: "$(G.testfile)" create => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/100.cf0000644000175100017510000000215212316547775022754 0ustar00a10038a1003800000000000000###################################################### # # Test that ${this.promiser} is expanded in comments (Issue 691) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kvf $(this.promise_filename).sub | grep Comment", "useshell"); meta: "test_skip_needs_work" string => "windows"; } ####################################################### bundle agent check { classes: "ok1" not => regcmp(".*this\.promiser.*", "$(test.subout)"); "ok2" expression => regcmp(".*foobar.*", "$(test.subout)"); "ok" and => { "ok1", "ok2" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG:: "$(test.subout)"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/100.cf.sub0000644000175100017510000000021112236160673023523 0ustar00a10038a1003800000000000000body common control { bundlesequence => { 'test' }; } bundle agent test { files: "/tmp/foobar" comment => "${this.promiser}"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/031.cf0000644000175100017510000000200412243421446022734 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/depends_on_canonify.cf0000644000175100017510000000117312316547775026462 0ustar00a10038a1003800000000000000# Test depends_on with a canonify() function call body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { classes: # this works "foo1" expression => "any", depends_on => { canonify($(G.testfile)) }; methods: "" usebundle => test2($(G.testfile)); } bundle agent test2(file) { classes: # this fails "foo2" expression => "any", depends_on => { canonify($(file)) }; } bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/044.x.cf0000644000175100017510000000171612411001073023202 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { guest_environments: "host1" environment_host => "...com._", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/002.x.cf0000644000175100017510000000205212316547775023222 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_motd)"; link_type => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/038.x.cf0000644000175100017510000000175112243421446023221 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { promise_repaired => { "ok" }; persist_time => "banana"; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/003.x.cf0000644000175100017510000000212512316547775023224 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "type" string => "banana"; files: "$(G.testfile)" move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_motd)"; link_type => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/0000755000175100017510000000000012332665147023566 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/018.x.cf0000644000175100017510000000227712243421446024657 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { log_priority => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/009.x.cf0000644000175100017510000000176312243421446024656 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "type" string => "banana"; files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { log_level => "$(g.type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/030.x.cf0000644000175100017510000000227712243421446024651 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { report_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/028.x.cf0000644000175100017510000000173212243421446024653 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action("banana"); } body action test_action(type) { report_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/011.x.cf0000644000175100017510000000215712243421446024645 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { log_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/701.x.cf0000644000175100017510000000267712316547775024701 0ustar00a10038a1003800000000000000####################################################### # # Issue 377 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "files" slist => { "1", "2", "3" }; files: "$(G.testdir)/." create => "true"; "$(G.testdir)/$(files)" copy_from => init_copy("$(G.etc_group)"); } body copy_from init_copy(file) { source => "$(file)"; } ####################################################### bundle agent test { vars: "counter" string => "$(G.testdir)/counter"; files: "$(G.testdir)" transformer => "/bin/sh -c 'echo $(this.promiser) >> $(counter)'", file_select => test_plain, depth_search => test_recurse; } body file_select test_plain { file_types => { "plain" }; file_result => "file_types|bfd.pms.wtf!"; # Illegal test names } body depth_search test_recurse { depth => "inf"; } ####################################################### bundle agent check { vars: "count" string => execresult("$(G.wc) $(test.counter)", "noshell"); classes: "ok" expression => regcmp("\s*3\s.*", "$(count)"); reports: DEBUG:: "3 transformations expected, saw '$(count)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/021.x.cf0000644000175100017510000000176512243421446024652 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "type" string => "banana"; files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { action_policy => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/048.x.cf0000644000175100017510000000226312243421446024655 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("...com._"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { guest_environments: "host1" environment_host => "$(val)", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/022.x.cf0000644000175100017510000000173312243421446024646 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action("banana"); } body action test_action(type) { action_policy => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/035.x.cf0000644000175100017510000000201112243421446024640 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" create => "$(val)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/036.x.cf0000644000175100017510000000212612243421446024650 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" create => "$(val)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/039.x.cf0000644000175100017510000000214612243421446024655 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("...com._"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { guest_environments: "host1" environment_host => "$(val)", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/006.x.cf0000644000175100017510000000235212316547775024665 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" move_obstructions => "true", link_from => test_link("$(val)"); } body link_from test_link(type) { source => "$(G.etc_motd)"; link_type => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/024.x.cf0000644000175100017510000000230012243421446024637 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { action_policy => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/047.x.cf0000644000175100017510000000214612243421446024654 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("...com._"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { guest_environments: "host1" environment_host => "$(val)", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/703.x.cf0000644000175100017510000000146212243421446024653 0ustar00a10038a1003800000000000000####################################################### # # Issue 378 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { bindtointerface => "...com..._"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" expression => "any"; reports: DEBUG:: "This is expected to crash"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/027.x.cf0000644000175100017510000000176412243421446024657 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "type" string => "banana"; files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { report_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/029.x.cf0000644000175100017510000000216212243421446024652 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { report_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/046.x.cf0000644000175100017510000000176012243421446024654 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 (duplicate, to with pattern of 6) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { guest_environments: "host1" environment_host => "...com._", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/016.x.cf0000644000175100017510000000173212243421446024650 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action("banana"); } body action test_action(type) { log_priority => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/005.x.cf0000644000175100017510000000223512316547775024664 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" move_obstructions => "true", link_from => test_link("$(val)"); } body link_from test_link(type) { source => "$(G.etc_motd)"; link_type => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/010.x.cf0000644000175100017510000000172712243421446024646 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action("banana"); } body action test_action(type) { log_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/043.cf0000644000175100017510000000204212243421446024375 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { guest_environments: "host1" environment_host => "test", classes => whatever("ok"); } body classes whatever(c) { promise_kept => { "$(c)" }; promise_repaired => { "$(c)" }; } ####################################################### bundle agent check { reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/017.x.cf0000644000175100017510000000216212243421446024647 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { log_priority => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/015.x.cf0000644000175100017510000000176412243421446024654 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "type" string => "banana"; files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { log_priority => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/702.x.cf0000644000175100017510000000142612243421446024652 0ustar00a10038a1003800000000000000####################################################### # # Issue 378 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; syslog_host => "...com..._"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" expression => "any"; reports: DEBUG:: "This is expected to crash"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/012.x.cf0000644000175100017510000000227412243421446024646 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(v) { methods: "any" usebundle => do_test(v); } bundle agent do_test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { log_level => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/staging/023.x.cf0000644000175100017510000000216312243421446024645 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### # This test falls out of the usual test-syntax, because 1) It is designed to # fail and 2) Two of the set of tests requires a non-standard bundlesequence body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { init, test("banana"), check }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test(val) { files: "$(G.testfile)" create => "true", action => test_action("$(val)"); } body action test_action(type) { action_policy => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/020.x.cf0000644000175100017510000000200112243421446023175 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { action_policy => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/034.x.cf0000644000175100017510000000171612243421446023216 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 (duplicate, to preserve pattern of 5) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/710.x.cf0000644000175100017510000000170412243421446023214 0ustar00a10038a1003800000000000000####################################################### # # Related to bug introduced in core r1900 - allowed any body constraint name # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "$(G.testdir)/shouldnotexist" create => "true", nonexistant_attribute => "abc"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testdir)/shouldnotexist"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/004.x.cf0000644000175100017510000000207412316547775023230 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", link_from => test_link("banana"); } body link_from test_link(type) { source => "$(G.etc_motd)"; link_type => "$(type)"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/001.cf0000644000175100017510000000244412316547775022760 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile).SOURCE" create => "true"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", link_from => test_link; meta: "test_suppress_fail" string => "windows", meta => { "redmine4608" }; } body link_from test_link { source => "$(G.testfile).SOURCE"; link_type => "hardlink"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/019.cf0000644000175100017510000000222012243421446022742 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { action_policy => "warn"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; "This test should not create $(G.testfile)"; ok:: "$(this.promise_filename) FAIL"; !ok:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/depends_on.cf0000644000175100017510000000333712316547775024600 0ustar00a10038a1003800000000000000# Test depends_on body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "expandit" slist => { "hc2" }; methods: "zebra" usebundle => zebra:zebra; classes: "c1" expression => "any", scope => "namespace", handle => "hc1", depends_on => { }; "c2" expression => "any", scope => "namespace", handle => "hc2", depends_on => { "hc1", "me2" }; "c3" expression => "any", scope => "namespace", handle => "hc3", depends_on => { "$(expandit)" }; "c4" expression => "any", scope => "namespace", handle => "hc4", depends_on => { "nosuchhandle" }; "c5" expression => "any", scope => "namespace", handle => "hc5", depends_on => { "zebra.zebra" }; "c6" expression => "any", scope => "namespace", handle => "hc6", depends_on => { "zebra:zebra" }; reports: "me too" handle => "me2"; } bundle agent check { classes: "ok" and => { "c1", "c2", "c3", "!c4", "!c5", "!c6", }; reports: DEBUG.!c1:: "bad: c1 was NOT defined"; DEBUG.!c2:: "bad: c2 was NOT defined"; DEBUG.!c3:: "bad: c3 was NOT defined"; DEBUG.c4:: "bad: c4 WAS defined"; DEBUG.c5:: "bad: c5 WAS defined"; DEBUG.c6:: "bad: c6 WAS defined"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body file control { namespace => "zebra"; } bundle agent zebra { classes: "zebra" expression => "any", scope => "namespace", handle => "zebra"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/cf-promises-common-bundles-only.cf0000644000175100017510000000162312316547775030604 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3576: cf-promises should not run agent bundles # NOTE: changed to if --eval-functions=no # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_promises) --eval-functions=no -v -f $(this.promise_filename).sub | $(G.grep) PURPLE", "useshell"); } bundle agent check { # If the output contains the string, we fail classes: "ok1" not => regcmp(".*PURPLE_DINOSAUR.*", "$(test.subout)"); "ok" and => { "ok1" }; reports: DEBUG:: "PURPLE TEST: $(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/026.x.cf0000644000175100017510000000200012243421446023202 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", action => test_action; } body action test_action { report_level => "banana"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: DEBUG:: "This test should fail"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/cf-promises-99999999999.cf0000644000175100017510000000341212404565361026130 0ustar00a10038a1003800000000000000####################################################### # # Related to redmine #6531 # # In short, on 32-bit platforms the maximum number that cf-agent # understands is LONG_MAX. However the number "99999999999" (eleven # nines) has been historically used in many places, so this test makes # sure that it's still being accepted, even though on 32-bit platforms # it will be truncated to LONG_MAX. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### # With this body we're making sure cf-promises won't bail out on # this. This is exactly the body that cf-promises was rejecting before # the fix. body classes u_always_forever(theclass) { persist_time => 99999999999; } ####################################################### bundle agent init { vars: # truncation will happen on 32-bit architectures "x" int => "99999999999"; "y" int => "-99999999999"; } bundle agent test { classes: "x_ok" or => { strcmp("$(init.x)", "99999999999"), # 64-bit arch strcmp("$(init.x)", "2147483647") # 32-bit arch }, scope => "namespace"; "y_ok" or => { strcmp("$(init.y)", "-99999999999"), # 64-bit arch strcmp("$(init.y)", "-2147483648") # 32-bit arch }, scope => "namespace"; } bundle agent check { reports: DEBUG:: "x is $(init.x), should be 99999999999 or LONG_MAX"; "y is $(init.y), should be -99999999999 or LONG_MIN"; x_ok.y_ok:: "$(this.promise_filename) Pass"; !x_ok|!y_ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/101.cf0000644000175100017510000000160212316547775022754 0ustar00a10038a1003800000000000000###################################################### # # Test that \ expands correctly by eating newline (Issue 696) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "mystring" string => "some\ thing"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("$(test.mystring)", "something"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG:: "$(test.subout)"; } cfengine-3.6.2/tests/acceptance/00_basics/01_compiler/037.cf0000644000175100017510000000207612243421446022753 0ustar00a10038a1003800000000000000###################################################### # # Issue 375 setup (precursor to actual tickle of bug) # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", classes => test_action; } body classes test_action { promise_repaired => { "ok" }; persist_time => "10"; } ####################################################### bundle agent check { reports: DEBUG:: "This test should pass as a precursor to a bunch of related failures"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/validation/0000755000175100017510000000000012352022221022130 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/validation/validation_tagging_directory.cf0000644000175100017510000002302412352022221030361 0ustar00a10038a1003800000000000000# Test that cf-promises -T tags a directory correctly body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { meta: "test_skip_needs_work" string => "windows"; vars: "options" string => ifelse("verbose_mode", " -v ", ""); "dirs" slist => { $(G.testdir), $(sys.masterdir), $(sys.inputdir) }; "hubfile" slist => { "$(sys.workdir)/policy_server.dat", "$(sys.workdir)/state/am_policy_hub" }; methods: "rm hub" usebundle => dcs_fini($(hubfile)); "run" usebundle => test_dorun("testdir", $(G.testdir), "$(sys.cf_promises) -T $(G.testdir) $(options)"); "run" usebundle => test_dorun("inputdir", $(sys.inputdir), "$(sys.cf_agent) -K $(options)"); # make this machine a hub "mk hub" usebundle => file_make($(hubfile), "$(sys.host)"); "run" usebundle => test_dorun("masterdir", $(sys.masterdir), "$(sys.cf_agent) -K $(options)"); } bundle agent test_dorun(name, dir, tagopt) { vars: "simulated_validated_ok" string => ' { "timestamp": 1234, } '; "simulated_validated_bad" string => ' { "timestamp": 1234, } '; methods: vars: "masters" slist => { "promises.cf", "x.cf", "y.cf" }; methods: "rsync" usebundle => dir_sync("$(this.promise_dirname)/testdir", $(dir)); "master2cf" usebundle => file_copy("$(dir)/$(masters).master", "$(dir)/$(masters)"); "make ignored file 1" usebundle => file_make("$(dir)/ignoreme", "fnord $(sys.date)"); "make ignored file 2" usebundle => file_make("$(dir)/ignoredir/2", "fnord $(sys.date)"); "tag1" usebundle => test_tag("1", $(name), $(tagopt), "make new cf_promises_validated and cf_promises_release_id in $(dir)"); "read1" usebundle => test_read("1", $(name), $(dir)); "rm r_id" usebundle => dcs_fini($(test_read.rf)); "tag2" usebundle => test_tag("2", $(name), $(tagopt), "recreate cf_promises_release_id even if cf_promises_validated is OK"); "read2" usebundle => test_read("2", $(name), $(dir)); "make good validated file" usebundle => file_make("$(dir)/cf_promises_validated", $(simulated_validated_ok)); "tag3" usebundle => test_tag("3", $(name), $(tagopt), "rewrite good cf_promises_validated and leave cf_promises_release_id alone"); "read3" usebundle => test_read("3", $(name), $(dir)); "make bad validated file" usebundle => file_make("$(dir)/cf_promises_validated", $(simulated_validated_bad)); "tag4" usebundle => test_tag("4", $(name), $(tagopt), "overwrite bad cf_promises_validated"); "read4" usebundle => test_read("4", $(name), $(dir)); reports: "$(this.bundle): $(name) $(dir) '$(tagopt)'"; } bundle agent test_tag(vary, topname, tagopt, desc) { vars: "uid" string => "$(topname)_$(vary)"; classes: "tagged_$(uid)" expression => returnszero("$(tagopt) -D$(uid)", "noshell"), scope => "namespace"; reports: "Case $(uid): $(desc)"; DEBUG:: "Case $(uid): failed to $(tagopt)" ifvarclass => "!tagged_$(uid)"; "Case $(uid): tagged $(tagopt)" ifvarclass => "tagged_$(uid)"; } bundle agent test_read(suffix, topname, dir) { vars: "vf" string => "$(dir)/cf_promises_validated"; "rf" string => "$(dir)/cf_promises_release_id"; "uid" string => "$(topname)_$(suffix)"; "v_$(uid)" data => readjson($(vf), 4k), ifvarclass => "have_vf_$(uid)"; "v_$(uid)_str" string => format("%S", "v_$(uid)"), handle => "v_$(uid)_str", ifvarclass => "have_vf_$(uid)"; "r_$(uid)" data => readjson($(rf), 4k), ifvarclass => "have_rf_$(uid)"; "r_$(uid)_str" string => format("%S", "r_$(uid)"), handle => "r_$(uid)_str", ifvarclass => "have_rf_$(uid)"; classes: "have_vf_$(uid)" expression => fileexists($(vf)), scope => "namespace"; "have_rf_$(uid)" expression => fileexists($(rf)), scope => "namespace"; reports: DEBUG:: "Case $(uid): $(vf) = $(v_$(uid)_str)" depends_on => { "v_$(uid)_str" }, ifvarclass => "have_vf_$(uid)"; "Case $(uid): Missing validation file $(vf)" ifvarclass => "!have_vf_$(uid)"; "Case $(uid): $(rf) = $(r_$(uid)_str)" depends_on => { "r_$(uid)_str" }, ifvarclass => "have_rf_$(uid)"; "Case $(uid): Missing release ID file $(rf)" ifvarclass => "!have_rf_$(uid)"; } bundle agent check { vars: "expected_checksum" string => "4b974a13b5473cfbf60edfb66b201a364d38960f"; "tops" slist => { "testdir", "masterdir", "inputdir" }; "tests" slist => { "1", "2", "3", "4" }; classes: # exceptions # the release ID is not recreated in a normal agent run if the # promises validated file is OK, even on the hub "correct_release_masterdir_2" expression => "any"; # the release ID is not generated when running on a non-hub "correct_release_inputdir_$(tests)" expression => "any"; # normal testing "correct_timestamp_$(tops)_1" expression => "any"; "correct_release_$(tops)_1" expression => strcmp("$(test_read.r_$(tops)_1[releaseId])", $(expected_checksum)); "correct_timestamp_$(tops)_2" expression => "any"; "correct_release_$(tops)_2" expression => strcmp("$(test_read.r_$(tops)_2[releaseId])", $(expected_checksum)); # we expect the bad timestamp "correct_timestamp_inputdir_3" expression => strcmp("$(test_read.v_inputdir_3[timestamp])", "1234"); # anything except the bad timestamp is OK "correct_timestamp_masterdir_3" not => strcmp("$(test_read.v_masterdir_3[timestamp])", "1234"); "correct_timestamp_testdir_3" not => strcmp("$(test_read.v_testdir_3[timestamp])", "1234"); "correct_release_$(tops)_3" expression => strcmp("$(test_read.r_$(tops)_3[releaseId])", $(expected_checksum)); # we expect the bad timestamp "correct_timestamp_inputdir_4" expression => strcmp("$(test_read.v_inputdir_4[timestamp])", "1234"); # anything except the bad timestamp is OK "correct_timestamp_masterdir_4" not => strcmp("$(test_read.v_masterdir_4[timestamp])", "1234"); "correct_timestamp_testdir_4" not => strcmp("$(test_read.v_testdir_4[timestamp])", "1234"); "correct_release_$(tops)_4" expression => strcmp("$(test_read.r_$(tops)_4[releaseId])", $(expected_checksum)); "ok" and => { "tagged_testdir_1", "correct_timestamp_testdir_1", "correct_release_testdir_1", "tagged_testdir_2", "correct_timestamp_testdir_2", "correct_release_testdir_2", "tagged_testdir_3", "correct_timestamp_testdir_3", "correct_release_testdir_3", "tagged_testdir_4", "correct_timestamp_testdir_4", "correct_release_testdir_4", "tagged_masterdir_1", "correct_timestamp_masterdir_1", "correct_release_masterdir_1", "tagged_masterdir_2", "correct_timestamp_masterdir_2", "correct_release_masterdir_2", "tagged_masterdir_3", "correct_timestamp_masterdir_3", "correct_release_masterdir_3", "tagged_masterdir_4", "correct_timestamp_masterdir_4", "correct_release_masterdir_4", "tagged_inputdir_1", "correct_timestamp_inputdir_1", "correct_release_inputdir_1", "tagged_inputdir_2", "correct_timestamp_inputdir_2", "correct_release_inputdir_2", "tagged_inputdir_3", "correct_timestamp_inputdir_3", "correct_release_inputdir_3", "tagged_inputdir_4", "correct_timestamp_inputdir_4", "correct_release_inputdir_4", }; reports: DEBUG:: "Case $(tops)_$(tests): the timestamp was correct or ignored" ifvarclass => "correct_timestamp_$(tops)_$(tests)"; "Case $(tops)_$(tests): the timestamp was incorrect, actual $(test_read.v_$(tops)_$(tests)[timestamp])" ifvarclass => "!correct_timestamp_$(tops)_$(tests)"; "Case $(tops)_$(tests): the release ID was correct ($(expected_checksum)) or ignored" ifvarclass => "correct_release_$(tops)_$(tests)"; "Case $(tops)_$(tests): the release ID was incorrect, expected $(expected_checksum) vs. actual $(test_read.r_$(tops)_$(tests)[releaseId])" ifvarclass => "!correct_release_$(tops)_$(tests)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/0000755000175100017510000000000012316547775023640 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/promises.dat0000644000175100017510000000013612316547775026173 0ustar00a10038a1003800000000000000body common control { inputs => { "x.cf", "y.cf" }; bundlesequence => { x, y }; } cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/x.cf.master0000644000175100017510000000007112316547775025711 0ustar00a10038a1003800000000000000bundle agent x { reports: "$(this.bundle): x"; } cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/.gitattributes0000644000175100017510000000001112316547775026523 0ustar00a10038a1003800000000000000* eol=lf cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/y.cf.master0000644000175100017510000000007112316547775025712 0ustar00a10038a1003800000000000000bundle agent y { reports: "$(this.bundle): y"; } cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/promises.conf0000644000175100017510000000013612316547775026350 0ustar00a10038a1003800000000000000body common control { inputs => { "x.cf", "y.cf" }; bundlesequence => { x, y }; } cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/promises.txt0000644000175100017510000000013612316547775026242 0ustar00a10038a1003800000000000000body common control { inputs => { "x.cf", "y.cf" }; bundlesequence => { x, y }; } cfengine-3.6.2/tests/acceptance/00_basics/validation/testdir/promises.cf.master0000644000175100017510000000013612316547775027305 0ustar00a10038a1003800000000000000body common control { inputs => { "x.cf", "y.cf" }; bundlesequence => { x, y }; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/0000755000175100017510000000000012332665147022152 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/02_switches/README0000644000175100017510000000042512236160673023030 0ustar00a10038a1003800000000000000There are tests in this directory that consist of two files. The first file is the nnn.cf file, which is called by the test runner. The second file is the nnn.cf.sub file, which is called by the nnn.cf file. In each case we are testing the effects of various runtime flags. cfengine-3.6.2/tests/acceptance/00_basics/02_switches/003.cf.sub0000644000175100017510000000163712236160673023562 0ustar00a10038a1003800000000000000####################################################### # # Test class creation with -D # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should only pass if you do not run it with: -D ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) FAIL"; !ok:: "$(fn[1]) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/004.cf0000644000175100017510000000115512243421446022762 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,ok."; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/002.cf.sub0000644000175100017510000000163012236160673023552 0ustar00a10038a1003800000000000000####################################################### # # Test class creation with -D # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should only pass if you run it with: -D ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) Pass"; !ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/008.cf0000644000175100017510000000117312332665147022775 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,MAIN -N ok,foo"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/006.cf.sub0000644000175100017510000000153512332665147023565 0ustar00a10038a1003800000000000000####################################################### # # Test initial class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" expression => "any"; "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should pass even if you run it with: -N ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) Pass"; !ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/003.cf0000644000175100017510000000115512243421446022761 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,ok_"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/005.cf0000644000175100017510000000115712243421446022765 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO -N ok"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/006.cf0000644000175100017510000000116712332665147022776 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,MAIN -N ok"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/002.cf0000644000175100017510000000115512243421446022760 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,ok,"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/008.cf.sub0000644000175100017510000000153512332665147023567 0ustar00a10038a1003800000000000000####################################################### # # Test initial class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" expression => "any"; "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should pass even if you run it with: -N ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) Pass"; !ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/0000755000175100017510000000000012332665147023606 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/negate_hard_class.cf0000644000175100017510000000145612316547775027564 0ustar00a10038a1003800000000000000####################################################### # # Test hard class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle common test { classes: "rejected" not => returnszero("$(sys.cf_agent) -Kf $(this.promise_filename).sub -Ncfengine", "noshell"); } ####################################################### bundle agent check { classes: "ok" and => { "rejected" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/007.cf0000644000175100017510000000116712243421446024424 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,MAIN -N ok"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/009.cf.sub0000644000175100017510000000173512236160673025223 0ustar00a10038a1003800000000000000####################################################### # # Test initial class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "$(g.testfile)" create => "true", classes => set_bingo; } body classes set_bingo { promise_kept => { "bingo" }; promise_repaired => { "bingo" }; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); "ok" expression => "bingo"; reports: DEBUG:: "This should pass even if you run it with: -N ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) Pass"; !ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/negate_hard_class.cf.sub0000644000175100017510000000024212316547775030344 0ustar00a10038a1003800000000000000body common control { bundlesequence => { run }; } bundle agent run { reports: DEBUG:: "$(this.bundle): running from $(this.promise_filename)"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/009.cf0000644000175100017510000000117312243421446024423 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,MAIN -N ok,foo"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; "Test results come from $(this.promise_filename).sub"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/staging/007.cf.sub0000644000175100017510000000173512236160673025221 0ustar00a10038a1003800000000000000####################################################### # # Test initial class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "$(g.testfile)" create => "true", classes => set_bingo; } body classes set_bingo { promise_kept => { "bingo" }; promise_repaired => { "bingo" }; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); "ok" expression => "bingo"; reports: DEBUG:: "This should pass even if you run it with: -N ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) Pass"; !ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/001.cf0000644000175100017510000000105712243421446022760 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO,ok"; commands: "$(cmd)"; reports: DEBUG:: "Running: $(cmd)"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/001.cf.sub0000644000175100017510000000163012236160673023551 0ustar00a10038a1003800000000000000####################################################### # # Test class creation with -D # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should only pass if you run it with: -D ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) Pass"; !ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/010.cf.sub20000644000175100017510000000202512236160673023632 0ustar00a10038a1003800000000000000####################################################### # # Test class creation with -D # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub\d", $(this.promise_filename), "fn"); reports: DEBUG:: "This is $(this.promise_filename)"; "This should only pass if you run it with the 'bingo' class defined"; "The main tester does NOT set it, but it is created in the 'setup'"; "config file, $(fn[1]).sub1"; bingo:: "$(fn[1]) FAIL"; !bingo:: "$(fn[1]) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/010.cf.sub10000644000175100017510000000215112236160673023631 0ustar00a10038a1003800000000000000####################################################### # # Test initial class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", classes => set_bingo; } body classes set_bingo { promise_kept => { "bingo" }; promise_repaired => { "bingo" }; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub\d", $(this.promise_filename), "fn"); "ok" expression => "bingo"; reports: DEBUG:: "This is $(this.promise_filename), the setup stage of the test only"; DEBUG.bingo:: "bingo is set in $(this.promise_filename)"; DEBUG.!bingo:: "bingo is not set in $(this.promise_filename)"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/010.cf0000644000175100017510000000144712243421446022763 0ustar00a10038a1003800000000000000####################################################### # # This is a special test - it exercises runtime switches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test }; version => "1.0"; } ####################################################### bundle agent test { vars: "cmd1" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub1 -D AUTO -N bingo"; "cmd2" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub2 -D AUTO"; commands: "$(cmd1)"; "$(cmd2)"; reports: DEBUG:: "Running: $(cmd1)"; "Running: $(cmd2)"; "Setup comes from $(this.promise_filename).sub1, results come from $(this.promise_filename).sub2"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/004.cf.sub0000644000175100017510000000163712236160673023563 0ustar00a10038a1003800000000000000####################################################### # # Test class creation with -D # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should only pass if you do not run it with: -D ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) FAIL"; !ok:: "$(fn[1]) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/02_switches/005.cf.sub0000644000175100017510000000163312236160673023560 0ustar00a10038a1003800000000000000####################################################### # # Test initial class negation with -N # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: DEBUG:: "This should pass if you run it with: -N ok"; "Look at $(fn[1]) to see which flags are passed in"; ok:: "$(fn[1]) FAIL"; !ok:: "$(fn[1]) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/0000755000175100017510000000000012332665147021757 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/passing-vars.cf0000644000175100017510000000402712316547775024721 0ustar00a10038a1003800000000000000# Test that variables can be passed across bundles and namespaces body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "x" string => "datax"; "y" slist => { "datay1", "datay2" }; "z" data => parsejson('{ "hello": "there" }'); meta: "test_skip_needs_work" string => "windows"; methods: "x" usebundle => see_scalar($(x)); "y" usebundle => see_slist(@(test.y)); "z" usebundle => see_data(@(z)); } bundle agent see_scalar(svar) { classes: "saw_scalar" scope => "namespace", expression => strcmp($(svar), "datax"); reports: DEBUG:: "The passed-in string was $(svar)"; } bundle agent see_slist(lvar) { vars: "concat" string => join(",", lvar); classes: "saw_slist" scope => "namespace", expression => strcmp($(concat), "datay1,datay2"); reports: DEBUG:: "The passed-in slist was $(lvar)"; } bundle agent see_data(cvar_passed) { vars: "concat_passed" string => storejson(cvar_passed); "cvar_local" data => parsejson('{ "hello": "there" }'); "concat_local" string => storejson(cvar_local); # generates a warning about "can't find container named cvar_passed" "dummy" data => mergedata(cvar_local, cvar_passed); classes: "saw_data" scope => "namespace", expression => strcmp($(concat_passed), '{ "hello": "there" }'); reports: DEBUG:: "The passed-in container as string was $(concat_passed)"; "The local container as string was $(concat_local)"; } bundle agent check { classes: "ok" and => { "saw_scalar", "saw_slist", "saw_data" }; reports: DEBUG.!saw_scalar:: "The scalar passing didn't work"; DEBUG.!saw_slist:: "The slist passing didn't work"; DEBUG.!saw_data:: "The data passing didn't work"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/namespaced.x.cf0000644000175100017510000000071512316547775024652 0ustar00a10038a1003800000000000000# Redmine#4025: should fail body common control { inputs => { "../../default.cf.sub", "namespaced.cf.subx" }; bundlesequence => { mytest, default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { } bundle agent check { classes: "ok" and => { "any" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/bundle-iteration.cf0000644000175100017510000000150112316547775025543 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "bundles" slist => { "a", "b" }; "values" slist => { "x", "y" }; methods: "b" usebundle => $(bundles)("z"); # runs 2x "bv" usebundle => $(bundles)($(values)); # runs 4x } bundle agent a(var) { classes: "a_$(var)" expression => "any", scope => "namespace"; } bundle agent b(var) { classes: "b_$(var)" expression => "any", scope => "namespace"; } bundle agent check { classes: "ok" and => { "a_x", "b_x", "a_y", "b_y", "a_z", "b_z" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/getindices-vars-need-secondpass.cf0000644000175100017510000000203712316547775030443 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "x" slist => { "PARAM1", "PARAM2" }; "conf[internal1]" string => "internalvalue1"; "conf[internal2]" string => "internalvalue2"; "conf[$(x)]" string => "$(x)"; "keys_unsorted" slist => getindices("conf"); "keys" slist => sort(keys_unsorted, "lex"); "keys_str" string => format("%S", keys); reports: DEBUG:: "conf[$(keys_unsorted)] = $(conf[$(keys_unsorted)])"; } bundle agent check { vars: "expected" string => '{ "PARAM1", "PARAM2", "internal1", "internal2" }'; classes: "ok" expression => strcmp($(test.keys_str), $(expected)); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG.!ok:: "Expected $(expected), actual $(test.keys_str)"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/namespaced.cf.subx0000644000175100017510000000021212316547775025354 0ustar00a10038a1003800000000000000body file control { namespace => "ns1"; } bundle agent mytest { files: "$(sys.workdir)/ppkeys/." create => "true"; } call_namespaced_bundle_from_namespace_without_specifying_namespace.cf0000644000175100017510000000226312332665147037717 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/04_bundles# Test that namespaced bundles that call other namespaced bundles can do so # without specifying their own namespace # Redmine:4289 (https://cfengine.com/dev/issues/4289) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "agent_output" string => execresult("$(sys.cf_agent) -KIf $(this.promise_filename).sub -b testing:one", "noshell"); } bundle agent check { classes: "OK_non_specified_namespace" expression => regcmp(".*OKI DOKI.*", $(test.agent_output)); "OK_specified_namespace" expression => regcmp(".*artichokie.*", $(test.agent_output)); "ok" and => { "OK_non_specified_namespace", "OK_specified_namespace", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG:: "agent output: =============================================================================== $(test.agent_output) ==============================================================================="; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/namespaced.cf.sub0000644000175100017510000000201112316547775025163 0ustar00a10038a1003800000000000000body file control { namespace => "ns1"; } bundle agent mytest(a) { classes: "ns1global" expression => "any", scope => "namespace"; "ns1global_from_ppkeys" expression => "ns1ppkeys", scope => "namespace"; # should be defined "ns1global_from_ppkeys_explicit" expression => "ns1:ns1ppkeys", scope => "namespace"; # prefix should not be necessary vars: cfengine_3:: "ns1string" string => $(this.promise_dirname); files: "$(sys.workdir)/ppkeys/." create => "true", classes => default:always("ns1ppkeys"); reports: EXTRA:: "$(this.bundle): ns1string = '$(ns1string)'"; } body file control { namespace => "ns2"; } bundle agent mytest(a,b) { classes: "ns2global" expression => "cfengine_3", scope => "namespace"; vars: "ns2string" string => $(sys.fqhost); "ns2string2" string => $(const.t); files: "$(sys.workdir)/ppkeys/." create => "true"; reports: EXTRA:: "$(this.bundle): ns2string = '$(ns2string)'"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/wrong-bundle-type.cf.sub0000644000175100017510000000017312236160673026441 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "test" }; } bundle wrongwrongwrong test { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/wrong-bundle-type.cf0000644000175100017510000000123712243421446025647 0ustar00a10038a1003800000000000000# Test that wrong bundle type is detected (Redmine #XXXX) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: "subout" string => execresult("${sys.cf_agent} -Kf ${this.promise_filename}.sub", "noshell"); } bundle agent check { classes: "ok" expression => regcmp(".*Unknown bundle type.*", "${test.subout}"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/common-bundle-normal-ordering.cf0000644000175100017510000000155712243421446030126 0ustar00a10038a1003800000000000000# Tests that normal ordering (classes before vars) is adhered to in commmon # bundles, leading to correct resolution regardless of policy order. # This check tests that # 1. Common bundles are converged before other bundles. # 2. Common bundles promises follow normal ordering body common control { bundlesequence => { check }; version => "1.0"; } bundle agent check { reports: any:: # this was the only way I found to trigger the issue. Classifying # on join seems to resolve the variable. "$(this.promise_filename) $(g_stuff.two)"; } # It is critical that the common bundle is declared after the agent bundles bundle common g_stuff { # promise type ordering here is critical vars: trigger:: "one" string => "Pas"; any:: "two" slist => { "$(one)s" }; classes: "trigger" expression => "any"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/namespaced.cf0000644000175100017510000000341612332665147024375 0ustar00a10038a1003800000000000000# Redmine#4025 body common control { inputs => { "../../default.cf.sub", "namespaced.cf.sub" }; bundlesequence => { ns1:mytest("x"), ns2:mytest("x", "y"), default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { } bundle agent check { vars: "checks" slist => { "ns1:ns1global", "ns2:ns2global", "ns1:ns1global_from_ppkeys", "ns1:ns1global_from_ppkeys_explicit", "ns1global", "ns2global", "ok_ns1string", "ok_ns2string", "ok_ns2string2", }; classes: "ok_ns1string" expression => strcmp($(ns1:mytest.ns1string), $(this.promise_dirname)); "ok_ns2string" expression => strcmp($(ns2:mytest.ns2string), $(sys.fqhost)); "ok_ns2string2" expression => strcmp($(ns2:mytest.ns2string2), $(const.t)); "ok" and => { "ns1:ns1global", "ns2:ns2global", "ns1:ns1global_from_ppkeys", "ns1:ns1ppkeys", "!ns1global", "!ns2global", "ok_ns1string", "ok_ns2string", "ok_ns2string2", }; reports: EXTRA:: "class $(checks) is ON" ifvarclass => $(checks); EXTRA:: "class $(checks) is OFF" ifvarclass => "!$(checks)"; DEBUG.ns1:ns1global_from_ppkeys:: "ns1:ns1global_from_ppkeys is on as expected"; DEBUG.ns1:ns1global_from_ppkeys_explicit:: "ns1:ns1global_from_ppkeys_explicit is on as expected"; DEBUG.!ns1:ns1global_from_ppkeys:: "ns1:ns1global_from_ppkeys is NOT on as expected"; DEBUG.!ns1:ns1global_from_ppkeys_explicit:: "ns1:ns1global_from_ppkeys_explicit is NOT on as expected"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/04_bundles/duplicate_promise_handles.cf0000644000175100017510000000202412316547775027505 0ustar00a10038a1003800000000000000# Test that we dont get errors about duplicate handles when using variables in # handle name that do not expand identically # Redmine:4682 (https://cfengine.com/dev/issues/4682) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "duplicate" handle => "$(this.handle)_$(this.promiser)", string => "foo"; } bundle agent test { vars: "duplicate" handle => "$(this.handle)_$(this.promiser)", string => "bar"; # Two promises with equal handle but different classes is allowed reports: debian:: "this is debian" handle => "os_handle"; redhat:: "this is redhat" handle => "os_handle"; } bundle agent check { classes: "ok" and => { "any" }, comment => "Policy validation failing will cause us to never reach this if the test fails"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } call_namespaced_bundle_from_namespace_without_specifying_namespace.cf.sub0000644000175100017510000000054212316547775040515 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/04_bundlesbody file control { namespace => "testing"; } bundle agent one { methods: "call namespaced bundle from namespace" usebundle => two; "call namespaced bundle from namespace and specify the namespace" usebundle => testing:three; } bundle agent two { reports: "OKI DOKI"; } bundle agent three { reports: "artichokie"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/0000755000175100017510000000000012411001073021543 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/125.cf0000644000175100017510000000156512243421446022410 0ustar00a10038a1003800000000000000# Test a context defined in body classes with scope => bundle, # cancelling a namespace class using a bundle class body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; processes: any:: "$(G.true)" classes => set_cancel_this; } bundle agent test { processes: any:: "$(G.true)" classes => bundle_class; } body classes set_cancel_this { promise_kept => { "cancel_this" }; } body classes bundle_class { scope => "bundle"; promise_kept => { "bundle_class" }; cancel_kept => { "cancel_this" }; } bundle agent check { reports: !cancel_this:: "$(this.promise_filename) Pass"; cancel_this|bundle_class:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/119.cf0000644000175100017510000001034112353264455022412 0ustar00a10038a1003800000000000000####################################################### # # Test no classes set with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "1" }; repaired_returncodes => { "2" }; failed_returncodes => { "3" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/dynamic_inputs_findfiles.cf.sub0000644000175100017510000000027312316547775027754 0ustar00a10038a1003800000000000000bundle agent dynamic_included { meta: "tags" string => "included"; classes: "class_defined_from_included_bundle" expression => "any", scope => "namespace"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/120.cf0000644000175100017510000001036512243421446022401 0ustar00a10038a1003800000000000000####################################################### # # Test overlapping codes with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0", "1" }; repaired_returncodes => { "1" }; failed_returncodes => { "1", "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/README0000644000175100017510000000030512236160673022442 0ustar00a10038a1003800000000000000The files in this directory are tests of bodies that occur "anywhere": 0xx.cf body action 1xx.cf body classes 2xx.cf body comments 3xx.cf body depends_on 4xx.cf body handle 5xx.cf body ifvarclass cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/117.cf0000644000175100017510000001037612243421446022411 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0" }; repaired_returncodes => { "1" }; failed_returncodes => { "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/112.cf0000644000175100017510000001023012243421446022371 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" # create => "true", # file will not exist! edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/dynamic_inputs_findfiles.cf0000644000175100017510000000205312316547775027162 0ustar00a10038a1003800000000000000####################################################### # # Redmine#3315: Test dynamic inputs and bundlesequence # ####################################################### body common control { inputs => { "../../default.cf.sub", @(dynamic.inputs), }; bundlesequence => { dynamic, default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent dynamic { vars: "todo" slist => bundlesmatching(".*included"); "inputs" slist => findfiles("$(this.promise_filename).[s][u][b]"); methods: "run" usebundle => $(todo); reports: DEBUG:: "Found dynamic bundle: $(todo)"; } bundle agent init { } bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4730" }; } bundle agent check { classes: "ok" expression => "class_defined_from_included_bundle"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/control-body-fncall.cf0000644000175100017510000000123012316547775025755 0ustar00a10038a1003800000000000000# Test that functions may be called from control bodies body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { # this is just to trigger the desired behavior. here ifelse is evaluated # without any caller promise. If it was a non-control body, the caller # would have been the promise inlining the body. here there is no caller. default_repository => ifelse("x", "false", "y", "false", "false"); } bundle agent init { } bundle agent test { } bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/401.x.cf0000644000175100017510000000151512243421446022646 0ustar00a10038a1003800000000000000####################################################### # # Test handling of duplicate handles # Should error, was crashing in Issue 2267 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: "firstvar" handle => "dupehandle", string => "Some item with a handle"; "secondvar" handle => "dupehandle", string => "Another variable with an intentionally duplicated handle"; } bundle agent check { reports: DEBUG:: "Expected to return an error"; !ok:: "$(this.promise_filename) Pass"; ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/122.x.cf0000644000175100017510000001045212243421446022646 0ustar00a10038a1003800000000000000####################################################### # # Test illegal codes (string) with command and *_returncodes (issue 751) # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "1", "3" }; repaired_returncodes => { "fred", "7" }; # Must be an integer failed_returncodes => { "1", "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/dynamic_inputs_maplist.cf.sub0000644000175100017510000000041612352022221027427 0ustar00a10038a1003800000000000000bundle agent dynamic_included { meta: "tags" string => "included"; classes: "class_defined_from_included_bundle" expression => "any", scope => "namespace"; reports: DEBUG:: "$(this.promise_filename) activated $(this.bundle)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/114.cf0000644000175100017510000001023012316547775022412 0ustar00a10038a1003800000000000000####################################################### # # Test setting two classes in one promise # Copy file with one mode, then copy again with different mode # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile)" copy_from => local("$(G.etc_group)"), perms => mode("666"); } body copy_from local(f) { source => "$(f)"; } body perms mode(m) { mode => "$(m)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { meta: "test_skip_needs_work" string => "windows"; files: "$(G.testfile)" copy_from => local("$(G.etc_group)"), # Same file perms => mode("644"), # Different mode classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/103.cf0000644000175100017510000001024412243421446022376 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired (different location in edit_line) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/102.cf0000644000175100017510000001001612243421446022372 0ustar00a10038a1003800000000000000####################################################### # # Test multiple promise_repaired and cancel_repaired (contrived example) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_repaired => { "promise_repaired", "p2_repaired" }; cancel_repaired => { "cancel_repaired", "cancel_kept", "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[p2_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "p2_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/123.cf0000644000175100017510000000151612243421446022402 0ustar00a10038a1003800000000000000# Test a context defined in body classes with scope => bundle body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { processes: any:: "$(G.true)" classes => bundle_class; bundle_context:: "$(G.true)" classes => namespace_class; } body classes namespace_class { # default to namespace scoping promise_kept => { "namespace_context" }; } body classes bundle_class { scope => "bundle"; promise_kept => { "bundle_context" }; } bundle agent check { reports: namespace_context.!bundle_context:: "$(this.promise_filename) Pass"; bundle_context:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/104.cf0000644000175100017510000001024212243421446022375 0ustar00a10038a1003800000000000000####################################################### # # Test promise_kept and cancel_kept # Insert lines to a file, then verify that insert promise is kept # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => init_insert("$(init.body)"), edit_defaults => init_empty, classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/109.cf0000644000175100017510000001136112243421446022405 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (correctly done!) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/116.cf0000644000175100017510000001035712243421446022407 0ustar00a10038a1003800000000000000####################################################### # # Test promise_kept and cancel_kept with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0" }; repaired_returncodes => { "1" }; failed_returncodes => { "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/003.cf0000644000175100017510000000124712243421446022400 0ustar00a10038a1003800000000000000# Test that log_failed and log_kept set to the same value do not cause stack overflow (Redmine #2317) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { commands: "$(G.true)" action => log; } body action log { log_repaired => "$(G.testfile).action.log"; log_failed => "$(G.testfile).action.log"; log_kept => "$(G.testfile).action.log"; log_string => ""; } bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/002.cf0000644000175100017510000000150512243421446022374 0ustar00a10038a1003800000000000000# Test that log_failed and log_kept set to the same value do not cause stack overflow (Redmine #2317) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile).src" create => "yes"; "$(G.testfile).dest" create => "yes"; } bundle agent test { files: "$(G.testfile).dest" link_from => hard("$(G.testfile).src"), action => log; } body action log { log_failed => "$(G.testfile).action.log"; log_kept => "$(G.testfile).action.log"; log_string => ""; } body link_from hard(from) { source => "$(from)"; link_type => "hardlink"; } bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/evaluation-should-respect-ifvarclass.cf0000644000175100017510000000376112332665147031351 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3577: evaluation should respect ifvarclass # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { methods: "rm" usebundle => dcs_fini("$(G.testfile).z"); "rm" usebundle => dcs_fini("$(G.testfile).z2"); } bundle agent test { classes: "zclass" expression => returnszero("$(G.echo) xyz > $(G.testfile).z", "useshell"), ifvarclass => not("any"); "zclass" expression => returnszero("$(G.echo) xyz > $(G.testfile).z", "useshell"), depends_on => { "this_handle_does_not_exist" }; !any:: "z2class" expression => returnszero("$(G.echo) xyz > $(G.testfile).z2", "useshell"); vars: "x" string => concat("a", "b"), ifvarclass => "!any"; "x_not" string => concat("a", "b"), ifvarclass => not("any"); !any:: "y" string => concat("c", "d"); } bundle agent check { # If the output contains the string, we fail classes: "eval_x" expression => strcmp("ab", "$(test.x)"); "eval_x_not" expression => strcmp("ab", "$(test.x_not)"); "eval_y" expression => strcmp("cd", "$(test.y)"); "eval_z" expression => "zclass"; "zfile_created" expression => fileexists("$(G.testfile).z"); "z2file_created" expression => fileexists("$(G.testfile).z2"); methods: "" usebundle => dcs_passif_expected("", "eval_x,eval_x_not,eval_y,zclass,zfile_created,z2file_created", $(this.promise_filename)), inherit => "true"; reports: DEBUG:: "x $(test.x)"; "x_not $(test.x_not)"; "y $(test.y)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/0000755000175100017510000000000012332665147023223 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/204.cf0000644000175100017510000000712212332665147024044 0ustar00a10038a1003800000000000000####################################################### # # Test promise_kept and cancel_kept # Insert lines to a file, then verify that insert promise is kept # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => init_insert("$(init.body)"), edit_defaults => init_empty, classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/223.x.cf0000644000175100017510000001045512332665147024316 0ustar00a10038a1003800000000000000####################################################### # # Test illegal codes (negative num) with command and *_returncodes (issue 751) # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "-1", "3" }; # Must be positive repaired_returncodes => { "12" }; failed_returncodes => { "11", "12" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/224.x.cf0000644000175100017510000001044712332665147024320 0ustar00a10038a1003800000000000000####################################################### # # Test illegal codes (> 255) with command and *_returncodes (issue 751) # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "11", "13" }; repaired_returncodes => { "12" }; failed_returncodes => { "1111", "12" }; # Must be <= 255 } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/225.cf0000644000175100017510000001047312332665147024052 0ustar00a10038a1003800000000000000####################################################### # # Test illegal codes (space in num) with command and *_returncodes (issue 751) # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "11", "13" }; repaired_returncodes => { "12" }; failed_returncodes => { " 1", "12" }; # Spaces in number should be ok } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/209.cf0000644000175100017510000001024112332665147024045 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (correctly done!) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/217.cf0000644000175100017510000000725712332665147024061 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0" }; repaired_returncodes => { "1" }; failed_returncodes => { "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/215.cf0000644000175100017510000000707312332665147024053 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired with command and no *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/203.cf0000644000175100017510000000712412332665147024045 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired (different location in edit_line) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/216.cf0000644000175100017510000000723712332665147024056 0ustar00a10038a1003800000000000000####################################################### # # Test promise_kept and cancel_kept with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0" }; repaired_returncodes => { "1" }; failed_returncodes => { "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/201.cf0000644000175100017510000000706312332665147024045 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/213.cf0000644000175100017510000000723512332665147024051 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept (different location and results) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" # create => "true", # file will not exist! edit_line => init_insert("$(body)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)", # Promise never executed, so classes not set! classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/212.cf0000644000175100017510000000711012332665147024040 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" # create => "true", # file will not exist! edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/218.cf0000644000175100017510000000724312332665147024055 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0" }; repaired_returncodes => { "1" }; failed_returncodes => { "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile).missing" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/214.cf0000644000175100017510000000706112332665147024047 0ustar00a10038a1003800000000000000####################################################### # # Test setting two classes in one promise # Copy file with one mode, then copy again with different mode # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile)" copy_from => local("$(G.etc_group)"), perms => mode("666"); } body copy_from local(f) { source => "$(f)"; } body perms mode(m) { mode => "$(m)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" copy_from => local("$(G.etc_group)"), # Same file perms => mode("644"), # Different mode classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/221.cf0000644000175100017510000000726212332665147024050 0ustar00a10038a1003800000000000000####################################################### # # Test overlapping codes (with no match) with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "10", "11" }; repaired_returncodes => { "11" }; failed_returncodes => { "11", "12" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/staging/219.cf0000644000175100017510000000721112332665147024051 0ustar00a10038a1003800000000000000####################################################### # # Test no classes set with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "1" }; repaired_returncodes => { "2" }; failed_returncodes => { "3" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/log_file_permissions.cf0000644000175100017510000000176412316547775026334 0ustar00a10038a1003800000000000000# Test that log_failed and log_kept set to the same value do not cause stack overflow (Redmine #2317) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { meta: "test_skip_unsupported" string => "windows"; commands: "$(G.true)" action => log; } body action log { log_repaired => "$(G.testfile).action.log"; log_failed => "$(G.testfile).action.log"; log_kept => "$(G.testfile).action.log"; log_string => "ignore me"; } bundle agent check { vars: "perms" string => filestat("$(G.testfile).action.log", "permoct"); classes: "ok" expression => strcmp("600", $(perms)); reports: DEBUG:: "Log file $(G.testfile).action.log had permissions $(perms)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/115.cf0000644000175100017510000001021312243421446022375 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired with command and no *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/001.cf0000644000175100017510000000107012243421446022370 0ustar00a10038a1003800000000000000# Test that log_failed without log_kept does not segfault (Mantis #1107) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { files: "$(G.testdir)/foo.txt" create => "true", action => log; } body action log { log_failed => "stdout"; log_string => ""; } bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/113.cf0000644000175100017510000001035412243421446022401 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept (different location and results) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" # create => "true", # file will not exist! edit_line => init_insert("$(body)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)" # Promise never executed, so classes not set! classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/121.cf0000644000175100017510000001041212353264455022402 0ustar00a10038a1003800000000000000####################################################### # # Test overlapping codes (with no match) with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "10", "11" }; repaired_returncodes => { "11" }; failed_returncodes => { "11", "12" }; } ####################################################### bundle agent test { commands: "$(G.grep) linenotfound $(G.testfile)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/118.cf0000644000175100017510000001037312243421446022407 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept with command and *_returncodes # Insert lines to a file, the grep for a line which is there # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; kept_returncodes => { "0" }; repaired_returncodes => { "1" }; failed_returncodes => { "2" }; } ####################################################### bundle agent test { commands: "$(G.grep) BEGIN $(G.testfile).missing" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; MAIN.ok:: "$(this.promise_filename) Pass" report_to_file => "$(G.logfile)"; !ok:: "$(this.promise_filename) FAIL"; MAIN.!ok:: "$(this.promise_filename) FAIL" report_to_file => "$(G.logfile)"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/124.cf0000644000175100017510000000216012243421446022377 0ustar00a10038a1003800000000000000# Test a context defined in body classes with scope => bundle, # check that the bundle context goes away after the bundle is done body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { methods: !pass_one:: "whatever" usebundle => set_context("yes"); pass_one:: "whatever2" usebundle => set_context("no"); } bundle agent set_context(doit) { classes: "set_bundle_class" expression => strcmp(${doit}, "yes"); processes: set_bundle_class:: "$(G.true)" classes => bundle_class; "$(G.true)" classes => namespace_class; } body classes namespace_class { scope => "namespace"; promise_kept => { "pass_one" }; } body classes bundle_class { scope => "bundle"; promise_kept => { "bundle_context" }; } bundle agent check { reports: !bundle_context:: "$(this.promise_filename) Pass"; bundle_context:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/ifvarclass-with-function.cf0000644000175100017510000000256312400110676027024 0ustar00a10038a1003800000000000000# Verify that functions returns are interpreted correctly in ifvarclass # Redmine 6327 body common control { AUTO:: inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; !AUTO:: bundlesequence => { "init", "check" }; } bundle agent init { vars: "always" string => "any"; "never" string => "!any"; } bundle agent check { classes: # yes "variable_with_set_class" expression => "any", ifvarclass => canonify("$(init.always)"); # no "variable_with_unset_class" expression => "any", ifvarclass => canonify("$(init.never)"); "just_a_class" expression => "any", ifvarclass => not("any"); "undefined_variable" expression => "any", ifvarclass => canonify("$(init.unknown)"); "undefined_bundle" expression => "any", ifvarclass => canonify("$(never.never)"); "invalid_function" expression => "any", ifvarclass => now(); "fail" expression => "variable_with_unset_class|just_a_class|undefined_variable|undefined_bundle|invalid_function"; "ok" and => { "variable_with_set_class", "!fail" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG.just_a_class:: "just_a_class"; DEBUG.undefined_variable:: "undefined_variable"; DEBUG.undefined_bundle:: "undefined_bundle"; DEBUG.invalid_function:: "invalid_function"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/dynamic_inputs_maplist.cf0000644000175100017510000000217212352022221026640 0ustar00a10038a1003800000000000000####################################################### # # Redmine#3315: Test dynamic inputs and bundlesequence using maplist # ####################################################### body common control { inputs => { "../../default.cf.sub", @(dynamic.inputs), }; bundlesequence => { dynamic, default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent dynamic { vars: "todo" slist => bundlesmatching(".*included"); "dynamic_input_names" slist => {"$(this.promise_filename).sub"}; "inputs" slist => maplist("$(this)", "dynamic_input_names"); methods: "run" usebundle => $(todo); reports: DEBUG:: "Found dynamic bundle: $(todo)"; } bundle agent init { } bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4730" }; } bundle agent check { classes: "ok" expression => "class_defined_from_included_bundle"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/00_basics/03_bodies/101.cf0000644000175100017510000000771712243421446022407 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "cancel_kept" expression => "any"; "cancel_repaired" expression => "any"; "cancel_notkept" expression => "any"; } ####################################################### bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/default.cf.sub0000644000175100017510000000100512332665147020777 0ustar00a10038a1003800000000000000######################################################################## # Acceptance test framework. # # See README for details about writing test cases. ######################################################################## body file control { # plucked.cf.sub comes from the stdlib with `make pluck` inputs => { "$(D.owndir)$(const.dirsep)plucked.cf.sub", "$(D.owndir)$(const.dirsep)dcs.cf.sub",}; } bundle common D { vars: "owndir" string => "$(this.promise_dirname)"; } cfengine-3.6.2/tests/acceptance/README0000644000175100017510000002237012411001073017115 0ustar00a10038a1003800000000000000============================================================================== CFEngine acceptance testsuite ============================================================================== CFEngine has an extensive testsuite which covers lot of functionality which can be tested as a series of cf-agent runs. You are encouraged to run this testsuite on any new software/hardware configuration, in order to * verify that CFEngine functions correctly * provide developers with reproducible way to fix any problems encountered in new configurations / environment In case you find a bug you are encouraged to create tests in format of testsuite which demonstrate bug found, so the test could be added to this testsuite and checked for in the future. ------------------------------------------------------------------------------ Preparing for running tests ------------------------------------------------------------------------------ * Compile CFEngine. - It is advised to use Tokyo Cabinet as it gives much better performance in test suite over Berkeley DB. * Install fakeroot(1). If this tool is not available for your operating system, you may any other "fake root" environment or even sudo(1). Alternative tools are specified by --gainroot option of `testall' script. Note that if you use the --unsafe option (can damage your system), you may have to use --gainroot=sudo in order to get correct results. * If you want output in color, set CFENGINE_COLOR to 1. If you want diff output colorized, you also need to install the colordiff utility. ------------------------------------------------------------------------------ Running testsuite ------------------------------------------------------------------------------ All tests ought only to create files and directories in /tmp, and ought not to modify other files. The exception to this rule are so called unsafe tests, which reside in a special directory. More on unsafe tests below. Run ./testall --agent=$workdir/bin/cf-agent e.g. ./testall --agent=/var/cfengine/bin/cf-agent Testing will start. For every test case the name and result (failed / passed) will be produced. At the end testing summary will be provided. Test runner creates the following log files: * test.log contains detailed information about each test case (name, standard output/error contents, return code, and test status). * summary.log contains summary information, like the one displayed during testsuite run. Also a directory .succeeded will be created, containing stamps for each passed test case, so test cases which passed before and failing in subsequent testsuite run will be additionally marked in output as "(UNEXPECTED FAILURE)". You might run a subset of tests by passing either filenames: ./testall --agent=$workdir/bin/cf-agent 01_vars/01_basic/sysvars.cf or directories to 'testall': ./testall --agent=$workdir/bin/cf-agent 01_vars ------------------------------------------------------------------------------ Creating/editing test cases ------------------------------------------------------------------------------ Each test should be 100% standalone, and must contain at least 1 of the main bundles: init setup, create initial and hoped-for final states test the actual test code check the comparison of expected and actual results Look in default.cf for some standard check bundles (for example, to compare files when testing file edits, or for cleaning up temporary files). Tests should be named with short names describing what they test, using lower- case letters and underscores only. If the test is expected to generate a crash or error (that is, if they contan syntax errors or other faults), it should have an additional '.x' suffix before '.cf' (e.g. 'string_vars.x.cf'). Tests which are not expected to pass yet (e.g. there is a bug in code which prevents tests from passing) should be placed in 'staging' subdirectory in the test directory where they belong. Such test cases will be only run if --staging argument to ./testall is passed. Tests which modify the system outside of /tmp are so called unsafe tests, and should be placed in the 'unsafe' subdirectory in the directory where they belong. Such test cases have the potential to damage the host system and will only be run if the --unsafe argument is given to ./testall. For the user's protection, this option is needed even if the test file name is specified directly on the command line. Tests which need network connectivity should be placed to 'network' subdirectories. Those tests may be disabled by passing --no-network option to 'testall'. NOTE: Since the class 'ok' is used in most tests, never create a persistent class called 'ok' in any test. Persistent classes are cleaned up between test runs, but better safe than sorry. All tests should contain three bundles: init, test and check. In the "body common control" this file should be included, and bundlesequence should be set to default("$(this.promise_filename)"). Output "$(this.promise_filename) Pass" for passing and "$(this.promise_filename) FAIL" for failing. If you want to use tools like grep, diff, touch, etc, please use the $(G.grep) format so that the correct path to the tool is chosen by the test template. If a tool is missing you can add it to dcs.cf.sub. ------------------------------------------------------------------------------ Waiting in tests ------------------------------------------------------------------------------ If your test needs to wait for a significant amount of time, for example in order for locks to expire, you should use the wait functionality in the test suite. It requires three parts: 1. Your test needs to be put in a "timed" directory. 2. Whenever you want to wait, use the "dcs_wait($(this.promise_filename), )" method to wait the specified number of seconds. 3. Each test invocation will have a predefined class set, "test_pass_", where is the current pass number starting from one. This means you can wait several times. The test suite will keep track of time, and run other tests while your test is waiting. Some things to look out for though: - During the wait time, your test is no longer running, so you cannot for example do polling. - You cannot leave daemons running while waiting, because it may interfere with other tests. If you need that you will have to wait the traditional way, by introducing sleeps in the policy itself. - The timing is not guaranteed to be accurate to the second. The test will be resumed as soon as the current test has finished running, but if it takes a long time, this will add to the wait time. ------------------------------------------------------------------------------ Handling different platforms ------------------------------------------------------------------------------ For tests that need to be skipped on certain platforms, you can add special meta variables to one of the test bundles. These are the possible variable names: - test_skip_unsupported Skips a test because it makes no sense on that platform (e.g. symbolic links on Windows). - test_skip_needs_work Skips a test because the test itself is not adapted to the platform (even if the functionality exists). - test_suppress_fail Runs the test, but will accept failure. Use this when there is a real failure, but it is acceptable for the time being. This variable requires a meta tag on the the variable set to "redmine", where is a Redmine issue number. In all cases, the variable is expected to be set to a class expression suitable for ifvarclass, where a positive match means that the test will be skipped. So the expression '"test_skip_needs_work" string => "hpux|aix";' will skip the test on HP-UX and AIX, and nowhere else. Example: bundle agent test { meta: # Class expression giving platforms that should be skipped. "test_skip_unsupported" string => "hpux"; } bundle agent test { meta: # Class expression giving platforms that should be skipped. "test_skip_needs_work" string => "hpux"; } bundle agent test { meta: # Class expression giving platforms where we suppress a failure. "test_suppress_fail" string => "hpux", meta => { "redmine1234" }; } ------------------------------------------------------------------------------ Glossary ------------------------------------------------------------------------------ For purposes of testing, here is what our terms mean: Pass: the test did what we expected (whether that was setting a variable, editing a file, killing or starting a process, or correctly failing to do these actions in the light of existing conditions or attributes). Note that in the case of tests that end in an 'x', a Pass is generated when the test abnormally terminates and we wanted it to do that. FAIL: not doing what we wanted: either test finished and returned "FAIL" from check bundle, or something went wrong - cf-agent might have dropped core, cf-promises may have denied execution of the promises, etc. FAILed to crash: test was expected to crash, but did not. This is another kind of failure, split into separate kind due to low impact. Skipped: test is skipped due to be either explicitly disabled or being Nova-specific and being run on Community cf-agent. cfengine-3.6.2/tests/acceptance/19_security/0000755000175100017510000000000012316547775020445 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/19_security/other_writeable/0000755000175100017510000000000012332665147023614 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/19_security/other_writeable/other_write.cf0000644000175100017510000000271712332665147026470 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check defaults # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: # This extracts the octal mode, and decimal nlink, uid, gid, size "policy_file" string => ' body common control { bundlesequence => { "test" }; } bundle agent test { reports: "We\'re not in KS anymore toto."; }'; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", edit_defaults => empty, edit_line => insert_lines("$(g.policy_file)"), perms => m("602"); } ####################################################### bundle agent test { vars: "agent_output" string => execresult("$(sys.cf_agent) -f $(G.testfile)", "noshell"); classes: "security_exception" expression => regcmp(".*is writable by others (security exception).*", "$(agent_output)"), comment => "It's a security risk to evaluate policy that is writeable by users other than the owner"; } ####################################################### bundle agent check { classes: "ok" expression => "!security_exception"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/19_security/other_writeable/group_write.cf0000644000175100017510000000310012332665147026466 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check defaults # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: # This extracts the octal mode, and decimal nlink, uid, gid, size "policy_file" string => ' body common control { bundlesequence => { "test" }; } bundle agent test { reports: "Dorothy: How do you talk if you don\'t have a brain?"; "Scarecrow: Well, some people without brains do an awful lot of talking don\'t they?"; }'; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", edit_defaults => empty, edit_line => insert_lines("$(g.policy_file)"), perms => m("620"); } ####################################################### bundle agent test { vars: "agent_output" string => execresult("$(sys.cf_agent) -f $(G.testfile)", "noshell"); classes: "security_exception" expression => regcmp(".*is writable by others (security exception).*", "$(agent_output)"), comment => "It's a security risk to evaluate policy that is writeable by users other than the owner"; } ####################################################### bundle agent check { classes: "ok" expression => "!security_exception"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/0000755000175100017510000000000012411001073017504 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/03_lists/0000755000175100017510000000000012412221023021144 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaces/0000755000175100017510000000000012332665147023307 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaces/passing_slists3.cf0000644000175100017510000000166312332665147026757 0ustar00a10038a1003800000000000000# Redmine#4494 # the agent should not try to process files promises on the unexpanded # version of a passed list # here, the error manifests as "Failed to chdir into @(given_watch)" # but it also generates a NOTKEPT compliance entry body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "output" string => execresult("$(sys.cf_agent) -K -f $(this.promise_filename).sub | $(G.grep) 'Failed to chdir' 2>&1", "useshell"); } bundle agent check { methods: "pass" usebundle => dcs_check_regcmp(".*Failed to chdir into '@.given_watch.'.*", $(test.output), $(this.promise_filename), "true"); reports: EXTRA:: "Output = $(test.output)"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaces/passing_slists3.cf.sub0000644000175100017510000000241512316547775027553 0ustar00a10038a1003800000000000000# Redmine#4494 # - passing a slist to a non-namespaced agent bundle (works) # - passing a slist to a namespaced agent bundle with no "classes" promises (works) # - passing a slist to a namespaced agent bundle with a "classes" promises (emits spurious "Failed to chdir..." message) body common control { bundlesequence => { test }; } bundle agent test { vars: "watch" slist => { "/" }; methods: "watch" usebundle => watch(@(test.watch)); "nswatch" usebundle => ns:watch(@(test.watch)); "ns2watch" usebundle => ns2:watch(@(test.watch)); } bundle agent watch(given_watch) { classes: vars: "watch" slist => { @(given_watch) }; files: "$(watch)"; reports: "$(this.namespace):$(this.bundle): got local watch = $(watch)"; } body file control { namespace => "ns"; } bundle agent watch(given_watch) { classes: vars: "watch" slist => { @(given_watch) }; files: "$(watch)"; reports: "$(this.namespace):$(this.bundle): got local watch = $(watch)"; } body file control { namespace => "ns2"; } bundle agent watch(given_watch) { vars: "watch" slist => { @(given_watch) }; files: "$(watch)"; reports: "$(this.namespace):$(this.bundle): got local watch = $(watch)"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaces/passing_slists.cf0000644000175100017510000000116412316547775026700 0ustar00a10038a1003800000000000000body common control { inputs => { "../../../default.cf.sub", "passing_slists.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "mylist___mylist_" }; } bundle common g { vars: "slist_pass" slist => { "1", "2", "3" }; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace(@(g.slist_pass)); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace(join(",", "g.slist_pass"), "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaces/passing_slists.cf.sub0000644000175100017510000000165712332665147027467 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle agent test_in_namespace(passed_list) { vars: "mylist" slist => { @(passed_list) }; "joined" string => join(",", "mylist"); classes: "mylist_$(mylist)" expression => "any"; reports: default:DEBUG:: "BUG: mylist___mylist_ was defined!" ifvarclass => "mylist___mylist_"; "BUG: mylist_1 not defined" ifvarclass => "!mylist_1"; "GOOD: mylist_1 was defined" ifvarclass => "mylist_1"; "mylist = $(b:test_in_namespace.mylist)"; "mylist without namespace = $(test_in_namespace.mylist)"; "mylist without qualifiers = $(mylist)"; "Set joined to $(joined)"; } bundle agent check_in_namespace(target,test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.joined)", "$(target)", "$(test)", "no"); reports: default:DEBUG:: "comparing '$(b:test_in_namespace.joined)' and '$(target)'"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaces/passing_slists2.cf0000644000175100017510000000110612332665147026746 0ustar00a10038a1003800000000000000# Redmine#4494 # the agent should not abort when a bundle is passed a qualified slist # name that doesn't actually exist body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { methods: "watch" usebundle => watch(@(run.watch)); } bundle agent check { methods: "pass" usebundle => dcs_passif("any", $(this.promise_filename)); } bundle agent watch(given_watch) { vars: "watch" slist => { @(given_watch) }; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaced_list_including_list_expanded.cf.sub0000644000175100017510000000117312316547775032376 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "go" }; version => "1.0"; } bundle agent go { methods: "if you like then you better put a namespace on it" usebundle => test:namespace_check; } body file control { namespace => "test"; } bundle agent namespace_check { classes: "server" expression => "any"; vars: "packages" slist => { "mysql-client", "mysql-common" }, policy => "free"; "server_packages" slist => { "mysql-server", "mysql-server-core" }, policy => "free"; "all_packages" slist => { @(packages), @(server_packages) }, policy => "free"; reports: "$(all_packages)"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/007.cf0000644000175100017510000000127312236160673022010 0ustar00a10038a1003800000000000000# Test that cf_null lists can be joined body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => ""; } bundle agent test { vars: "dummy" string => ""; } bundle agent check { vars: "emptylist" slist => { "cf_null" }; "joined" string => join(":", "emptylist"); classes: "ok1" expression => strcmp($(joined), ""); "ok" and => { "ok1" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG:: "Expected empty string, got $(joined)!"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/015.cf0000644000175100017510000000312212332665147022005 0ustar00a10038a1003800000000000000####################################################### # # Iteration on slist of size 1 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => ""; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle edit_line test_insert { vars: "one" slist => { }; insert_lines: "$(one)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/011.cf0000644000175100017510000000254712332665147022013 0ustar00a10038a1003800000000000000####################################################### # # Test list iteration over cf_null special blank characters, all blank # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_list_null, edit_defaults => init_empty; } bundle edit_line test_list_null { vars: "lines" slist => { "cf_null", "cf_null", "cf_null" }; insert_lines: "$(lines)" whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/004.cf0000644000175100017510000000331012332665147022002 0ustar00a10038a1003800000000000000####################################################### # # Iterations of non-local slists # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => " a b c"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle agent otherbundle { vars: "one" slist => { "a", "b", "c" }; } bundle edit_line test_insert { vars: "one" slist => { "c", "b", "a" }; insert_lines: "$(otherbundle.one)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/interpolation_order.cf0000644000175100017510000000160512332665147025566 0ustar00a10038a1003800000000000000# Redmine#3122: ensure lists are interpolated in the correct order body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "first_list" slist => { "item1", "item2", "item3", "item4", "item5" }; } bundle agent test { vars: "local" slist => { @(second_list) }; "second_list" slist => { @(init.first_list), "item6" }; } bundle agent check { vars: "expected" string => '{ "item1", "item2", "item3", "item4", "item5", "item6" }'; "joined" string => format("%S", "test.local"); methods: "check" usebundle => dcs_check_strcmp($(expected), $(joined), "$(this.promise_filename)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/016.cf0000644000175100017510000000241112412221023021762 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #2936: Check that list variables under reserved scope expand # as they should. The initial bug report was for reports promises only, # but here we check it for files promises. # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { # TODO delete the testfile } bundle agent test { meta: "test_suppress_fail" string => "hpux|windows|sunos_5_11", meta => { "redmine4745", "redmine4963" }; files: "$(G.testfile).actual" create => "true", edit_defaults => init_empty, edit_line => test_insert_macs; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line test_insert_macs { insert_lines: "$(sys.hardware_addresses)"; } bundle agent check { # If the file contains the string "sys.hardware_addresses" then we # failed to expand the variable! classes: "ok" not => regline(".*sys\.hardware_addresses.*", "$(G.testfile).actual"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/008.cf0000644000175100017510000000266712332665147022024 0ustar00a10038a1003800000000000000####################################################### # # Test list iteration over cf_null special blank character, start of list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "expected" string => "1 2 3"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert("$(expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_list_null, edit_defaults => init_empty; } bundle edit_line test_list_null { vars: "lines" slist => { "cf_null", "1", "2", "3" }; insert_lines: "$(lines)" whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/namespaced_list_including_list_expanded.cf0000644000175100017510000000233612332665147031600 0ustar00a10038a1003800000000000000# Redmine#4445: Ensure that namespaced lists that include other lists are fully expanded body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "agent_output" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "noshell"); } bundle agent check { classes: "unexpanded_list" expression => regcmp(".*packages.*", $(test.agent_output)), comment => "check to see if an included list is unexpanded"; "found_from_packages" expression => regcmp(".*mysql-client.*", $(test.agent_output)), comment => "found something good from one list"; "found_from_server_packages" expression => regcmp(".*mysql-server.*", $(test.agent_output)), comment => "found something good from one list"; "found_expected_output" and => { "found_from_packages", "found_from_server_packages" }, comment => "Found something good from both included lists"; "ok" expression => "!unexpanded_list.found_expected_output"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/013.cf0000644000175100017510000000257512332665147022016 0ustar00a10038a1003800000000000000# Test expansion of remote arrays containing lists body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; nova_edition:: host_licenses_paid => "5"; } bundle agent init { vars: "array[one]" string => "1"; "array[two]" string => "2"; "array[list]" slist => { "first", "second", "last" }; "keys" slist => { "one", "two", "list" }; "expected" string => " 1 2 first second last"; "actual" string => ""; "states" slist => { "expected", "actual" }; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$($(states))"), edit_defaults => init_empty; } bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle edit_line test_insert { insert_lines: "$(init.array[$(init.keys)])"; } bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); reports: DEBUG:: "can expand $(init.array[$(init.keys)])"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/014.cf0000644000175100017510000000326512332665147022014 0ustar00a10038a1003800000000000000####################################################### # # Iteration on non-local empty slist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => ""; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle agent otherbundle { vars: "list" slist => { }; } bundle edit_line test_insert { vars: "list" slist => { "a", "b", "c" }; insert_lines: "$(otherbundle.list)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/extend_list.cf0000644000175100017510000000475612400110676024024 0ustar00a10038a1003800000000000000####################################################### # # Test that slists can be extended (redefined using its own previous value) # Redmine:4335 and 6541 ####################################################### body common control { AUTO:: inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; !AUTO:: bundlesequence => { "init", "test", "check" }; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "x" slist => { "xyz" }, policy => "free"; "x" slist => { @(x), "extended" }, policy => "free"; "x" slist => { @(x), "more" }, policy => "free"; "x1" slist => { @(x), @(undefined1), @(undefined2) }, policy => "ifdefined"; "x2" slist => { @(undefined1), @(x), @(undefined2) }, policy => "ifdefined"; "x3" slist => { @(undefined1), @(undefined2), @(x) }, policy => "ifdefined"; "x4" slist => { @(x), @(undefined1), @(undefined2), @(x) }, policy => "ifdefined"; "x5" slist => { @(undefined1), "entry", @(undefined2) }, policy => "ifdefined"; } ####################################################### bundle agent check { vars: "expected" string => "xyz,extended,more"; "joined_test_x" string => join(",", "test.x"); "joined_test_x1" string => join(",", "test.x1"); "joined_test_x2" string => join(",", "test.x2"); "joined_test_x3" string => join(",", "test.x3"); "joined_test_x4" string => join(",", "test.x4"); "joined_test_x5" string => join(",", "test.x5"); classes: "ok0" expression => strcmp($(expected), $(joined_test_x)); "ok1" expression => strcmp($(expected), $(joined_test_x1)); "ok2" expression => strcmp($(expected), $(joined_test_x2)); "ok3" expression => strcmp($(expected), $(joined_test_x3)); "ok4" expression => strcmp("$(expected),$(expected)", $(joined_test_x4)); "ok5" expression => strcmp("entry", $(joined_test_x5)); "ok" and => { "ok0", "ok1", "ok2", "ok3", "ok4", "ok5" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG.!ok0:: "x: $(joined_test_x)"; DEBUG.!ok1:: "x1: $(joined_test_x1)"; DEBUG.!ok2:: "x2: $(joined_test_x2)"; DEBUG.!ok3:: "x3: $(joined_test_x3)"; DEBUG.!ok4:: "x4: $(joined_test_x4)"; DEBUG.!ok5:: "x5: $(joined_test_x5)"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/003.cf0000644000175100017510000000313612332665147022007 0ustar00a10038a1003800000000000000####################################################### # # Iteration on slist of size 1 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => " a"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle edit_line test_insert { vars: "one" slist => { "a" }; insert_lines: "$(one)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/005.cf0000644000175100017510000000353112332665147022010 0ustar00a10038a1003800000000000000####################################################### # # Iterations of non-local slists # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => " XX XXX XXXX"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle agent otherbundle { vars: "list" slist => { "one", "two", "three" }; } bundle edit_line test_insert { vars: "array[one]" string => "XX"; "array[two]" string => "XXX"; "array[three]" string => "XXXX"; "list" slist => { "three", "two", "one" }; insert_lines: "$(array[$(otherbundle.list)])"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/006.cf0000644000175100017510000000107612243421446022004 0ustar00a10038a1003800000000000000# Test that reglist() does not match cf_null values body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => ""; } bundle agent test { vars: "dummy" string => ""; } bundle agent check { vars: "emptylist" slist => { "cf_null" }; classes: "ok" not => reglist("@(emptylist)", ".+"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/009.cf0000644000175100017510000000266212332665147022020 0ustar00a10038a1003800000000000000####################################################### # # Test list iteration over cf_null special blank character, mid list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "expected" string => "1 2 3"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert("$(expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_list_null, edit_defaults => init_empty; } bundle edit_line test_list_null { vars: "lines" slist => { "1", "cf_null", "2", "3" }; insert_lines: "$(lines)" whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/002.cf0000644000175100017510000000314412332665147022005 0ustar00a10038a1003800000000000000####################################################### # # Iterations of slists # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => " a b c"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle edit_line test_insert { vars: "one" slist => { "a", "b", "c" }; insert_lines: "$(one)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/staging/0000755000175100017510000000000012411001073022600 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/03_lists/staging/interpolation_empty_lists.cf0000644000175100017510000000157212411001073030442 0ustar00a10038a1003800000000000000# ensure interpolated empty lists don't drag in cf_null body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "list" slist => { "item1", "item2", "item3", "item4", "item5" }; } bundle agent test { vars: "local" slist => { }; # should *not* bring in cf_null "splice" slist => { @(init.list), @(local) }; } bundle agent check { vars: "expected" string => '{ "item1", "item2", "item3", "item4", "item5" }'; "joined" string => format("%S", "test.splice"); methods: "check" usebundle => dcs_check_strcmp($(expected), $(joined), "$(this.promise_filename)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/001.cf0000644000175100017510000000334612411001073021764 0ustar00a10038a1003800000000000000####################################################### # # Nested iterations of slists (the ordering is not guaranteed, so we sort) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => " a x a y a z b x b y b z c x c y c z"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle edit_line test_insert { vars: "one" slist => { "a", "b", "c" }; "two" slist => { "x", "y", "z" }; insert_lines: "$(one) $(two)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/usebundle_naked.cf0000644000175100017510000000142712332665147024636 0ustar00a10038a1003800000000000000# Test usebundle passing a naked list from local scope body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "expected" string => "1,2,3"; } bundle agent test { vars: "testlist" slist => {"1","2","3"}; methods: "call sub" usebundle => sub(@{testlist}); } bundle agent sub(sublist) { vars: "joined" string => join(",", "sublist"); reports: DEBUG:: "sub joined $(joined)"; } bundle agent check { methods: "check results" usebundle => dcs_check_strcmp("$(init.expected)", "$(sub.joined)", "$(this.promise_filename)", "no"); reports: DEBUG:: "comparing '$(init.expected)' with '$(sub.joined)'"; } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/010.cf0000644000175100017510000000266512332665147022013 0ustar00a10038a1003800000000000000####################################################### # # Test list iteration over cf_null special blank character, end of list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "expected" string => "1 2 3"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert("$(expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_list_null, edit_defaults => init_empty; } bundle edit_line test_list_null { vars: "lines" slist => { "1", "2", "3", "cf_null" }; insert_lines: "$(lines)" whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/03_lists/012.cf0000644000175100017510000000351212332665147022005 0ustar00a10038a1003800000000000000####################################################### # # Iterations of non-local slists inside non-local (sclar) array # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => ""; "expected" string => " XX XXX XXXX"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert; } bundle agent otherbundle { vars: "array[one]" string => "XX"; "array[two]" string => "XXX"; "array[three]" string => "XXXX"; "list" slist => { "one", "two", "three" }; } bundle edit_line test_insert { insert_lines: "$(otherbundle.array[$(otherbundle.list)])"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_sort("$(G.testfile).actual", "$(G.testfile).actual.sorted"); "any" usebundle => dcs_sort("$(G.testfile).expected", "$(G.testfile).expected.sorted"); "any" usebundle => dcs_check_diff("$(G.testfile).actual.sorted", "$(G.testfile).expected.sorted", "$(this.promise_filename)"); } body contain check_in_shell { useshell => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/0000755000175100017510000000000012316547775022210 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/04_containers/extraction.cf0000644000175100017510000000236512316547775024710 0ustar00a10038a1003800000000000000####################################################### # # Redmine#4301: "Couldn't find extracted variable" # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "config" data => parsejson('{"*.alert": "root"}'); files: "$(G.testfile).actual" create => "true", edit_line => test_set_line_based("test.config", " ", "\s+", ".*", "\s*#\s*"); } # this is the stdlib set_line_based cut down bundle edit_line test_set_line_based(v, sep, bp, kp, cp) { vars: # even though it's not used in the iteration, the vkeys variable # is required for the test to fail "vkeys" slist => getindices("$(v)"); "i" slist => grep($(kp), vkeys); # Escape the value (had a problem with special characters and regex's) "ev[$(i)]" string => escape("$($(v)[$(i)])"); } ####################################################### bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson_null.cf0000644000175100017510000000253612243421446025350 0ustar00a10038a1003800000000000000####################################################### # # Test datas creation from a null through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: 'null'; } bundle edit_line init_insert_lines { insert_lines: "$(const.dollar)(test.load)"; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/parsejson.cf0000644000175100017510000000222312243421446024506 0ustar00a10038a1003800000000000000####################################################### # # Test parsejson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; } bundle edit_line init_insert_lines { insert_lines: 'a'; 'b'; 'c'; } ####################################################### bundle agent test { vars: "load" data => parsejson('["a", "b", "c"]'); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson_scalar.cf0000644000175100017510000000254212243421446025640 0ustar00a10038a1003800000000000000####################################################### # # Test datas creation from a scalar through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: '123456'; } bundle edit_line init_insert_lines { insert_lines: "$(const.dollar)(test.load)"; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson_objects.cf0000644000175100017510000000261712243421446026027 0ustar00a10038a1003800000000000000####################################################### # # Test nested datas iteration through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: '{ "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null}'; } bundle edit_line init_insert_lines { insert_lines: '1'; '2'; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/mergecontainer_arrays.cf0000644000175100017510000000240012243421446027062 0ustar00a10038a1003800000000000000####################################################### # # Test mergejson() with two JSON arrays # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; } bundle edit_line init_insert_lines { insert_lines: 'a'; 'b'; 'c'; } ####################################################### bundle agent test { vars: "load1" data => parsejson('["a", "b"]'); "load2" data => parsejson('["c"]'); "load" data => mergedata("load1", "load2"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/mergecontainer_conflict.cf0000644000175100017510000000257712243421446027401 0ustar00a10038a1003800000000000000####################################################### # # Test mergejson() with mismatched datas # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; } bundle edit_line init_insert_lines { insert_lines: "$(const.dollar)(test.load[third])"; } ####################################################### bundle agent test { vars: "load1" data => parsejson('["x": "y", "third"]'); "load2" data => parsejson(' { "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null } '); # this should fail "load" data => mergedata("load1", "load2"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load[third])"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/mergecontainer.cf0000644000175100017510000000251312316547775025525 0ustar00a10038a1003800000000000000####################################################### # # Test mergedata() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; } bundle edit_line init_insert_lines { insert_lines: 'a'; 'b'; 'c'; } ####################################################### bundle agent test { vars: "load1" data => parsejson('{"x": "y", "third": 123}'); "load2" data => parsejson(' { "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null } '); "load" data => mergedata("load1", "load2"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load[third])"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/parsejson_indexed.cf0000644000175100017510000000233112243421446026206 0ustar00a10038a1003800000000000000####################################################### # # Test parsejson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; } bundle edit_line init_insert_lines { insert_lines: 'a'; 'b'; 'c'; } ####################################################### bundle agent test { vars: "load" data => parsejson(' { "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null } '); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load[third])"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson_arrays.cf0000644000175100017510000000262412243421446025675 0ustar00a10038a1003800000000000000####################################################### # # Test nested datas iteration through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: '[ 1, 2, 3, [ "a", "b", "c" ], "d", 5, null]'; } bundle edit_line init_insert_lines { insert_lines: '1'; '2'; '3'; 'd'; '5'; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson_subindex.cf0000644000175100017510000000265112243421446026215 0ustar00a10038a1003800000000000000####################################################### # # Test subreferencing of datas loaded through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: '{ "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null}'; } bundle edit_line init_insert_lines { insert_lines: 'a'; 'b'; 'c'; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load[third])"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson.cf0000644000175100017510000000253412243421446024314 0ustar00a10038a1003800000000000000####################################################### # # Test datas creation through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: '[ "hello", "there" ]'; } bundle edit_line init_insert_lines { insert_lines: "hello"; "there"; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.load)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/passing_containers.cf0000644000175100017510000000234612243421446026401 0ustar00a10038a1003800000000000000####################################################### # # Test passing of datas with @(ref) notation # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; } bundle edit_line init_insert_lines { insert_lines: '1'; '2'; } ####################################################### bundle agent test { vars: "load" data => parsejson(' { "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null} '); files: "$(G.testfile).actual" create => "true", edit_line => test_insert(@(load)); } bundle edit_line test_insert(data) { insert_lines: "$(data)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/04_containers/readjson_subindex_quoted.cf0000644000175100017510000000304012243421446027567 0ustar00a10038a1003800000000000000####################################################### # # Test subreferencing with quoted keys of datas loaded through readjson() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert_lines; "$(G.testfile).json" create => "true", edit_line => init_insert_json; } bundle edit_line init_insert_json { insert_lines: '{ "first": 1, "seconds": 2, "third key! can? almost be anything& but no dollar or bracket yet": [ "a", "b", "c" ]}'; } bundle edit_line init_insert_lines { insert_lines: 'a'; 'b'; 'c'; } ####################################################### bundle agent test { vars: "load" data => readjson("$(G.testfile).json", 1024); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: '$(test.load[third key! can? almost be anything& but no dollar or bracket yet])'; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/0000755000175100017510000000000012412512360022024 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/countlinesmatching.cf0000644000175100017510000000253112316547775026262 0ustar00a10038a1003800000000000000# Test that countlinesmatching works correctly body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { } bundle agent test { vars: # meta comment 1 # meta comment 2 # meta comment 3 # meta comment 4 "metagrep" int => countlinesmatching(".*# meta comment.*", $(this.promise_filename)); "exactgrep" int => countlinesmatching("bundle agent test", $(this.promise_filename)); "nullgrep" int => countlinesmatching("blue hippo, purple elephant, yellow submarine", $(this.promise_filename)); } bundle agent check { classes: "ok" and => { strcmp("$(test.metagrep)", "5"), # the 4 comments plus the pattern! strcmp("$(test.exactgrep)", "1"), strcmp("$(test.nullgrep)", "0") }; reports: DEBUG:: "Grepping for 'meta comment' found $(test.metagrep) matches, expected 5"; "Grepping for exactly 'bundle agent test' found $(test.exactgrep) matches, expected 1"; "Grepping for children's rhyme found $(test.nullgrep) matches, expected 0"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/datastate.cf0000644000175100017510000000411412316547775024335 0ustar00a10038a1003800000000000000# Test that the datastate() function gives good data body common control { inputs => { "../../default.cf.sub", "datastate.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { classes: "a" expression => "any", scope => "namespace"; "b" expression => "any"; "c" expression => "!any"; vars: "x" string => "1"; "y" data => parsejson('{"ykey":["yvalue1", "yvalue2"]}'); "z" slist => { "z1", "z2", "z3" }; } bundle agent test { vars: "state" data => datastate(); } bundle agent check { vars: "init_state_str" string => format("%S", "test.state[vars][init]"); "ns_state_str" string => format("%S", "test.state[vars][visible_namespace:included]"); "known_classes" slist => getindices("test.state[classes]"); "printed_classes" string => format("%S", known_classes); "init_expected" string => '{"x":"1","y":{"ykey":["yvalue1","yvalue2"]},"z":["z1","z2","z3"]}'; "ns_expected" string => '{"i":"1","l":[1,"l","|"],"j":"two","k":["k2","everest"]}'; classes: "init_ok" expression => strcmp($(init_state_str), $(init_expected)); "ns_ok" expression => strcmp($(ns_state_str), $(ns_expected)); "classes_ok" and => { some("cfengine_3", known_classes), some("a", known_classes), some("visible_namespace:foo", known_classes) }; "ok" and => { "init_ok", "ns_ok", "classes_ok" }; reports: DEBUG.!ns_ok:: "visible_namespace:included data state is $(ns_state_str)"; "expected visible_namespace:included state is $(ns_expected)"; "expected state != visible_namespace:included data state"; DEBUG.!init_ok:: "init data state is $(init_state_str)"; "expected init state is $(init_expected)"; "expected init state != init data state"; DEBUG.!classes_ok:: "expected classes a, visible_namespace:foo, and cfengine_3 were not in $(printed_classes)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/204.cf0000644000175100017510000000305412243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test getindices(), size 5 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "alpha"; "beta"; "gamma's"; "delta-delta:delta"; "last"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "two"; "array[gamma's]" string => "three's"; "array[delta-delta:delta]" string => "four-fore:quatre"; "array[last]" string => "last"; "keys" slist => getindices("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(keys)"; } bundle edit_line test_insert { vars: "keys" slist => { @{test.keys} }; insert_lines: "$(keys)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/701.cf0000644000175100017510000000131112243421446022647 0ustar00a10038a1003800000000000000# Test that countclassesmatching works correctly (Mantis #975) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { classes: "test_fbeae67f3e347b5e0032302200141131" expression => "any"; "test_fbeae67f3e347b5e0032302200141131_1" expression => "any"; } bundle agent test { vars: "num" int => countclassesmatching("test_fbeae67f3e347b5e0032302200141131.*"); } bundle agent check { classes: "ok" expression => strcmp("$(test.num)", "2"); reports: DEBUG:: "$(test.num)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/text_xform.cf0000644000175100017510000001441012332665147024552 0ustar00a10038a1003800000000000000####################################################### # # Test the * functions() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "tests" slist => { "q1", "q2", "q3" }; "offsets" ilist => { "0", "1", "20", "26", "27", "28" }; "fn1" slist => { "string_head", "string_tail" }; "data[q1]" string => "this is the Question"; "data[q2]" string => ""; "data[q3]" string => "some text is not $(const.t) simple "; "data[$(tests)_string_reverse]" string => string_reverse("$(data[$(tests)])"); "data[$(tests)_string_length]" int => string_length("$(data[$(tests)])"); "data[$(tests)_string_upcase]" string => string_upcase("$(data[$(tests)])"); "data[$(tests)_string_downcase]" string => string_downcase("$(data[$(tests)])"); "data[$(tests)_string_head_$(offsets)]" string => string_head("$(data[$(tests)])", $(offsets)); "data[$(tests)_string_tail_$(offsets)]" string => string_tail("$(data[$(tests)])", $(offsets)); "expected[q1_string_reverse]" string => "noitseuQ eht si siht"; "expected[q1_string_length]" int => "20"; "expected[q1_string_upcase]" string => "THIS IS THE QUESTION"; "expected[q1_string_downcase]" string => "this is the question"; "expected[q1_string_head_0]" string => ""; "expected[q1_string_tail_0]" string => ""; "expected[q1_string_head_1]" string => "t"; "expected[q1_string_tail_1]" string => "n"; "expected[q1_$(fn1)_20]" string => "$(data[q1])"; "expected[q1_$(fn1)_26]" string => "$(data[q1])"; "expected[q1_$(fn1)_27]" string => "$(data[q1])"; "expected[q1_$(fn1)_28]" string => "$(data[q1])"; "expected[q2_string_reverse]" string => ""; "expected[q2_string_length]" int => "0"; "expected[q2_string_upcase]" string => ""; "expected[q2_string_downcase]" string => ""; "expected[q2_$(fn1)_$(offsets)]" string => ""; "expected[q3_string_reverse]" string => " elpmis $(const.t) ton si txet emos"; "expected[q3_string_length]" int => "27"; "expected[q3_string_upcase]" string => "SOME TEXT IS NOT $(const.t) SIMPLE "; "expected[q3_string_downcase]" string => "$(data[q3])"; "expected[q3_$(fn1)_0]" string => ""; "expected[q3_string_head_1]" string => "s"; "expected[q3_string_tail_1]" string => " "; "expected[q3_string_head_20]" string => "some text is not $(const.t) s"; "expected[q3_string_tail_20]" string => "xt is not $(const.t) simple "; "expected[q3_string_head_26]" string => "some text is not $(const.t) simple "; "expected[q3_string_tail_26]" string => "ome text is not $(const.t) simple "; "expected[q3_$(fn1)_27]" string => "$(data[q3])"; "expected[q3_$(fn1)_28]" string => "$(data[q3])"; } ####################################################### bundle agent check { vars: "tests" slist => { @(test.tests) }; "fn0" slist => { "string_reverse", "string_length", "string_upcase", "string_downcase" }; "fn1" slist => { @(test.fn1) }; "offsets" ilist => { @(test.offsets) }; classes: "ok_$(tests)_$(fn0)" expression => strcmp("$(test.expected[$(tests)_$(fn0)])", "$(test.data[$(tests)_$(fn0)])"); "not_ok_$(tests)_$(fn0)" not => strcmp("$(test.expected[$(tests)_$(fn0)])", "$(test.data[$(tests)_$(fn0)])"); "ok_$(tests)_$(fn1)_$(offsets)" expression => strcmp("$(test.expected[$(tests)_$(fn1)_$(offsets)])", "$(test.data[$(tests)_$(fn1)_$(offsets)])"); "not_ok_$(tests)_$(fn1)_$(offsets)" not => strcmp("$(test.expected[$(tests)_$(fn1)_$(offsets)])", "$(test.data[$(tests)_$(fn1)_$(offsets)])"); "ok" and => { 'ok_q1_string_reverse', 'ok_q2_string_reverse', 'ok_q3_string_reverse', 'ok_q1_string_length', 'ok_q2_string_length', 'ok_q3_string_length', 'ok_q1_string_upcase', 'ok_q2_string_upcase', 'ok_q3_string_upcase', 'ok_q1_string_downcase', 'ok_q2_string_downcase', 'ok_q3_string_downcase', 'ok_q1_string_head_0', 'ok_q2_string_head_0', 'ok_q3_string_head_0', 'ok_q1_string_tail_0', 'ok_q2_string_tail_0', 'ok_q3_string_tail_0', 'ok_q1_string_head_1', 'ok_q2_string_head_1', 'ok_q3_string_head_1', 'ok_q1_string_tail_1', 'ok_q2_string_tail_1', 'ok_q3_string_tail_1', 'ok_q1_string_head_20', 'ok_q2_string_head_20', 'ok_q3_string_head_20', 'ok_q1_string_tail_20', 'ok_q2_string_tail_20', 'ok_q3_string_tail_20', 'ok_q1_string_head_26', 'ok_q2_string_head_26', 'ok_q3_string_head_26', 'ok_q1_string_tail_26', 'ok_q2_string_tail_26', 'ok_q3_string_tail_26', 'ok_q1_string_head_27', 'ok_q2_string_head_27', 'ok_q3_string_head_27', 'ok_q1_string_tail_27', 'ok_q2_string_tail_27', 'ok_q3_string_tail_27', 'ok_q1_string_head_28', 'ok_q2_string_head_28', 'ok_q3_string_head_28', 'ok_q1_string_tail_28', 'ok_q2_string_tail_28', 'ok_q3_string_tail_28' }; reports: DEBUG:: "OK: test $(tests) with function $(fn0) passes" ifvarclass => "ok_$(tests)_$(fn0)"; "NOT OK: test $(tests) with function $(fn0) failed; expected = '$(test.expected[$(tests)_$(fn0)])' actual = '$(test.data[$(tests)_$(fn0)])'" ifvarclass => "not_ok_$(tests)_$(fn0)"; "OK: test $(tests) with function $(fn1)($(offsets)) passes" ifvarclass => "ok_$(tests)_$(fn1)_$(offsets)"; "NOT OK: test $(tests) with function $(fn1)($(offsets)) failed; expected = '$(test.expected[$(tests)_$(fn1)_$(offsets)])' actual = '$(test.data[$(tests)_$(fn1)_$(offsets)])'" ifvarclass => "not_ok_$(tests)_$(fn1)_$(offsets)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/read-file-endless-loop.cf0000644000175100017510000000104412243421446026575 0ustar00a10038a1003800000000000000# Test that regline, getfields and countlinesmatching do not loop endlessly if # supplied with a directory (Redmine #2453) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { } bundle agent test { classes: "foo" expression => regline("foo", "/"); vars: "bar" int => getfields(".*", "/", ":", "foo"); "baz" int => countlinesmatching(".*", "/"); } bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/069.cf0000644000175100017510000000302012316547775022674 0ustar00a10038a1003800000000000000####################################################### # # Test getusers() arg0 and arg1, but expect a failure # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: # All users except r.*t [illegal!], bin, and daemon "users" slist => getusers("r.*t,bin","1,5,6,7"); files: "$(G.testfile)" delete => init_delete; reports: cfengine_3:: "$(users)" report_to_file => "$(G.testfile)"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: # Try to delete the lines that shouldn't be there anyway "$(G.testfile)" edit_line => test_delete, classes => full_set; } bundle edit_line test_delete { delete_lines: "root"; "daemon"; "bin"; } body classes full_set { promise_kept => { "fail" }; promise_repaired => { "pass" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { classes: "ok" expression => "pass&!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/execresult_multiples.cf0000644000175100017510000000217212412512360026621 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #2981: execresult and returnszero should not be run so much # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kv -f $(this.promise_filename).sub | $(G.egrep) 'execresult|returnszero'", "useshell"); } bundle agent check { # If the output contains CLASSONCE or RETONCE more than once, we fail classes: "ok1" not => regcmp(".*ran.*CLASSONCE.*ran.*CLASSONCE.*", "$(test.subout)"); "ok2" not => regcmp(".*ran.*RETONCE.*ran.*RETONCE.*", "$(test.subout)"); "ok" and => { "ok1", "ok2" }; reports: DEBUG:: "agent output: $(test.subout)"; ok1.ok2:: "The duplicate output in cf-agent didn't happen"; !(ok1.ok2):: "The duplicate output in cf-agent happened"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/data_readstringarrayidx.cf.txt0000644000175100017510000000445212316547775030105 0ustar00a10038a1003800000000000000# app_name;instance;mmax;mmin;mperm;zone;tomcat_version;env;setenv;app_properties;newrelic;newrelic_name;newrelic_version;context_static;checks;action;context some_app_config;9123;8192;512;192;europe;tomcat7;live;;this string is short and no problem at all;true;blah;2.0.3;false;true;fix;app_server working_app_config;9123;8192;512;192;europe;tomcat7;live;;.23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789.;true;blah;2.0.3;false;true;fix;app_server not_working_app_config;9123;8192;512;192;europe;tomcat7;live;;.23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..;true;blah;2.0.3;false;true;fix;app_server cfengine-3.6.2/tests/acceptance/01_vars/02_functions/443.cf0000644000175100017510000000603312243421446022660 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarrayidx(), introduce a non-parsed comment # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 # Not parsed as a comment this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "4"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "# Not parsed as a comment"), strcmp("$(test.ary[2][0])", "this"), strcmp("$(test.ary[2][1])", "is"), strcmp("$(test.ary[2][2])", "a"), strcmp("$(test.ary[2][3])", "test"), strcmp("$(test.ary[3][0])", "1"), strcmp("$(test.ary[3][1])", "2"), strcmp("$(test.ary[3][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][1]"), isvariable("test.ary[2][4]"), isvariable("test.ary[3][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/420.cf0000644000175100017510000000565712400110676022661 0ustar00a10038a1003800000000000000####################################################### # # Test parsestringarray(), simple # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","NoComment",":",10,1000); # ensure that bare words are OK "ignore" int => parsestringarray("ary", "mydata","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "is"), strcmp("$(test.ary[this][2])", "a"), strcmp("$(test.ary[this][3])", "test"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[this][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/018.cf0000644000175100017510000000307612243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456 789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/0000755000175100017510000000000012332665147024160 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/003_namespaced_getindices.cf.sub0000644000175100017510000000063512332665147032146 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace(array_name, array_name2) { vars: "repo_ids3" slist => getindices("$(array_name2)"); } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids3)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/002_namespaced_getindices.cf.sub0000644000175100017510000000063612332665147032146 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace(array_name, array_name2) { vars: "repo_ids2" slist => getindices("default:g.array"); } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids2)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/103_namespaced_getindices.cf.sub0000644000175100017510000000067012332665147032146 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace { vars: "array_name2" string => "b:variables.array2"; "repo_ids3" slist => getindices("$(array_name2)"); } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids3)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/103.cf0000644000175100017510000000134512236160673024775 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 103: getindices() with local variable argument, from non-default namespace to the same namespace # same as 003.cf but without using a parameter body common control { inputs => { "../../../default.cf.sub", "103_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace; } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/004.cf0000644000175100017510000000132512236160673024773 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 004: getindices() with constant argument, from non-default namespace to the same namespace. body common control { inputs => { "../../../default.cf.sub", "004_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace("default:g.array", "b:variables.array2"); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/203.cf0000644000175100017510000000140412236160673024772 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 003: getindices() with parameter variable argument, from non-default namespace to the same namespace, but with getindices() inside braces. body common control { inputs => { "../../../default.cf.sub", "203_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace("default:g.array", "b:variables.array2"); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/203_namespaced_getindices.cf.sub0000644000175100017510000000064112332665147032145 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace(array_name, array_name2) { vars: "repo_ids3" slist => { getindices("$(array_name2)") }; } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids3)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/201.cf0000644000175100017510000000142012236160673024766 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 201: getindices() with parameter variable in its argument, from a non-default namespace to the default namespace, but with getindices() inside braces. body common control { inputs => { "../../../default.cf.sub", "201_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace("default:g.array", "b:variables.array2"); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/004_namespaced_getindices.cf.sub0000644000175100017510000000064112332665147032144 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace(array_name, array_name2) { vars: "repo_ids4" slist => getindices("b:variables.array2"); } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids4)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/003.cf0000644000175100017510000000133612236160673024774 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 003: getindices() with parameter variable argument, from non-default namespace to the same namespace body common control { inputs => { "../../../default.cf.sub", "003_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace("default:g.array", "b:variables.array2"); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/001_namespaced_getindices.cf.sub0000644000175100017510000000063312332665147032142 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace(array_name, array_name2) { vars: "repo_ids1" slist => getindices("$(array_name)"); } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids1)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/005.cf0000644000175100017510000000143612332665147025002 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 004: getindices() with constant argument, from non-default namespace to the same namespace. body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "any" usebundle => test_default_namespace("g.array"); } bundle agent test_default_namespace(array_name) { vars: "repo_ids5" slist => getindices("$(array_name)"); } bundle agent check { methods: "check" usebundle => dcs_check_strcmp("$(test_default_namespace.repo_ids5)", "key", "$(this.promise_filename)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/006.cf0000644000175100017510000000140112332665147024773 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 004: getindices() with constant argument, from non-default namespace to the same namespace. body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "any" usebundle => test_default_namespace; } bundle agent test_default_namespace { vars: "repo_ids6" slist => getindices("g.array"); } bundle agent check { methods: "check" usebundle => dcs_check_strcmp("$(test_default_namespace.repo_ids6)", "key", "$(this.promise_filename)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/101_namespaced_getindices.cf.sub0000644000175100017510000000066212332665147032145 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace { vars: "array_name" string => "default:g.array"; "repo_ids1" slist => getindices("$(array_name)"); } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids1)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/002.cf0000644000175100017510000000132512236160673024771 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 002: getindices() with constant argument, from a non-default namespace to default namespace body common control { inputs => { "../../../default.cf.sub", "002_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace("default:g.array", "b:variables.array2"); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/001.cf0000644000175100017510000000135212236160673024770 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 001: getindices() with parameter variable in its argument, from a non-default namespace to the default namespace body common control { inputs => { "../../../default.cf.sub", "001_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace("default:g.array", "b:variables.array2"); } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/201_namespaced_getindices.cf.sub0000644000175100017510000000063712332665147032150 0ustar00a10038a1003800000000000000body file control { namespace => "b"; } bundle common variables { vars: "array2[key]" string => "string2"; } bundle agent test_in_namespace(array_name, array_name2) { vars: "repo_ids1" slist => { getindices("$(array_name)") }; } bundle agent check_in_namespace(test) { methods: "any" usebundle => default:dcs_check_strcmp("$(b:test_in_namespace.repo_ids1)", "key", "$(test)", "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/namespaces/101.cf0000644000175100017510000000136112236160673024771 0ustar00a10038a1003800000000000000# Check that getindices() works correctly within and across namespaces # 101: getindices() with local variable in its argument, from a non-default namespace to the default namespace # same as 001.cf but without using a parameter body common control { inputs => { "../../../default.cf.sub", "101_namespaced_getindices.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "array[key]" string => "string"; } bundle agent init { vars: } bundle agent test { methods: "test_in_namespace" usebundle => b:test_in_namespace; } bundle agent check { methods: "check_in_namespace" usebundle => b:check_in_namespace("$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/063.x.cf0000644000175100017510000000171012243421446023121 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,1000,1000,1000,1000,40001); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/long_string_from_module.cf0000644000175100017510000000650412332665147027275 0ustar00a10038a1003800000000000000####################################################### # # Test that we dont crash when reading in large strings from a module # Redmine:3957 (https://cfengine.com/dev/issues/3957) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).module" create => "true", perms => m("700"), edit_defaults => empty, edit_line => seed_module; } ####################################################### bundle agent test { commands: "$(G.testfile).module" module => "true"; } ####################################################### bundle agent check { classes: "ok" expression => "any", comment => "If we made it to here, we didnt crash"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } bundle edit_line seed_module { insert_lines: "#!/bin/bash"; "echo '@keys= { \"ssh-dss YavBsyK3sHDac4Gj4nDbVH9E7OfRPi16DADNOWGKEjWiBB0cCe0UY6xxEgcYuwOOl8HUGqqzLOByvUbo1hENDQldKFt8N7WIb2E9gXFtGm0Sf0NlYARALj1nhLju9hodpGxkr4vKioW1fZQBmBqsI7Ky8ZhzU5p4CAm4uCbxAZuiIhDTAcxj7RlDy3fe9WBw7v0cSIbu8E3zEbPn0VQjTduLCJtFOb5LvUxpxUsHMhHu0xS8DvXIwf7l83cQ0XZtwyIgbF3ZxjIZaPyYhKZRAV1qCze4BlcOerJeVYOiKjpXJlOoBprxy2SfEYVS4Khun0efkmsmBAfllKUUNCqsK9j6oWo7BvNbXqzkl2ULJd6h0LNy9jW8IXnnrfWknLGa7lksVmL3afSAufDAb7yRESaUP5KmcD3ghP3Nvu7fy9hz7nIAPgj2dQOwnFRbkv9Svoi9YmCtvBWYAcwIUVNJBmwXe5j5xJyt5vOyRSI2ooJ9mk69UOCsIM8PEnEXwtHcsg9fDjfu9ChFY2HWZPWeNXH05SATnSyLgclQsZcazhQXPoxZbcqR80mfuRX9ymEzNwZJ1jJUERnj9PZkSInu6mFVRjTaQjg8yvqMGRxWknP8aURCDh5rr4Na23jULVVI66heWOi7nzLqBg5U8GsbLsocM8zBam8bhXfU0KvpBo5wlUtHnDWHoMlS3ktr25ldrp3zLuywhHe5vGUbg2E0gr4xB3oPAyaDa3MGQiVXPfngu5CJhwIXmeN5JtIBA0S46ihg7lQ6IU8kAaRHwhWh3TokoNFOYE8R5i24gpYNF8dgCRGqSZIT5V7wuR3qG1Wau963ILuX8EFOSu7xDc5qnGTem3FwICTpSdnZNqpzRt4Ipqsn4Pa2tFFpHlzDwKFRPS7r8v4QX7acqdTSCUOuZ68GwDRlvHIz5mHUf1XLY3FH2InuWFsonJAZwmEbX5evWXFgyJHFlplQcGJvyNdL0T6oBmbG3ssSMoRnqnsk8XjGWtUyvYoQmOY8HWlMhf4V3v78C4k4TnCbN4LmnDYaDcnXMejrUMYDk6QwW3fdTF5ZyjJMy4ANu2fJfKysZMc1Cc== root@host1\", \"ssh-dss a58AZSxQlmcq33EBCW1GuhpkYCgUfr7o5A1arQZ2dr8I4kldCF76mpl6o2CFthZs4YUU8LewbIDDPqjhS2WwafTXeMEvPMtmLufk6E5njNy2WQtAnmGc9R21qIteTgikY9ubRCM3hlhzJ1wGSKCsE5oBHDQC0thk1ljJGHzsEl0AuVClkUq3yz4eWAsiRdbD9QY7ddD6zA61aHomuczKU5F0VvyO8gRQmWV7b6lysoUFcMgCPVf3UaDdg7L7vvBVkQN2vGCh9CCJz5OkBShlZVNaAXd5TkKJNmsTuBDscPyxeCBAk8sai69f1NNtTeAyWTtSu1KiqTDvD9aal93MhpZnPdOZzNr7etK4C7HuPD0uFjdvKZy1H55rpwNHnJ4GojqiNG1VvN5bGLa3sSLiKOngtMBCokdtHpZn2eHD7oLUROTIG3ZXqFGGvfKEP5zlpvJz3392n4PDQ7EKuNFPhyNQpVXEIAQEDcmeWMopVTGezLoFJG01hKMPxs5QWF7qetVLi1pCjmlUpqgE8c81WGxvMe7ooMtQbeVNulX3qBC3rZhYKtk0R5AA8JxmxHSLYlLFbtnR1PA97hnRvnvlfk92i7WL1hjJsMl29LOrubi554Dr9N2uVUrCFcPZMK45PY0TiRH82AKFmkM8mbM0rndJxoJobZsqRAGHVIkcS53hxMT69liRxlCyubwcxgDaqmeQnJU2Ug0YyFs1uxt4NT9laJ0CO2IxhkbmGeDGw1FJqKyc8Haov263cFMcB97I3gyNHccsAynQnxpMS1ltTFXalghuochdue4unbq0Ty2PfS4jPMkavBlMYN8UZdnyZHuUhycwBJri1Grv5kf2SP00P6NQhuB8kwjqoTG8ay5fKWvhDrVetd7tPuj4dMouHuDeaLJInc7Cz0S5tQOuMfRhpPqk1E8A0YnuNCyPDNuW75rkXZkxP9cYSVWeDa1wgOyNLZDTzYts82qiu9kxLbZ184jowJ8rru4UB20JRtoehnD2nGU1NfegD1qOBgQHtDuB18xggfvOgvUNXBrQpICSz0JqszpftAgV5TJq1FjOdjUo1kOCFuqqi6C4S0Siho== root@host2\" }'"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readfile.cf0000644000175100017510000000311012316547775024131 0ustar00a10038a1003800000000000000# test readfile() body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "sizes" ilist => { "0", "1", "4094", "4095", "4096", "4097", "99999999" }; "read_$(sizes)" string => readfile("$(this.promise_filename).txt", $(sizes)); "length_$(sizes)" int => string_length("$(read_$(sizes))"); } bundle agent check { vars: "sizes" ilist => { @(test.sizes) }; "expected[0]" int => "4095"; "expected[1]" int => "1"; "expected[4094]" int => "4094"; "expected[4095]" int => "4095"; "expected[4096]" int => "4095"; "expected[4097]" int => "4095"; "expected[99999999]" int => "4095"; classes: "ok_$(sizes)" expression => strcmp("$(test.length_$(sizes))", "$(expected[$(sizes)])"); "ok" and => { "ok_0", "ok_1", "ok_4094", "ok_4095", "ok_4096", "ok_4097", "ok_99999999", }; reports: DEBUG:: "Got expected size for read of $(sizes): $(test.length_$(sizes))" ifvarclass => "ok_$(sizes)"; "Did NOT get expected size for read of $(sizes): $(test.length_$(sizes)) != expected $(expected[$(sizes)])" ifvarclass => "!ok_$(sizes)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/025.cf0000644000175100017510000000266012243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123"; "456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/226.cf0000644000175100017510000000247212332665147022671 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 0, ".*v" matches nothing (anchored regex) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "zero" string => "zero"; "one" string => "one"; files: "$(G.testfile).expected" create => "true"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep(".*v", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/regextract2.cf0000644000175100017510000000217412332665147024611 0ustar00a10038a1003800000000000000####################################################### # # Test regextract # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: parsed:: "part1_as_int" int => "$(part[1])"; "part2_as_int" int => "$(part[2])"; "part1_as_str" string => "$(part[1])"; "part2_as_str" string => "$(part[2])"; classes: "parsed" expression => regextract("^node-(\d+)-0*(\d+)", "node-8-01", "part"); } ####################################################### bundle agent check { classes: "ok1" expression => strcmp("$(test.part1_as_int)", "$(test.part1_as_str)"); "ok2" expression => strcmp("$(test.part2_as_int)", "$(test.part2_as_str)"); "ok" and => { "ok1", "ok2" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readfile.cf.txt0000644000175100017510000002400112316547775024751 0ustar00a10038a10038000000000000001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 cfengine-3.6.2/tests/acceptance/01_vars/02_functions/sublist.cf0000644000175100017510000001170112332665147024040 0ustar00a10038a1003800000000000000####################################################### # # Test sublist() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { "starting list = 1", "starting list = 2", "starting list = 3", "starting list = one", "starting list = two", "starting list = three", "starting list = long string", "head(1) = 1", "head(9999) = 1", "head(9999) = 2", "head(9999) = 3", "head(9999) = long string", "head(9999) = one", "head(9999) = three", "head(9999) = two", "tail(1) = three", "tail(10) = 1", "tail(10) = 2", "tail(10) = 3", "tail(10) = long string", "tail(10) = one", "tail(10) = three", "tail(10) = two", "tail(2) = three", "tail(2) = two", "tail(9999) = 1", "tail(9999) = 2", "tail(9999) = 3", "tail(9999) = long string", "tail(9999) = one", "tail(9999) = three", "tail(9999) = two", 'string version of default:test.test_head0 = { --empty-list-- }', 'string version of default:test.test_head1 = { "1" }', 'string version of default:test.test_head9999 = { "1", "2", "3", "one", "two", "three", "long string", "one", "two", "three" }', 'string version of default:test.test_tail0 = { --empty-list-- }', 'string version of default:test.test_tail1 = { "three" }', 'string version of default:test.test_tail10 = { "1", "2", "3", "one", "two", "three", "long string", "one", "two", "three" }', 'string version of default:test.test_tail2 = { "two", "three" }', 'string version of default:test.test_tail9999 = { "1", "2", "3", "one", "two", "three", "long string", "one", "two", "three" }', }; files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "one", "two", "three", }; "test_head9999" slist => sublist("test", "head", 9999); "test_head1" slist => sublist("test", "head", 1); "test_head0" slist => sublist("test", "head", 0); "test_tail9999" slist => sublist("test", "tail", 9999); "test_tail10" slist => sublist("test", "tail", 10); "test_tail2" slist => sublist("test", "tail", 2); "test_tail1" slist => sublist("test", "tail", 1); "test_tail0" slist => sublist("test", "tail", 0); "strings" slist => variablesmatching("default:test\.test_(head|tail)[0-9]+"); "format[$(strings)]" string => format("%S", $(strings)); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: EXTRA:: "Found strings: $(strings) = $(format[$(strings)])"; } bundle edit_line test_insert { insert_lines: "starting list = $(test.test)"; "This line should not appear: $(test.test_head0)"; "head(1) = $(test.test_head1)"; "head(9999) = $(test.test_head9999)"; "This line should not appear: $(test.test_tail0)"; "tail(1) = $(test.test_tail1)"; "tail(10) = $(test.test_tail10)"; "tail(2) = $(test.test_tail2)"; "tail(9999) = $(test.test_tail9999)"; "string version of $(test.strings) = $(test.format[$(test.strings)])"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/read_long_file.cf0000644000175100017510000000165512316547775025323 0ustar00a10038a1003800000000000000# Test that long file is succesfully read by readstringlist() function body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "value" slist => readstringlist("$(this.promise_filename).txt", "", "\n", 100000, 1000000); } bundle agent check { vars: "length" int => length("test.value"); "last" string => nth("test.value", 599); classes: "ok1" expression => strcmp("$(length)", "600"); "ok2" expression => strcmp("$(last)", "line600"); "ok" and => { "ok1", "ok2" }; reports: DEBUG.ok1:: "passed1"; DEBUG.ok2:: "passed2"; DEBUG.!ok1:: "failed1 $(length) != 600"; DEBUG.!ok2:: "failed2 $(last) != line600"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/440.cf0000644000175100017510000000533612243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarrayidx(), simple # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "this"), strcmp("$(test.ary[1][1])", "is"), strcmp("$(test.ary[1][2])", "a"), strcmp("$(test.ary[1][3])", "test"), strcmp("$(test.ary[2][0])", "1"), strcmp("$(test.ary[2][1])", "2"), strcmp("$(test.ary[2][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][4]"), isvariable("test.ary[2][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = 'this', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = 'is', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = 'a', saw '$(test.ary[1][2])'"; "expected test.ary[1][3] = 'test', saw '$(test.ary[1][3])'"; "expected test.ary[2][0] = '1', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = '2', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = '3', saw '$(test.ary[2][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/ifelse.cf0000644000175100017510000000370512332665147023627 0ustar00a10038a1003800000000000000####################################################### # # Test ifelse() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { 1, "single string parameter", "hardclass OK", "bundle class OK", "5 parameters OK" }; files: "$(G.testfile).expected" create => "true", edit_defaults => empty, edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { classes: "myclass" expression => "any"; "myclass2" expression => "any"; "secondpass" expression => "any"; vars: secondpass:: "vals" slist => { ifelse(1), ifelse("single string parameter"), ifelse("cfengine", "hardclass OK", "hardclass broken"), ifelse("myclass.myclass2", "bundle class OK", "bundle class broken"), ifelse("this is not true", "5 parameters broken", "this is also not true", "5 parameters broken 2", "5 parameters OK"), }; files: "$(G.testfile).actual" create => "true", edit_defaults => empty, edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/205.cf0000644000175100017510000000322412243421446022653 0ustar00a10038a1003800000000000000####################################################### # # getindices should not truncate keys # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "longstring" string => "abcdefghijklmnopqrstuvwxyz1234abcdefghijklmnopqrstuvwxyz1234abcdefghijklmnopqrstuvwxyz1234abcdefghijklmnopqrstuvwxyz1234abcdefghijklmnopqrstuvwxyz1234abcdefghijklmnopqrstuvwxyz1234AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJJJJJJJJJJJJJJJJJJJJJJJKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPQRSTUVWXYZ"; "table[$(longstring)]" string => "0050"; "member" slist => getindices("table"); } ####################################################### bundle agent test { } ####################################################### bundle agent check { classes: "ok" expression => strcmp($(init.member), $(init.longstring)); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/046.cf0000644000175100017510000000301212243421446022651 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456 789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/027.cf0000644000175100017510000000264612243421446022664 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\.",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/parsearray_maxlen.cf0000644000175100017510000000432512316547775026104 0ustar00a10038a1003800000000000000# Test the parse\w+array(idx)? functions honour their maxlen parameter. body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { vars: "float" string => " 1.0 4.0 2.0 1.0 3.0 1e1 # 36 bytes up to 1e1 4.0 2.0 5.0 16.0 6.0 3.0"; "whole" string => " 1 4 2 1 3 10 # 30 bytes up to 10 4 2 5 16 6 3"; "words" string => " one four two one three ten # 37 bytes up to ten four two five sixteen six three"; } bundle agent test { vars: "flen" int => parserealarray("float", "$(init.float)", "\s*#[^\n]*", "\s+", 1000, 36); "ilen" int => parseintarray("whole", "$(init.whole)", "\s*#[^\n]*", "\s+", 1000, 30); "slen" int => parsestringarray("words", "$(init.words)", "\s*#[^\n]*", "\s+", 1000, 37); "tlen" int => parsestringarrayidx("texts", "$(init.words)", "\s*#[^\n]*", "\s+", 1000, 37); } bundle agent check { vars: "arrays" slist => { "float", "whole", "words", "texts" }; "key_$(arrays)" slist => getindices("test.$(arrays)"); "sub_$(key_$(arrays))" slist => getindices("test.$(arrays)[$(key_$(arrays))]"); classes: "okf" expression => strcmp("$(test.flen)", "3"); "oki" expression => strcmp("$(test.ilen)", "3"); "oks" expression => strcmp("$(test.slen)", "3"); "okt" expression => strcmp("$(test.tlen)", "3"); "ok" and => { "okf", "oki", "oks", "okt" }; reports: DEBUG.!okf:: "float: '$(test.flen)'"; "float[$(key_float)][$(sub_$(key_float))] = $(test.float[$(key_float)][$(sub_$(key_float))])"; DEBUG.!oki:: "whole: '$(test.ilen)'"; "whole[$(key_whole)][$(sub_$(key_whole))] = $(test.whole[$(key_whole)][$(sub_$(key_whole))])"; DEBUG.!oks:: "words: '$(test.slen)'"; "words[$(key_words)][$(sub_$(key_words))] = $(test.words[$(key_words)][$(sub_$(key_words))])"; DEBUG.!okt:: "texts: '$(test.tlen)'"; "texts[$(key_texts)][$(sub_$(key_texts))] = $(test.texts[$(key_texts)][$(sub_$(key_texts))])"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/017.cf0000644000175100017510000000301612243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; "789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok789", islessthan("$(test.sum)", "912.457"), isgreaterthan("$(test.sum)", "912.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/045.cf0000644000175100017510000000256012243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","X",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok" and => { "ok_list", "ok123", islessthan("$(test.sum)", "123.457"), isgreaterthan("$(test.sum)", "123.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/getvalues_flattens-list-elements.cf0000644000175100017510000000304612243421446031031 0ustar00a10038a1003800000000000000####################################################### # # Test getvalues(), to be sure that If the array contains list elements on the # right hand side then all of the list elements are flattened into a single list # to make the return value a list. (Bug #1271) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { "one", "two", "red", "blue" }; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "sea[fish]" slist => { "one", "two" }; "sea[shark]" slist => { "red", "blue" }; secondpass:: "vals" slist => getvalues("sea"); classes: "secondpass" expression => "any"; files: secondpass:: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/225.cf0000644000175100017510000000254712332665147022673 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 1, last element # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "Five"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep(".*v.*", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/datastate.cf.sub0000644000175100017510000000054212316547775025126 0ustar00a10038a1003800000000000000body file control { namespace => "visible_namespace"; } bundle common included { classes: "foo" expression => "any"; "bar" expression => "any", scope => "bundle"; vars: "i" int => "1"; "j" string => "two"; "k" slist => { "k2", "everest" }; "l" data => parsejson('[1, "l", "|"]'); # Night of the Bad Font } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/regline.cf0000644000175100017510000000301012316547775024002 0ustar00a10038a1003800000000000000####################################################### # # Test filter() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "results" slist => { "five trailing spaces ", "no trailing spaces", }; files: "$(G.testfile)" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } bundle agent test { classes: "matched1" expression => regline("five trailing spaces ", $(G.testfile)), scope => "namespace"; "matched2" expression => regline("five trailing spaces ", $(G.testfile)), scope => "namespace"; reports: DEBUG.matched1:: "Line matched1 matched"; DEBUG.!matched1:: "Line matched1 did not match"; DEBUG.matched2:: "Line matched2 matched"; DEBUG.!matched2:: "Line matched2 did not match"; } bundle agent check { classes: "ok" expression => "matched1.!matched2"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; }cfengine-3.6.2/tests/acceptance/01_vars/02_functions/maplist.cf0000644000175100017510000000271512236160673024026 0ustar00a10038a1003800000000000000####################################################### # # Test maplist() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "value=zero"; "value=two"; "value=three's"; "value=four-fore:quatre"; "value=last"; } ####################################################### bundle agent test { vars: "testlist" slist => { "zero", "two", "three's", "four-fore:quatre", "last" }; "mapped" slist => maplist("value=$(this)", "testlist"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(mapped)"; } bundle edit_line test_insert { vars: "mapped" slist => { @{test.mapped} }; insert_lines: "$(mapped)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/peers.cf.mustache0000644000175100017510000000003212352022221025252 0ustar00a10038a1003800000000000000{{#peers}}{{.}} {{/peers}}cfengine-3.6.2/tests/acceptance/01_vars/02_functions/224.cf0000644000175100017510000000256712332665147022674 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 2, global array # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "Two"; "Three"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep("T.*","test.array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/026.cf0000644000175100017510000000264712243421446022664 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/313.cf0000644000175100017510000000200412316547775022665 0ustar00a10038a1003800000000000000####################################################### # # Test escape() - strings that end with \, issue 690 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "t1" string => escape("\\"); "e1" string => "\\"; } ####################################################### bundle agent check { classes: "ok" and => { regcmp("$(test.t1)", "$(test.e1)"), }; reports: DEBUG:: "Comparing actual vs. expected:"; "'$(test.t1)' vs. '$(test.e1)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/lsdir.cf0000644000175100017510000000477512316547775023515 0ustar00a10038a1003800000000000000####################################################### # # Test lsdir() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common files { vars: # * in filenames not allowed on win windows:: "names" slist => { "a", "bc", "d/e/f", "g/h/i/j", "klm/nop/qrs" }; !windows:: "names" slist => { "a", "bc", "d/e/f", "g/h/i/j", "klm/nop/qrs", "tu/*" }; } ####################################################### bundle agent init { files: "$(G.testdir)/$(files.names)" create => "true"; reports: DEBUG:: "Created $(G.testdir)/$(files.names)"; } ####################################################### bundle agent test { vars: "patterns[a]" string => "$(G.testdir)"; "patterns[b]" string => "$(G.testdir)/b"; # no such directory "pnames" slist => getindices("patterns"); "found_unsorted[$(pnames)]" slist => lsdir("$(patterns[$(pnames)])", "[^.].*", "true"); "found[$(pnames)]" slist => sort("found_unsorted[$(pnames)]", "lex"); "found_string[$(pnames)]" string => join(",", "found[$(pnames)]"); reports: DEBUG:: "found pattern $(pnames) '$(patterns[$(pnames)])' => '$(found_string[$(pnames)])'"; } ####################################################### bundle agent check { vars: windows:: "expected[a]" string => "$(G.testdir)$(const.dirsep)a,$(G.testdir)$(const.dirsep)bc,$(G.testdir)$(const.dirsep)d,$(G.testdir)$(const.dirsep)g,$(G.testdir)$(const.dirsep)klm"; !windows:: "expected[a]" string => "$(G.testdir)/a,$(G.testdir)/bc,$(G.testdir)/d,$(G.testdir)/g,$(G.testdir)/klm,$(G.testdir)/tu"; any:: "expected[b]" string => ""; "expects" slist => getindices("expected"); "fstring" slist => getindices("test.found_string"); "joint_condition" string => join(".", "expects"); classes: "$(expects)" expression => strcmp("$(test.found_string[$(expects)])", "$(expected[$(expects)])"); "ok" expression => "$(joint_condition)"; reports: DEBUG:: "pattern $(expects) matches as expected: '$(expected[$(expects)])'" ifvarclass => "$(expects)"; "pattern $(expects) does NOT match expected: '$(test.found_string[$(expects)])' != '$(expected[$(expects)])'" ifvarclass => "!$(expects)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/007.cf0000644000175100017510000000552512243421446022661 0ustar00a10038a1003800000000000000####################################################### # # Test canonify() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "in1" string => "hello"; "expect1" string => "hello"; "out1" string => canonify("$(in1)"); "in2" string => "hello there"; "expect2" string => "hello_there"; "out2" string => canonify("$(in2)"); "in3" string => "/etc/passwd"; "expect3" string => "_etc_passwd"; "out3" string => canonify("$(in3)"); "in4" string => "hello@mumble.com"; "expect4" string => "hello_mumble_com"; "out4" string => canonify("$(in4)"); "in5" string => "!@#$%^&*()_-+={}[]\:;<>,?"; "expect5" string => "_________________________"; "out5" string => canonify("$(in5)"); "in6" string => "Eystein Måløy Stenberg"; "expect6" string => "Eystein_M__l__y_Stenberg"; "out6" string => canonify("$(in6)"); "in7" string => "$(in1) $(in1)"; "expect7" string => "$(in1)_$(in1)"; "out7" string => canonify("$(in1) $(in1)"); "in8" string => "'\"hello\"'"; "expect8" string => "__hello__"; "out8" string => canonify("$(in8)"); } ####################################################### bundle agent check { classes: "ok" and => { strcmp("$(test.expect1)", "$(test.out1)"), strcmp("$(test.expect2)", "$(test.out2)"), strcmp("$(test.expect3)", "$(test.out3)"), strcmp("$(test.expect4)", "$(test.out4)"), strcmp("$(test.expect5)", "$(test.out5)"), strcmp("$(test.expect6)", "$(test.out6)"), strcmp("$(test.expect7)", "$(test.out7)"), strcmp("$(test.expect8)", "$(test.out8)"), }; reports: DEBUG:: "Expected canonify('$(test.in1)') => $(test.out1) == $(test.expect1)"; "Expected canonify('$(test.in2)') => $(test.out2) == $(test.expect2)"; "Expected canonify('$(test.in3)') => $(test.out3) == $(test.expect3)"; "Expected canonify('$(test.in4)') => $(test.out4) == $(test.expect4)"; "Expected canonify('$(test.in5)') => $(test.out5) == $(test.expect5)"; "Expected canonify('$(test.in6)') => $(test.out6) == $(test.expect6)"; "Expected canonify('$(test.in7)') => $(test.out7) == $(test.expect7)"; "Expected canonify('$(test.in8)') => $(test.out8) == $(test.expect8)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/015.cf0000644000175100017510000000270212243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok" and => { "ok_list", "ok123", islessthan("$(test.sum)", "123.457"), isgreaterthan("$(test.sum)", "123.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/nth_datacontainer.cf.json0000644000175100017510000000052012316547775027015 0ustar00a10038a1003800000000000000{ "boolean": true, "string": "Figaro. Figaro. Figaro, Figaro, Figaro... Figaro!", "integer": 20130111, "list": [ "chris", "dituri", "was", "here" ], "object": { "a": true, "b": [ 1, 2, 3 ], "c": "cat", "d": 108 }, "integer_2": 987654321, "string_2": "Othello? Where art thou now?", "boolean_2": false, "null": null, } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/011.cf0000644000175100017510000000265512243421446022655 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok" and => { "ok_list", islessthan("$(test.sum)", "123.1"), isgreaterthan("$(test.sum)", "122.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/data_readstringarrayidx.cf0000644000175100017510000000274412316547775027271 0ustar00a10038a1003800000000000000# Redmine#2926: test long lines with readstringarrayidx() body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "params" data => data_readstringarrayidx("$(this.promise_filename).txt", "\s*#[^\n]*", ";", 9999, 99999); "params_str" string => format("%S", params); "pk" slist => getindices(params); reports: DEBUG:: "params: $(params_str)"; } bundle agent check { vars: "dim" int => length("test.params"); "length" int => length("test.pk"); "last" string => nth("test.value", 599); classes: "ok1" expression => strcmp($(dim), "3"); "ok2" expression => strcmp($(dim), $(length)); "ok3" expression => strcmp("$(test.params[2][0])", "not_working_app_config"); "ok" and => { "ok1", "ok2", "ok3" }; reports: DEBUG.ok1:: "passed1"; DEBUG.ok2:: "passed2"; DEBUG.ok3:: "passed3"; DEBUG.!ok1:: "failed1 $(dim) != 3"; DEBUG.!ok2:: "failed2 $(dim) != $(length)"; DEBUG.!ok3:: "failed3 $(test.params[2][0]) != not_working_app_config"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/reverse.cf0000644000175100017510000000223512243421446024021 0ustar00a10038a1003800000000000000####################################################### # # Test reverse() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "a" slist => { "c", "b", "a" }; "b" slist => { }; } ####################################################### bundle agent test { vars: "sa" slist => reverse("init.a"); "sb" slist => reverse("init.b"); } ####################################################### bundle agent check { vars: "ja" string => join(",", "test.sa"); "jb" string => join(",", "test.sb"); "ea" string => "a,b,c"; "eb" string => ""; classes: any:: "ok_a" expression => strcmp($(ea), $(ja)); "ok_b" expression => strcmp($(eb), $(jb)); "ok" and => { "ok_a", "ok_b" }; reports: DEBUG:: "a '$(ja)' <> '$(ea)'"; "b '$(jb)' <> '$(eb)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/sort.cf0000644000175100017510000002175212352022221023327 0ustar00a10038a1003800000000000000####################################################### # # Test sort() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "a" slist => { "b", "c", "a" }; "b" slist => { "100", "9", "10" }; "c" slist => { }; "d" slist => { "", "a", "", "b" }; "e" slist => { "a", "1", "b" }; "f" slist => { "0", "100.0", "0.1", "3.2" }; "g" slist => { "", "-2.1", "0.88", "b", "00.88" }; "ip" slist => { "100.200.100.0", "1.2.3.4", "9.7.5.1", "9", "9.7", "9.7.5", "", "-1", "where are the IP addresses?" }; "ipv6" slist => { "FE80:0000:0000:0000:0202:B3FF:FE1E:8329", "FE80::0202:B3FF:FE1E:8329", "::1", # the following should all be parsed as the same address and sorted together "2001:db8:0:0:1:0:0:1", "2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1", "2001:db8::0:1:0:0:1", "2001:0db8::1:0:0:1", "2001:db8:0:0:1::1", "2001:db8:0000:0:1::1", "2001:DB8:0:0:1::1", # note uppercase IPv6 addresses are invalid # examples from https://www.ripe.net/lir-services/new-lir/ipv6_reference_card.pdf "8000:63bf:3fff:fdd2", "::ffff:192.0.2.47", "fdf8:f53b:82e4::53", "fe80::200:5aee:feaa:20a2", "2001:0000:4136:e378:", "8000:63bf:3fff:fdd2", "2001:0002:6c::430", "2001:10:240:ab::a", "2002:cb0a:3cdd:1::1", "2001:db8:8:4::2", "ff01:0:0:0:0:0:0:2", "-1", "where are the IP addresses?" }; "mac" slist => { "00:14:BF:F7:23:1D", "0:14:BF:F7:23:1D", ":14:BF:F7:23:1D", "00:014:BF:0F7:23:01D", "00:14:BF:F7:23:1D", "0:14:BF:F7:23:1D", ":14:BF:F7:23:1D", "00:014:BF:0F7:23:01D", "01:14:BF:F7:23:1D", "1:14:BF:F7:23:1D", "01:14:BF:F7:23:2D", "1:14:BF:F7:23:2D", "-1", "where are the MAC addresses?" }; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "hpux|sunos_5_9|windows", meta => { "redmine4934", "redmine5107" }; vars: "test" slist => { "a", "b", "c", "d", "e", "f", "g", "ip", "ipv6", "mac" }; "sort" slist => { "lex", "int", "real", "IP", "MAC" }; "$(sort)_sorted_$(test)" slist => sort("init.$(test)", $(sort)); } ####################################################### bundle agent check { vars: "test" slist => { "a", "b", "c", "d", "e", "f", "g", "ip", "ipv6", "mac" }; "sort" slist => { "lex", "int", "real", "IP", "MAC" }; "numerics" slist => { "int", "real" }; "non_numerics" slist => { "lex", "IP", "MAC" }; "$(sort)_joined_$(test)" string => join(",", "test.$(sort)_sorted_$(test)"); "$(sort)_check_a" string => "a,b,c"; "$(numerics)_check_b" string => "9,10,100"; "$(non_numerics)_check_b" string => "10,100,9"; "$(sort)_check_c" string => ""; "$(numerics)_check_d" string => ",,a,b"; "$(non_numerics)_check_d" string => ",,a,b"; "$(numerics)_check_e" string => "a,b,1"; "$(non_numerics)_check_e" string => "1,a,b"; "$(non_numerics)_check_f" string => "0,0.1,100.0,3.2"; "int_check_f" string => "0.1,0,3.2,100.0"; "real_check_f" string => "0,0.1,3.2,100.0"; "$(non_numerics)_check_g" string => ",-2.1,0.88,00.88,b"; "$(numerics)_check_g" string => ",b,-2.1,00.88,0.88"; "lex_check_ip" string => ",-1,1.2.3.4,100.200.100.0,9,9.7,9.7.5,9.7.5.1,where are the IP addresses?"; "int_check_ip" string => ",where are the IP addresses?,-1,1.2.3.4,9.7.5,9.7,9,9.7.5.1,100.200.100.0"; "real_check_ip" string => ",where are the IP addresses?,-1,1.2.3.4,9.7.5,9.7,9,9.7.5.1,100.200.100.0"; "IP_check_ip" string => ",-1,9,9.7,9.7.5,where are the IP addresses?,1.2.3.4,9.7.5.1,100.200.100.0"; "MAC_check_ip" string => $(lex_check_ip); "$(numerics)_check_ipv6" string => "::1,::ffff:192.0.2.47,FE80:0000:0000:0000:0202:B3FF:FE1E:8329,FE80::0202:B3FF:FE1E:8329,fdf8:f53b:82e4::53,fe80::200:5aee:feaa:20a2,ff01:0:0:0:0:0:0:2,where are the IP addresses?,-1,2001:db8:8:4::2,2001:10:240:ab::a,2001:0002:6c::430,2001:0000:4136:e378:,2001:DB8:0:0:1::1,2001:db8:0000:0:1::1,2001:db8:0:0:1::1,2001:0db8::1:0:0:1,2001:db8::0:1:0:0:1,2001:db8::1:0:0:1,2001:0db8:0:0:1:0:0:1,2001:db8:0:0:1:0:0:1,2002:cb0a:3cdd:1::1,8000:63bf:3fff:fdd2,8000:63bf:3fff:fdd2"; "lex_check_ipv6" string => "-1,2001:0000:4136:e378:,2001:0002:6c::430,2001:0db8:0:0:1:0:0:1,2001:0db8::1:0:0:1,2001:10:240:ab::a,2001:DB8:0:0:1::1,2001:db8:0000:0:1::1,2001:db8:0:0:1:0:0:1,2001:db8:0:0:1::1,2001:db8:8:4::2,2001:db8::0:1:0:0:1,2001:db8::1:0:0:1,2002:cb0a:3cdd:1::1,8000:63bf:3fff:fdd2,8000:63bf:3fff:fdd2,::1,::ffff:192.0.2.47,FE80:0000:0000:0000:0202:B3FF:FE1E:8329,FE80::0202:B3FF:FE1E:8329,fdf8:f53b:82e4::53,fe80::200:5aee:feaa:20a2,ff01:0:0:0:0:0:0:2,where are the IP addresses?"; # note uppercase IPv6 addresses are invalid "IP_check_ipv6" string => "-1,2001:0000:4136:e378:,2001:DB8:0:0:1::1,8000:63bf:3fff:fdd2,8000:63bf:3fff:fdd2,::ffff:192.0.2.47,FE80:0000:0000:0000:0202:B3FF:FE1E:8329,FE80::0202:B3FF:FE1E:8329,where are the IP addresses?,::1,2001:0002:6c::430,2001:10:240:ab::a,2001:db8:0000:0:1::1,2001:db8:0:0:1::1,2001:0db8::1:0:0:1,2001:db8::0:1:0:0:1,2001:db8::1:0:0:1,2001:0db8:0:0:1:0:0:1,2001:db8:0:0:1:0:0:1,2001:db8:8:4::2,2002:cb0a:3cdd:1::1,fdf8:f53b:82e4::53,fe80::200:5aee:feaa:20a2,ff01:0:0:0:0:0:0:2"; "MAC_check_ipv6" string => "-1,2001:0000:4136:e378:,2001:0002:6c::430,2001:0db8::1:0:0:1,2001:10:240:ab::a,2001:DB8:0:0:1::1,2001:db8:0000:0:1::1,2001:db8:0:0:1::1,2001:db8:8:4::2,2001:db8::0:1:0:0:1,2001:db8::1:0:0:1,2002:cb0a:3cdd:1::1,8000:63bf:3fff:fdd2,8000:63bf:3fff:fdd2,::1,::ffff:192.0.2.47,FE80::0202:B3FF:FE1E:8329,fdf8:f53b:82e4::53,fe80::200:5aee:feaa:20a2,where are the IP addresses?,ff01:0:0:0:0:0:0:2,2001:0db8:0:0:1:0:0:1,2001:db8:0:0:1:0:0:1,FE80:0000:0000:0000:0202:B3FF:FE1E:8329"; "lex_check_mac" string => "-1,00:014:BF:0F7:23:01D,00:014:BF:0F7:23:01D,00:14:BF:F7:23:1D,00:14:BF:F7:23:1D,01:14:BF:F7:23:1D,01:14:BF:F7:23:2D,0:14:BF:F7:23:1D,0:14:BF:F7:23:1D,1:14:BF:F7:23:1D,1:14:BF:F7:23:2D,:14:BF:F7:23:1D,:14:BF:F7:23:1D,where are the MAC addresses?"; "$(numerics)_check_mac" string => ":14:BF:F7:23:1D,:14:BF:F7:23:1D,where are the MAC addresses?,-1,00:014:BF:0F7:23:01D,0:14:BF:F7:23:1D,00:14:BF:F7:23:1D,00:014:BF:0F7:23:01D,0:14:BF:F7:23:1D,00:14:BF:F7:23:1D,1:14:BF:F7:23:2D,01:14:BF:F7:23:2D,1:14:BF:F7:23:1D,01:14:BF:F7:23:1D"; "IP_check_mac" string => "-1,00:014:BF:0F7:23:01D,00:014:BF:0F7:23:01D,00:14:BF:F7:23:1D,00:14:BF:F7:23:1D,01:14:BF:F7:23:1D,01:14:BF:F7:23:2D,0:14:BF:F7:23:1D,0:14:BF:F7:23:1D,1:14:BF:F7:23:1D,1:14:BF:F7:23:2D,:14:BF:F7:23:1D,:14:BF:F7:23:1D,where are the MAC addresses?"; "MAC_check_mac" string => "-1,:14:BF:F7:23:1D,:14:BF:F7:23:1D,where are the MAC addresses?,00:014:BF:0F7:23:01D,0:14:BF:F7:23:1D,00:14:BF:F7:23:1D,00:014:BF:0F7:23:01D,0:14:BF:F7:23:1D,00:14:BF:F7:23:1D,1:14:BF:F7:23:1D,01:14:BF:F7:23:1D,1:14:BF:F7:23:2D,01:14:BF:F7:23:2D"; classes: any:: "ok_$(sort)_$(test)" expression => strcmp("$($(sort)_check_$(test))", "$($(sort)_joined_$(test))"); "ok" and => { 'ok_lex_a', 'ok_int_a', 'ok_real_a', 'ok_IP_a', 'ok_MAC_a', 'ok_lex_b', 'ok_int_b', 'ok_real_b', 'ok_IP_b', 'ok_MAC_b', 'ok_lex_c', 'ok_int_c', 'ok_real_c', 'ok_IP_c', 'ok_MAC_c', 'ok_lex_d', 'ok_int_d', 'ok_real_d', 'ok_IP_d', 'ok_MAC_d', 'ok_lex_e', 'ok_int_e', 'ok_real_e', 'ok_IP_e', 'ok_MAC_e', 'ok_lex_f', 'ok_int_f', 'ok_real_f', 'ok_IP_f', 'ok_MAC_f', 'ok_lex_g', 'ok_int_g', 'ok_real_g', 'ok_IP_g', 'ok_MAC_g', 'ok_lex_ip', 'ok_IP_ip', 'ok_MAC_ip', # TOFIX: Debian 4 'ok_int_ip', 'ok_real_ip', 'ok_lex_ipv6', 'ok_int_ipv6', 'ok_real_ipv6', 'ok_IP_ipv6', 'ok_MAC_ipv6', 'ok_lex_mac', 'ok_int_mac', 'ok_real_mac', 'ok_IP_mac', 'ok_MAC_mac', }; reports: DEBUG:: "OK $(sort) $(test) class 'ok_$(sort)_$(test)': '$($(sort)_check_$(test))' == '$($(sort)_joined_$(test))'" ifvarclass => "ok_$(sort)_$(test)"; "BAD $(sort) $(test) class 'ok_$(sort)_$(test)': expected '$($(sort)_check_$(test))' <> '$($(sort)_joined_$(test))'" ifvarclass => "!ok_$(sort)_$(test)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_real_comments_noemptyfields2.cf0000644000175100017510000000510112332665147036515 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions####################################################### # # Test parsestringarray(), add some weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","^#.*",":+",10,14); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "bad" or => { isvariable("test.ary[he][1]"), isvariable("test.ary[blank][0]"), }; "ok" and => { "!bad", strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[he][0])", "he"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "saw 'bad'-class things"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[he][0] = 'he', saw '$(test.ary[he][0])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/024.cf0000644000175100017510000000253312243421446022654 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok" and => { "ok_list", islessthan("$(test.sum)", "123.1"), isgreaterthan("$(test.sum)", "122.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/filestat.cf0000644000175100017510000000573212332665147024175 0ustar00a10038a1003800000000000000####################################################### # # Test filestat() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", perms => init_m(600), edit_defaults => init_empty, edit_line => init_fill_in; reports: DEBUG:: "Created $(G.testfile)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } body perms init_m(mode) { mode => "$(mode)"; } bundle edit_line init_fill_in { insert_lines: "012345789"; "112345789"; "212345789"; "312345789"; "4"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "fields" slist => splitstring("size,gid,uid,ino,nlink,ctime,atime,mtime,mode,modeoct,permstr,permoct,type,devno,dev_minor,dev_major,basename,dirname,linktarget,linktarget_shallow", ",", 999); "stat[$(fields)]" string => filestat($(G.testfile), $(fields)); } ####################################################### bundle agent check { vars: "expected[type]" string => "regular file"; "expected[nlink]" string => "1"; "expected[dirname]" string => dirname($(G.testfile)); "expected[basename]" string => lastnode($(G.testfile), escape("$(const.dirsep)")); "expected[linktarget]" string => $(G.testfile); "expected[linktarget_shallow]" string => $(G.testfile); windows:: "expected[size]" string => "47"; "expected[mode]" string => "33206"; # 100666 "expected[permoct]" string => "666"; "expected[modeoct]" string => "100666"; "expected[permstr]" string => "-rw-rw-rw-"; !windows:: "expected[size]" string => "42"; "expected[mode]" string => "33152"; # 100600 "expected[permoct]" string => "600"; "expected[modeoct]" string => "100600"; "expected[permstr]" string => "-rw-------"; any:: "expects" slist => getindices("expected"); "fields" slist => getindices("test.stat"); "joint_condition" string => join(".", "expects"); classes: "$(expects)" expression => strcmp("$(test.stat[$(expects)])", "$(expected[$(expects)])"); "ok" expression => "$(joint_condition)"; reports: DEBUG:: "got $(G.testfile) field $(fields)=$(test.stat[$(fields)])"; "got $(G.testfile) field $(expects)=$(test.stat[$(expects)]) matches expected" ifvarclass => "$(expects)"; "got $(G.testfile) field $(expects)=$(test.stat[$(expects)]) did NOT match expected $(expected[$(expects)])" ifvarclass => "!$(expects)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/060.x.cf0000644000175100017510000000171312243421446023121 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(1001,1000,1000,1000,1000,40000); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/421.cf0000644000175100017510000000502412243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test parsestringarray(), introduce a singleton with no other fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 singleton 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[singleton][0])", "singleton"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[singleton][1]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[singleton][0] = 'singleton', saw '$(test.ary[singleton][0])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/065.cf0000644000175100017510000000166712243421446022670 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => now(); } ####################################################### bundle agent check { vars: "time" int => "1289601605"; # About when this test was created classes: "ok" expression => islessthan("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/053.cf0000644000175100017510000000163112243421446022654 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,0,1,1,2,100); } ####################################################### bundle agent check { vars: "time" int => "90220"; classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/nth.cf0000644000175100017510000000556512243421446023150 0ustar00a10038a1003800000000000000####################################################### # # Test nth() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { "starting list = 1", "starting list = 2", "starting list = 3", "starting list = one", "starting list = two", "starting list = three", "starting list = long string", "starting list = four", "starting list = fix", "starting list = six", "starting list = one", "starting list = two", "starting list = three", "element #0 of the test list: 1", "element #1 of the test list: 2", "element #10 of the test list: one", "element #1000 of the test list: $(test#test[1000])", "element #11 of the test list: two", "element #2 of the test list: 3", "element #6 of the test list: long string", }; files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "nth" slist => { 1, 2, 6, 10, 11, 1000 }; "test[$(nth)]" string => nth("test", $(nth)); "test[0]" string => nth("test", 0); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "starting list = $(test.test)"; "element #$(test.nth) of the test list: $(test.test[$(test.nth)])"; "element #0 of the test list: $(test.test[0])"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/062.x.cf0000644000175100017510000000171012243421446023120 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,1000,1000,1000,1001,40000); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/hash.cf0000644000175100017510000001337712411001073023265 0ustar00a10038a1003800000000000000####################################################### # # Test hash() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "base_null" string => ""; "base_easy" string => "test"; "base_hard" string => 'This is a test of the hash function!";'; "strings" slist => { "null", "easy", "hard" }; "$(strings)" string => "$(base_$(strings)) "; methods: "make $(strings)" usebundle => file_make("$(G.testfile).$(strings).txt", "$(base_$(strings))"); } ####################################################### bundle agent test { meta: "test_skip_needs_work" string => "windows"; vars: "algos" slist => { "md5", "sha1", "sha256", "sha384", "sha512" }; # XXX # What do we do about testing the crypt hash-type? # "null_$(algos)" string => hash("$(init.null)", $(algos)); # Cfengine does not expand most \ characters, so use Perl :-) "easy_$(algos)" string => hash("$(init.easy)", $(algos)); "hard_$(algos)" string => hash("$(init.hard)", $(algos)); } ####################################################### bundle agent check { vars: "null_md5" string => "68b329da9893e34099c7d8ad5cb9c940"; "null_sha1" string => "adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"; "null_sha256" string => "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"; "null_sha384" string => "ec664e889ed6c1b2763cacf7899d95b7f347373eb982e523419feea3aa362d891b3bf025f292267a5854049091789c3e"; "null_sha512" string => "be688838ca8686e5c90689bf2ab585cef1137c999b48c70b92f67a5c34dc15697b5d11c982ed6d71be1e1e7f7b4e0733884aa97c3f7a339a8ed03577cf74be09"; "easy_md5" string => "d8e8fca2dc0f896fd7cb4cb0031ba249"; "easy_sha1" string => "4e1243bd22c66e76c2ba9eddc1f91394e57f9f83"; "easy_sha256" string => "f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2"; "easy_sha384" string => "109bb6b5b6d5547c1ce03c7a8bd7d8f80c1cb0957f50c4f7fda04692079917e4f9cad52b878f3d8234e1a170b154b72d"; "easy_sha512" string => "0e3e75234abc68f4378a86b3f4b32a198ba301845b0cd6e50106e874345700cc6663a86c1ea125dc5e92be17c98f9a0f85ca9d5f595db2012f7cc3571945c123"; "hard_md5" string => "e80a705b338f8bd4e2525a2cec846233"; "hard_sha1" string => "305636f0563c179c71955612bff716648d2aa9bf"; "hard_sha256" string => "fbfa93af3ddc81df9f812a6d2eff1a40d53160692c81f9f8cfffa9b4562a1749"; "hard_sha384" string => "712843c71d5ca0b6a2b663251b8b5d08abe5fb55adc4445e6fdf759e5429a98f2c762a0f82612d4e42c4703474b58eb5"; "hard_sha512" string => "c9d45d2669a941d4e5014ac291fd0cac0c7717604476416cad118898f238a2887057269e70ac5cad972cf5b8cbb0673e985285b0cc69810d4fee507b8b89067c"; "algos" slist => { @(test.algos) }; "strings" slist => { @(init.strings) }; classes: "ok_$(strings)_$(algos)" expression => strcmp("$(test.$(strings)_$(algos))", "$($(strings)_$(algos))"); "not_ok_$(strings)_$(algos)" not => strcmp("$(test.$(strings)_$(algos))", "$($(strings)_$(algos))"); "ok_hmatch_$(strings)_$(algos)" expression => hashmatch("$(G.testfile).$(strings).txt", $(algos), "$($(strings)_$(algos))"); "not_ok_hmatch_$(strings)_$(algos)" not => hashmatch("$(G.testfile).$(strings).txt", $(algos), "$($(strings)_$(algos))"); "ok_null" and => { "ok_null_md5", "ok_null_sha1", "ok_null_sha256", "ok_null_sha384", "ok_null_sha512", }; "ok_easy" and => { "ok_easy_md5", "ok_easy_sha1", "ok_easy_sha256", "ok_easy_sha384", "ok_easy_sha512", }; "ok_hard" and => { "ok_hard_md5", "ok_hard_sha1", "ok_hard_sha256", "ok_hard_sha384", "ok_hard_sha512", }; "ok_hmatch_null" and => { "ok_hmatch_null_md5", "ok_hmatch_null_sha1", "ok_hmatch_null_sha256", "ok_hmatch_null_sha384", "ok_hmatch_null_sha512", }; "ok_hmatch_easy" and => { "ok_hmatch_easy_md5", "ok_hmatch_easy_sha1", "ok_hmatch_easy_sha256", "ok_hmatch_easy_sha384", "ok_hmatch_easy_sha512", }; "ok_hmatch_hard" and => { "ok_hmatch_hard_md5", "ok_hmatch_hard_sha1", "ok_hmatch_hard_sha256", "ok_hmatch_hard_sha384", "ok_hmatch_hard_sha512", }; "ok" and => { "ok_null", "ok_easy", "ok_hard", "ok_hmatch_null", "ok_hmatch_easy", "ok_hmatch_hard" }; reports: DEBUG:: "$(strings) / $(algos) is OK" ifvarclass => "ok_$(strings)_$(algos)"; "$(strings) / $(algos) failed, $(test.$(strings)_$(algos)) != $($(strings)_$(algos)) (original = $(init.$(strings)))" ifvarclass => "not_ok_$(strings)_$(algos)"; "$(strings) / $(algos) hashmatch is OK" ifvarclass => "ok_hmatch_$(strings)_$(algos)"; "$(strings) / $(algos) hashmatch failed $($(strings)_$(algos)) against $(G.testfile).$(strings).txt" ifvarclass => "not_ok_hmatch_$(strings)_$(algos)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/network/0000755000175100017510000000000012400110676023516 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/network/008.cf0000644000175100017510000000274412400110676024346 0ustar00a10038a1003800000000000000####################################################### # # Test host2ip() # ####################################################### body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: # Neither of these are likely to change... "localhost" string => host2ip("localhost"); "a" string => host2ip("a.root-servers.net"); } ####################################################### bundle agent check { vars: "localhost" string => "127.0.0.1"; "localhost_6" string => "::1"; "a" string => "198.41.0.4"; "a_6" string => "2001:503:ba3e::2:30"; classes: "ok_a" or => { strcmp("$(test.a)", "$(a)"), strcmp("$(test.a)", "$(a_6)"), }; "ok_localhost" or => { strcmp("$(test.localhost)", "$(localhost)"), strcmp("$(test.localhost)", "$(localhost_6)"), }; "ok" and => { "ok_a", "ok_localhost", }; reports: DEBUG:: "Expected $(test.localhost) == $(localhost)"; "Expected $(test.a) == ( $(a) or $(a_6) )"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/network/selectservers.cf0000644000175100017510000000302512352022221026713 0ustar00a10038a1003800000000000000# Test that failure to connect to remote host does not result in "Could not # close socket" error messages. body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { # 5 seconds timeout for selectservers for non-connecting host 8.8.8.8 default_timeout => "5"; } bundle agent init { } bundle agent test { vars: # The first two hosts listen to port 80, the third does not listen # to port 80, the fourth does not even resolve "hosts" slist => { "cfengine.com", "ntua.gr", "8.8.8.8", "inexistent-server" }; "retval" int => selectservers("@(hosts)","80","","","100","alive_servers"); } bundle agent check { classes: "up2servers" expression => strcmp("$(test.retval)", "2"); "first_is_ok" expression => isvariable("test.alive_servers[0]"); "second_is_ok" expression => isvariable("test.alive_servers[1]"); "third_is_bad" not => isvariable("test.alive_servers[2]"); "fourth_is_bad" not => isvariable("test.alive_servers[3]"); methods: # All above classes must be set for test to pass "" usebundle => dcs_passif_expected("up2servers,first_is_ok,second_is_ok,third_is_bad,fourth_is_bad", "", $(this.promise_filename)), inherit => "true"; reports: DEBUG:: "retval: $(test.retval)"; "alive_servers: $(test.alive_servers[0]) $(test.alive_servers[1]) $(test.alive_servers[2])"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readstringarrayidx_order.cf0000644000175100017510000000775612400110676027457 0ustar00a10038a1003800000000000000####################################################### # # Acceptance test for RedMine 6466. # # Order and duplication in data should be preserved. # Based on an initial test by Neil Watson. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: # Note: order is deliberately one unlikely to happen # automatically; and there are duplicates. "file" slist => { "1 ;; other field 1", "2 ;; other field 2", "4 ;; other field 4", "8 ;; other field 8", "16 ;; other field 16", "2 ;; other field 2", "3 ;; other field 3", "6 ;; other field 6", "12 ;; other field 12", "9 ;; other field 9", "18 ;; other field 18", "3 ;; other field 3", "5 ;; other field 5", "10 ;; other field 10", "15 ;; other field 15", "5 ;; other field 5", "7 ;; other field 7", "14 ;; other field 14", "7 ;; other field 7", "0 ;; other field 0" }; files: "$(G.testfile).orig.txt" create => 'true', edit_defaults => empty, edit_line => insert_all_lines( "@{file}" ); } ####################################################### # Insert lines, preserving duplicates: bundle edit_line insert_all_lines(lines) { vars: "whole" string => join(" ", "lines"); insert_lines: "$(whole)" insert_type => "preserve_block"; } ####################################################### bundle agent test { vars: "num" int => readstringarrayidx("mylines", "$(G.testfile).orig.txt", "\s*#[^\n]*", "\s*;;\s*", 50, 9999); "file" slist => { "${mylines[0][0]} ;; ${mylines[0][1]}", "${mylines[1][0]} ;; ${mylines[1][1]}", "${mylines[2][0]} ;; ${mylines[2][1]}", "${mylines[3][0]} ;; ${mylines[3][1]}", "${mylines[4][0]} ;; ${mylines[4][1]}", "${mylines[5][0]} ;; ${mylines[5][1]}", "${mylines[6][0]} ;; ${mylines[6][1]}", "${mylines[7][0]} ;; ${mylines[7][1]}", "${mylines[8][0]} ;; ${mylines[8][1]}", "${mylines[9][0]} ;; ${mylines[9][1]}", "${mylines[10][0]} ;; ${mylines[10][1]}", "${mylines[11][0]} ;; ${mylines[11][1]}", "${mylines[12][0]} ;; ${mylines[12][1]}", "${mylines[13][0]} ;; ${mylines[13][1]}", "${mylines[14][0]} ;; ${mylines[14][1]}", "${mylines[15][0]} ;; ${mylines[15][1]}", "${mylines[16][0]} ;; ${mylines[16][1]}", "${mylines[17][0]} ;; ${mylines[17][1]}", "${mylines[18][0]} ;; ${mylines[18][1]}", "${mylines[19][0]} ;; ${mylines[19][1]}" }; files: "$(G.testfile).copy.txt" create => 'true', edit_defaults => empty, edit_line => insert_all_lines( "@{file}" ); } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).copy.txt", "$(G.testfile).orig.txt", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/004.cf0000644000175100017510000000463112243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test sum() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "six" ilist => { "1", "2", "3" }; "sum_six" real => sum("six"); "minus_six" ilist => { "-1", "-2", "-3" }; "sum_minus_six" real => sum("minus_six"); "zero" ilist => { "-1", "-2", "3" }; "sum_zero" real => sum("zero"); "sixpoint" rlist => { "1.", "2", "3e0" }; "sum_sixpoint" real => sum("sixpoint"); "minus_sixpoint" rlist => { "-1.", "-2", "-3e0" }; "sum_minus_sixpoint" real => sum("minus_sixpoint"); "zeropoint" rlist => { "-1.", "-2", "3e0" }; "sum_zeropoint" real => sum("zeropoint"); } ####################################################### bundle agent check { classes: "ok" and => { isgreaterthan("$(test.sum_six)", "5.9999999"), islessthan("$(test.sum_six)", "6.0000001"), islessthan("$(test.sum_minus_six)", "-5.9999999"), isgreaterthan("$(test.sum_minus_six)", "-6.0000001"), isgreaterthan("$(test.sum_zero)", "-.0000001"), islessthan("$(test.sum_zero)", ".0000001"), isgreaterthan("$(test.sum_sixpoint)", "5.9999999"), islessthan("$(test.sum_sixpoint)", "6.0000001"), islessthan("$(test.sum_minus_sixpoint)", "-5.9999999"), isgreaterthan("$(test.sum_minus_sixpoint)", "-6.0000001"), isgreaterthan("$(test.sum_zeropoint)", "-.0000001"), islessthan("$(test.sum_zeropoint)", ".0000001"), }; reports: DEBUG:: "test.sum_six = $(test.sum_six)"; "test.sum_minus_six = $(test.sum_minus_six)"; "test.sum_zero = $(test.sum_zero)"; "test.sum_sixpoint = $(test.sum_sixpoint)"; "test.sum_minus_sixpoint = $(test.sum_minus_sixpoint)"; "test.sum_zeropoint = $(test.sum_zeropoint)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/nth_datacontainer.cf0000644000175100017510000000477412332665147026054 0ustar00a10038a1003800000000000000####################################################### # # Test nth() with data container input # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle common test_common { vars: "data" data => readjson("$(this.promise_filename).json", "100k"); "datastr" string => format("%S", data); "numbers" ilist => { "-100", "-1", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1000 }; "keys" slist => getindices(data); "object_keys" slist => getindices("data[object]"); "list_keys" slist => getindices("data[list]"); "all_keys" slist => { @(object_keys), @(list_keys), "foo", "bar", "", $(numbers), $(keys) }; "primitives[$(keys)]" string => nth(data, $(keys)); "list[$(all_keys)]" string => nth("data[list]", $(all_keys)); "object[$(all_keys)]" string => nth("data[object]", $(all_keys)); classes: "hasprimitive_$(keys)" expression => isvariable("primitives[$(keys)]"); "haslist_$(all_keys)" expression => isvariable("list[$(all_keys)]"); "hasobject_$(all_keys)" expression => isvariable("object[$(all_keys)]"); } bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_insert; "$(G.testfile).expected" copy_from => local_cp("$(this.promise_filename).expected"); } bundle edit_line test_insert { insert_lines: "jsonstring = $(test_common.datastr)"; "keys:json = $(test_common.keys)"; "primitive:json[$(test_common.keys)] = $(test_common.primitives[$(test_common.keys)])" ifvarclass => "hasprimitive_$(test_common.keys)"; "list:json[$(test_common.all_keys)] = $(test_common.list[$(test_common.all_keys)])" ifvarclass => "haslist_$(test_common.all_keys)"; "object:json[$(test_common.all_keys)] = $(test_common.object[$(test_common.all_keys)])" ifvarclass => "hasobject_$(test_common.all_keys)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/064.x.cf0000644000175100017510000000171312243421446023125 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(1001,1000,1000,1000,1000,40000); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/203.cf0000644000175100017510000000254112243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test getindices(), size 2 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "alpha"; "beta"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "two"; "keys" slist => getindices("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(keys)"; } bundle edit_line test_insert { vars: "keys" slist => { @{test.keys} }; insert_lines: "$(keys)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/222.cf0000644000175100017510000000217112243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 0, global array # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep("Z.*", "test.array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/getfields.cf0000644000175100017510000000261412243421446024315 0ustar00a10038a1003800000000000000####################################################### # # Test getfields() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", edit_line => init_fill_in; reports: DEBUG:: "Created $(G.testfile)"; } bundle edit_line init_fill_in { insert_lines: "one:data1"; "two:data2"; "three:data3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "num_matching" int => getfields("t.*", "$(G.testfile)", ":", "fields"); } ####################################################### bundle agent check { classes: any:: "ok" and => { strcmp("$(test.fields[1])", "two"), strcmp("$(test.fields[2])", "data2"), strcmp("$(test.num_matching)", "2") }; reports: DEBUG:: "got field $(test.fields[1])"; "got field $(test.fields[2])"; "num_matching is $(test.num_matching)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/051.cf0000644000175100017510000000162712243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,0,0,0,0,100); } ####################################################### bundle agent check { vars: "time" int => "100"; classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/regarray.cf0000644000175100017510000000166112243421446024164 0ustar00a10038a1003800000000000000####################################################### # # Test regarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "myarray[0]" string => "bla1"; "myarray[1]" string => "bla2"; "myarray[3]" string => "bla"; "myarray" string => "345"; "not" string => "345"; } ####################################################### bundle agent check { classes: "ok" expression => regarray("test.myarray","b.*2"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/601.cf0000644000175100017510000000463212243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test readrealarray(), introduce 777 12345 with no other fields # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 12345 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readrealarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[12345][0])", "12345"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[12345][1]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[12345][0] = '12345', saw '$(test.ary[12345][0])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/canonifyuniquely.cf0000644000175100017510000000643012243421446025751 0ustar00a10038a1003800000000000000####################################################### # # Test canonifyuniquely() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "in1" string => "h?llo"; "expect1" string => "h_llo_ad3f6fcf7063483c9d23b4b83c0b65df72e9f5cc"; "out1" string => canonifyuniquely("$(in1)"); "in2" string => "h/llo"; "expect2" string => "h_llo_5d049ef5eaa0c5b4622eac3eee899132731bc034"; "out2" string => canonifyuniquely("$(in2)"); "in3" string => "/etc/passwd"; "expect3" string => "_etc_passwd_b5cc3f676d00dd320d85ef41a5209fa0a99891ea"; "out3" string => canonifyuniquely("$(in3)"); "in4" string => "hello@mumble.com"; "expect4" string => "hello_mumble_com_5050b0473d3e79adccfb885b8cbe3f44ed706987"; "out4" string => canonifyuniquely("$(in4)"); "in5" string => "!@#$%^&*()_-+={}[]\:;<>,?"; "expect5" string => "__________________________55a3d62a602f37917827cbe044fcbb5da58f8df5"; "out5" string => canonifyuniquely("$(in5)"); "in6" string => "Eystein Måløy Stenberg"; "expect6" string => "Eystein_M__l__y_Stenberg_f1d661c705209075cd873226cb131d2e27374357"; "out6" string => canonifyuniquely("$(in6)"); "in7" string => "$(in1) $(in1)"; "expect7" string => "h_llo_h_llo_53750186dbccd2f8a512345c4a92ccc34d75267d"; "out7" string => canonifyuniquely("$(in1) $(in1)"); "in8" string => "'\"hello\"'"; "expect8" string => "__hello___b2a2a0459a623c8e1cae32e88673ba4067106dc9"; "out8" string => canonifyuniquely("$(in8)"); } ####################################################### bundle agent check { classes: "ok" and => { strcmp("$(test.expect1)", "$(test.out1)"), strcmp("$(test.expect2)", "$(test.out2)"), strcmp("$(test.expect3)", "$(test.out3)"), strcmp("$(test.expect4)", "$(test.out4)"), strcmp("$(test.expect5)", "$(test.out5)"), strcmp("$(test.expect6)", "$(test.out6)"), strcmp("$(test.expect7)", "$(test.out7)"), strcmp("$(test.expect8)", "$(test.out8)"), }; reports: DEBUG:: "Expected canonifyuniquely('$(test.in1)') => $(test.out1) == $(test.expect1)"; "Expected canonifyuniquely('$(test.in2)') => $(test.out2) == $(test.expect2)"; "Expected canonifyuniquely('$(test.in3)') => $(test.out3) == $(test.expect3)"; "Expected canonifyuniquely('$(test.in4)') => $(test.out4) == $(test.expect4)"; "Expected canonifyuniquely('$(test.in5)') => $(test.out5) == $(test.expect5)"; "Expected canonifyuniquely('$(test.in6)') => $(test.out6) == $(test.expect6)"; "Expected canonifyuniquely('$(test.in7)') => $(test.out7) == $(test.expect7)"; "Expected canonifyuniquely('$(test.in8)') => $(test.out8) == $(test.expect8)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/054.cf0000644000175100017510000000166712243421446022666 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,1,0,0,0,100); } ####################################################### bundle agent check { vars: "time" int => "2592100"; # 1 month == 30 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/312.cf0000644000175100017510000000213212243421446022647 0ustar00a10038a1003800000000000000# # Test escape() - issue 689 # body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: "t1" string => escape("1,2"); "e1" string => "1,2"; "t2" string => escape("{1,2}"); "e2" string => "{1,2}"; } bundle agent check { classes: "ok1" expression => regcmp("$(test.t1)", "$(test.e1)"); "ok2" expression => regcmp("$(test.t2)", "$(test.e2)"); "ok" and => { "ok1", "ok2" }; reports: DEBUG:: "Comparing actual vs. expected:"; DEBUG.ok1:: "'$(test.t1)' is the same as '$(test.e1)'"; DEBUG.!ok1:: "'$(test.t1)' is NOT the same as '$(test.e1)'"; DEBUG.ok2:: "'$(test.t2)' is the same as '$(test.e2)'"; DEBUG.!ok2:: "'$(test.t2)' is NOT the same as '$(test.e2)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/400.cf0000644000175100017510000000537712243421446022663 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarray(), simple # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "is"), strcmp("$(test.ary[this][2])", "a"), strcmp("$(test.ary[this][3])", "test"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[this][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/230.cf0000644000175100017510000000324412243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test maparray() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "key=alpha value=zero"; "key=beta value=two"; "key=gamma's value=three's"; "key=delta-delta:delta value=four-fore:quatre"; "key=last value=last"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "two"; "array[gamma's]" string => "three's"; "array[delta-delta:delta]" string => "four-fore:quatre"; "array[last]" string => "last"; "mapped" slist => maparray("key=$(this.k) value=$(this.v)", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(mapped)"; } bundle edit_line test_insert { vars: "mapped" slist => { @{test.mapped} }; insert_lines: "$(mapped)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/eval.cf0000644000175100017510000001114512400110676023270 0ustar00a10038a1003800000000000000####################################################### # # Test eval() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "values[0]" string => "x"; "values[1]" string => "+ 200"; "values[2]" string => "200 + 100"; "values[3]" string => "200 - 100"; "values[4]" string => "- - -"; "values[5]" string => "2 - (3 - 1)"; "values[6]" string => ""; "values[7]" string => "3 / 0"; "values[8]" string => "3^3"; "values[9]" string => "(-1)^2"; "values[10]" string => "sin(20)"; "values[11]" string => "cos(20)"; "values[12]" string => "asin(0.2)"; "values[13]" string => "acos(0.2)"; "values[14]" string => "tan(20)"; "values[15]" string => "atan(0.2)"; "values[16]" string => "log(0.2)"; "values[17]" string => "ln2"; "values[18]" string => "ln10"; "values[19]" string => "20 % 3"; "values[20]" string => "sqrt(0.2)"; "values[21]" string => "ceil(3.5)"; "values[22]" string => "floor(3.4)"; "values[23]" string => "abs(-3.4)"; "values[24]" string => "-3.4 -3.4"; "values[25]" string => "-3.400000 -3.400001"; "values[26]" string => "pi"; "values[27]" string => "e"; "values[28]" string => "10 == 10"; "values[29]" string => "10 == 11"; "values[30]" string => "3**0"; "values[31]" string => "step(10)"; "values[32]" string => "step(-10)"; "values[33]" string => "100k"; "values[34]" string => "(200m - 100k) / (2t + 2t)"; } ####################################################### bundle agent test { vars: "indices" slist => getindices("init.values"); # convert the result to lowercase because some platforms use 'inf' # and others 'Inf' and others... you don't wanna know "eval[$(indices)]" string => string_downcase(eval("$(init.values[$(indices)])", "math", "infix")); } ####################################################### bundle agent check { vars: # note this test will be MUCH more accurate when we have sprintf and rounding "verify[0]" string => ''; "verify[1]" string => ''; "verify[2]" string => '300.000000'; "verify[3]" string => '100.000000'; "verify[4]" string => ''; "verify[5]" string => '0.000000'; "verify[6]" string => '0.000000'; "verify[7]" string => 'inf'; "verify[8]" string => '27.000000'; "verify[9]" string => '1.000000'; "verify[10]" string => '0.912945'; "verify[11]" string => '0.408082'; "verify[12]" string => '0.201358'; "verify[13]" string => '1.369438'; "verify[14]" string => '2.237161'; "verify[15]" string => '0.197396'; "verify[16]" string => '-1.609438'; "verify[17]" string => '0.693147'; "verify[18]" string => '2.302585'; "verify[19]" string => '2.000000'; "verify[20]" string => '0.447214'; "verify[21]" string => '4.000000'; "verify[22]" string => '3.000000'; "verify[23]" string => '3.400000'; "verify[24]" string => '-6.800000'; "verify[25]" string => '-6.800001'; "verify[26]" string => '3.141593'; "verify[27]" string => '2.718282'; "verify[28]" string => '1.000000'; "verify[29]" string => '0.000000'; "verify[30]" string => '1.000000'; "verify[31]" string => '1.000000'; "verify[32]" string => '0.000000'; "verify[33]" string => '100000.000000'; "verify[34]" string => '0.000050'; "indices" slist => getindices("verify"); classes: "ok_$(indices)" expression => strcmp("$(test.eval[$(indices)])", "$(verify[$(indices)])"); "not_ok_$(indices)" not => strcmp("$(test.eval[$(indices)])", "$(verify[$(indices)])"); "ok" and => { ok_0, ok_1, ok_3, ok_4, ok_5, ok_6, ok_7, ok_8, ok_9, ok_10, ok_11, ok_13, ok_14, ok_15, ok_16, ok_17, ok_18, ok_19, ok_20, ok_21, ok_23, ok_24, ok_25, ok_26, ok_27, ok_28, ok_29, ok_30, ok_31, ok_32, ok_33, ok_34 }; reports: DEBUG:: "OK math eval('$(init.values[$(indices)])') = '$(test.eval[$(indices)])'" ifvarclass => "ok_$(indices)"; "FAIL math eval('$(init.values[$(indices)])') = '$(test.eval[$(indices)])' (expected '$(verify[$(indices)])')" ifvarclass => "not_ok_$(indices)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/peers.cf0000644000175100017510000001511412352022221023451 0ustar00a10038a1003800000000000000####################################################### # # Test peers() # Ref:Redmine:4848 (https://cfengine.com/dev/issues/4848) ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { methods: "nohosts" usebundle => file_empty("$(G.testfile).nohosts"); "nopeers" usebundle => file_mustache_jsonstring ( "$(this.promise_filename).mustache", '{ "peers": [ "a", "b", "c" ] }', "$(G.testfile).nopeers" ); "somepeers" usebundle => file_mustache_jsonstring ( "$(this.promise_filename).mustache", '{ "peers": [ "a", "b", "c", "$(sys.fqhost)" ] }', "$(G.testfile).somepeers" ); "allpeers" usebundle => file_mustache_jsonstring ( "$(this.promise_filename).mustache", '{ "peers": [ "$(sys.fqhost)", "$(sys.fqhost)", "$(sys.fqhost)", "$(sys.fqhost)" ] }', "$(G.testfile).allpeers" ); } bundle agent test { vars: "tests" slist => { "nohosts", "nopeers", "somepeers", "allpeers" }; "subtests" ilist => { "0", "1", "2", "3", "4", "5" }; "peers_$(tests)_$(subtests)" slist => peers("$(G.testfile).$(tests)", "#.*", $(subtests)); "peerleaders_$(tests)_$(subtests)" slist => peerleaders("$(G.testfile).$(tests)", "#.*", $(subtests)); "actual_peers_$(tests)_$(subtests)" string => format("%S", "peers_$(tests)_$(subtests)"); "actual_peerleaders_$(tests)_$(subtests)" string => format("%S", "peerleaders_$(tests)_$(subtests)"); "actual_peerleader_$(tests)_$(subtests)" string => peerleader("$(G.testfile).$(tests)", "#.*", $(subtests)); } ####################################################### bundle agent check { vars: "f" slist => { "peers", "peerleader", "peerleaders" }; "tests" slist => { @(test.tests) }; "subtests" ilist => { @(test.subtests) }; "good_cases" slist => { "peers_nohosts_2", "peers_nohosts_3", "peers_nohosts_4", "peers_nohosts_5", "peers_nopeers_2", "peers_nopeers_3", "peers_nopeers_4", "peers_nopeers_5", "peers_somepeers_2", "peers_somepeers_3", "peers_somepeers_4", "peers_somepeers_5", "peers_allpeers_2", "peers_allpeers_3", "peers_allpeers_4", "peers_allpeers_5", "peerleader_somepeers_2", "peerleader_somepeers_3", "peerleader_somepeers_4", "peerleader_somepeers_5", "peerleader_allpeers_2", "peerleader_allpeers_3", "peerleader_allpeers_4", "peerleader_allpeers_5", "peerleaders_nohosts_2", "peerleaders_nohosts_3", "peerleaders_nohosts_4", "peerleaders_nohosts_5", "peerleaders_nopeers_2", "peerleaders_nopeers_3", "peerleaders_nopeers_4", "peerleaders_nopeers_5", "peerleaders_somepeers_2", "peerleaders_somepeers_3", "peerleaders_somepeers_4", "peerleaders_somepeers_5", "peerleaders_allpeers_2", "peerleaders_allpeers_3", "peerleaders_allpeers_4", "peerleaders_allpeers_5", }; "bad_cases" slist => { "peers_nohosts_0", "peers_nohosts_1", "peers_nopeers_0", "peers_nopeers_1", "peers_somepeers_0", "peers_somepeers_1", "peers_allpeers_0", "peers_allpeers_1", "peerleader_nohosts_0", "peerleader_nohosts_1", "peerleader_nohosts_2", "peerleader_nohosts_3", "peerleader_nohosts_4", "peerleader_nohosts_5", "peerleader_nopeers_0", "peerleader_nopeers_1", "peerleader_nopeers_2", "peerleader_nopeers_3", "peerleader_nopeers_4", "peerleader_nopeers_5", "peerleader_somepeers_0", "peerleader_somepeers_1", "peerleader_allpeers_0", "peerleader_allpeers_1", "peerleaders_nohosts_0", "peerleaders_nohosts_1", "peerleaders_nopeers_0", "peerleaders_nopeers_1", "peerleaders_somepeers_0", "peerleaders_somepeers_1", "peerleaders_allpeers_0", "peerleaders_allpeers_1", }; "expected_peers_allpeers_$(subtests)" string => '{ --empty-list-- }'; "expected_peers_nopeers_$(subtests)" string => '{ --empty-list-- }'; "expected_peers_nohosts_$(subtests)" string => '{ --empty-list-- }'; "expected_peers_somepeers_2" string => '{ "c" }'; "expected_peers_somepeers_3" string => '{ --empty-list-- }'; "expected_peers_somepeers_4" string => '{ "a", "b", "c" }'; "expected_peers_somepeers_5" string => '{ "a", "b", "c" }'; "expected_peerleader_allpeers_$(subtests)" string => 'localhost'; "expected_peerleader_somepeers_2" string => 'c'; "expected_peerleader_somepeers_3" string => 'localhost'; "expected_peerleader_somepeers_4" string => 'a'; "expected_peerleader_somepeers_5" string => 'a'; "expected_peerleaders_nohosts_$(subtests)" string => '{ --empty-list-- }'; "expected_peerleaders_nopeers_2" string => '{ "a", "c" }'; "expected_peerleaders_nopeers_3" string => '{ "a" }'; "expected_peerleaders_nopeers_4" string => '{ "a" }'; "expected_peerleaders_nopeers_5" string => '{ "a" }'; "expected_peerleaders_somepeers_2" string => '{ "a", "c" }'; "expected_peerleaders_somepeers_3" string => '{ "a", "localhost" }'; "expected_peerleaders_somepeers_4" string => '{ "a" }'; "expected_peerleaders_somepeers_5" string => '{ "a" }'; "expected_peerleaders_allpeers_2" string => '{ "localhost", "localhost" }'; "expected_peerleaders_allpeers_3" string => '{ "localhost", "localhost" }'; "expected_peerleaders_allpeers_4" string => '{ "localhost" }'; "expected_peerleaders_allpeers_5" string => '{ "localhost" }'; "c[$(f)_$(tests)_$(subtests)]" string => "ok_$(f)_$(tests)_$(subtests)"; "cases" slist => getvalues(c); "cs" string => join(",", cases); classes: "ok_$(bad_cases)" not => isvariable("test.actual_$(bad_cases)"); "ok_$(good_cases)" expression => strcmp("$(expected_$(good_cases))", "$(test.actual_$(good_cases))"); methods: "" usebundle => dcs_passif_expected($(cs), "", $(this.promise_filename)), inherit => "true"; reports: EXTRA:: "$(good_cases): as expected, '$(expected_$(good_cases))'" ifvarclass => "ok_$(good_cases)"; "$(bad_cases): as expected, no variable" ifvarclass => "ok_$(bad_cases)"; DEBUG:: "$(good_cases): NOT as expected, '$(expected_$(good_cases))' != '$(test.actual_$(good_cases))'" ifvarclass => "!ok_$(good_cases)"; "$(bad_cases): NOT as expected, has variable '$(test.actual_$(bad_cases))'" ifvarclass => "!ok_$(bad_cases)"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/016.cf0000644000175100017510000000310712243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456"; "789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/211.cf0000644000175100017510000000234112243421446022647 0ustar00a10038a1003800000000000000####################################################### # # Test getvalues(), size 0 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true"; } ####################################################### bundle agent test { vars: "array" string => "zero"; # Intentionally not an array "vals" slist => getvalues("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/getindices.cf0000644000175100017510000000357112316547775024507 0ustar00a10038a1003800000000000000####################################################### # # Test that getindices on an array variable will resolve to 2 levels # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "user[name]" string => "zamboni"; "user[fullname][first]" string => "Diego"; "user[fullname][last]" string => "Zamboni"; "user[dirs]" slist => { "/home/zamboni", "/tmp/zamboni", "/export/home/zamboni" }; "fields" slist => getindices("user"); "fields_sorted" slist => sort("fields", "lex"); "fields_str" string => join(",", "fields_sorted"); "userfields" slist => getindices("user[fullname]"); "userfields_sorted" slist => sort("userfields", "lex"); "userfields_str" string => join(",", "userfields_sorted"); } ####################################################### bundle agent check { vars: "expected_fields" string => "dirs,fullname,name"; "expected_userfields" string => "first,last"; classes: "ok_fields" expression => strcmp($(expected_fields), $(test.fields_str)); "ok_userfields" expression => strcmp($(expected_userfields), $(test.userfields_str)); "ok" and => { "ok_fields", "ok_userfields" }; reports: DEBUG:: "fields = '$(test.fields_str)', expected = '$(expected_fields)'"; "userfields = '$(test.userfields_str)', expected = '$(expected_userfields)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/shuffle.cf0000644000175100017510000000264712316547775024030 0ustar00a10038a1003800000000000000####################################################### # # Test shuffle() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "a" slist => { "a", "b", "c", "d", "e", "f", "g" }; "b" slist => { }; } ####################################################### bundle agent test { vars: "sa" slist => shuffle("init.a", "skruf"); "sb" slist => shuffle("init.b", "skruf"); } ####################################################### bundle agent check { vars: "asorted" slist => sort("test.sa", "lex"); "jaorig" string => join(",", "init.a"); "jasorted" string => join(",", "asorted"); "ja" string => join(",", "test.sa"); "jb" string => join(",", "test.sb"); classes: "a_not_changed" expression => strcmp($(jaorig), $(ja)); "a_is_permutation" expression => strcmp($(jasorted), $(jaorig)); "ok_a" and => { "!a_not_changed", "a_is_permutation" }; "ok_b" expression => strcmp("", $(jb)); "ok" and => { "ok_a", "ok_b" }; reports: DEBUG:: "a '$(jaorig)' <> sort('$(ja)')"; "b '$(jb)' <> ''"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/702.cf0000644000175100017510000000136312243421446022657 0ustar00a10038a1003800000000000000# Test maplist expansion with ${this} syntax (Mantis #1249) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { vars: "s" slist => { "suffix" }; } bundle agent test { vars: "list1" slist => maplist("prefix${this}", "init.s"); "list2" slist => maplist("prefix$(this)", "init.s"); } bundle agent check { classes: "ok" and => { reglist("@(test.list1)", "prefixsuffix"), reglist("@(test.list2)", "prefixsuffix") }; reports: DEBUG:: "list1 => $(test.list1)"; "list2 => $(test.list2)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readtcp_connection_fail.cf.sub0000644000175100017510000000023212236160673027771 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "tcpread" }; } bundle agent tcpread { vars: 'trace_output' string => readtcp('127.0.0.1', '1', '', 1); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/044.cf0000644000175100017510000000275612243421446022665 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456 789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/nth_datacontainer.cf.expected0000644000175100017510000000162112316547775027650 0ustar00a10038a1003800000000000000jsonstring = {"boolean":true,"string":"Figaro. Figaro. Figaro, Figaro, Figaro... Figaro!","integer":20130111,"list":["chris","dituri","was","here"],"object":{"a":true,"b":[1,2,3],"c":"cat","d":108},"integer_2":987654321,"string_2":"Othello? Where art thou now?","boolean_2":false,"null":null} keys:json = boolean keys:json = string keys:json = integer keys:json = list keys:json = object keys:json = integer_2 keys:json = string_2 keys:json = boolean_2 keys:json = null primitive:json[boolean] = true primitive:json[string] = Figaro. Figaro. Figaro, Figaro, Figaro... Figaro! primitive:json[integer] = 20130111 primitive:json[integer_2] = 987654321 primitive:json[string_2] = Othello? Where art thou now? primitive:json[boolean_2] = false primitive:json[null] = null list:json[0] = chris list:json[1] = dituri list:json[2] = was list:json[3] = here object:json[a] = true object:json[c] = cat object:json[d] = 108 cfengine-3.6.2/tests/acceptance/01_vars/02_functions/format.cf0000644000175100017510000000746312332665147023655 0ustar00a10038a1003800000000000000####################################################### # # Test formatint(), formatreal(), and formatstring() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_defaults => empty, edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "key='c32' value='(unhandled format)'"; "key='c107' value='(unhandled format)'"; "key='int100' value='100'"; "key='string100' value='100'"; "key='int0100' value='0100'"; "key='string0100' value='0100'"; "key='real200' value='200.0'"; "key='string200' value='200.0'"; "key='real0200_00' value='0200.00'"; "key='string0200_00' value='0200.00'"; "key='stringabc' value='abc'"; "key='string6abc' value=' abc'"; "key='string-6abc' value='abc '"; "key='2strings-6abc-6def' value='abc def '"; "key='badend' value='ends badly '"; "key='escape' value='% should be a single percent'"; "key='S_123_list' value='{ \"one\", \"two\", \"\\\"three\\\"\" }'"; "key='S_container_1' value='[null]'"; "key='S_container_2' value='[{\"x\":123},\"yz\"]'"; "key='S_empty_list' value='{ --empty-list-- }'"; } ####################################################### bundle agent test { vars: "array[c32]" string => format("%c", 32); "array[c107]" string => format("%c", 107); "array[int100]" string => format("%d", 100); "array[string100]" string => format("%d", "100"); "array[int0100]" string => format("%04d", 100); "array[string0100]" string => format("%04d", "100"); "array[real200]" string => format("%.1f", 200); "array[string200]" string => format("%.1f", "200.00"); "array[real0200_00]" string => format("%07.2f", 200); "array[string0200_00]" string => format("%07.2f", "200.00"); "array[stringabc]" string => format("%s", "abc"); "array[string6abc]" string => format("%6s", "abc"); "array[string-6abc]" string => format("%-6s", "abc"); "array[2strings-6abc-6def]" string => format("%-6s%-6s", "abc", "def"); "array[badend]" string => format("ends badly %"); "array[escape]" string => format("%% should be a single percent"); # %S specifier "mydata" string => 'simplest data'; "emptylist" slist => {}; "list123" slist => { "one", "two", '"three"'}; "mycontainer1" data => parsejson("[ null ]"); "mycontainer2" data => parsejson('[ { "x": 123 }, "yz" ]'); "array[S_string]" string => format("prefix %S suffix", "simple data"); "array[S_var]" string => format("%S", $(mydata)); "array[S_empty_list]" string => format("%S", emptylist); "array[S_123_list]" string => format("%S", list123); "array[S_container_1]" string => format("%S", mycontainer1); "array[S_container_2]" string => format("%S", mycontainer2); "formatted" slist => maparray("key='$(this.k)' value='$(this.v)'", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(formatted)"; } bundle edit_line test_insert { vars: "formatted" slist => { @{test.formatted} }; insert_lines: "$(formatted)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/gettags.cf0000644000175100017510000000341212316547775024021 0ustar00a10038a1003800000000000000# Test that getvariabletags and getclasstags work correctly body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { classes: "myclass" expression => "any", meta => { "mytag1" }; "myotherclass" expression => "any", meta => { "mytag5", "mytag51" }; "myplainclass" expression => "any"; vars: "tests" slist => { "1", "2", "3", "4", "5" }; "myvar" string => "123", meta => { "mytag3" }; "myothervar" string => "123"; } bundle agent test { vars: "tags1" slist => getclassmetatags("myclass"); "tags2" slist => getclassmetatags("myplainclass"); "tags3" slist => getvariablemetatags("init.myvar"); "tags4" slist => getvariablemetatags("init.myothervar"); "tags5" slist => getclassmetatags("myotherclass"); "actual[$(init.tests)]" string => format('%S', "tags$(init.tests)"); } bundle agent check { vars: "expected[1]" string => '{ "source=promise", "mytag1" }'; "expected[2]" string => '{ "source=promise" }'; "expected[3]" string => '{ "source=promise", "mytag3" }'; "expected[4]" string => '{ "source=promise" }'; "expected[5]" string => '{ "source=promise", "mytag5", "mytag51" }'; classes: "ok_$(init.tests)" expression => strcmp("$(test.actual[$(init.tests)])", "$(expected[$(init.tests)])"); "ok" and => { ok_1, ok_2, ok_3, ok_4, ok_5, }; reports: DEBUG:: "Pass case $(init.tests)" ifvarclass => "ok_$(init.tests)"; "FAIL case $(init.tests): actual '$(test.actual[$(init.tests)])', expected '$(expected[$(init.tests)])'" ifvarclass => "!ok_$(init.tests)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/length.cf0000644000175100017510000000303412316547775023644 0ustar00a10038a1003800000000000000####################################################### # # Test 'length' function # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "normal_list" slist => { "b", "c", "a" }; "empty_list" slist => { }; "normal_object" data => parsejson('{ "a": 1, "b": 2 }'); "empty_object" data => parsejson('{}'); "normal_list_len" int => length(normal_list); "empty_list_len" int => length(empty_list); "normal_object_len" int => length(normal_object); "empty_object_len" int => length(empty_object); } ####################################################### bundle agent check { classes: "ok" and => { strcmp("3", $(test.normal_list_len)), strcmp("0", $(test.empty_list_len)), strcmp("2", $(test.normal_object_len)), strcmp("0", $(test.empty_object_len)) }; reports: DEBUG:: "Normal list len: $(test.normal_list_len)"; "Empty list len: $(test.empty_list_len)"; "Normal object len: $(test.normal_object_len)"; "Empty object len: $(test.empty_object_len)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/447.cf0000644000175100017510000001151212243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test parsestringarray(), weird indices, change comment parsing # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","",":",10,1000); "num" int => "9"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "# A duplicate follows"), strcmp("$(test.ary[6][1])", " this line is not always a comment"), strcmp("$(test.ary[7][0])", "this"), strcmp("$(test.ary[7][1])", "also"), strcmp("$(test.ary[8][0])", "last"), strcmp("$(test.ary[8][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = '# A duplicate follows', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ' this line is not always a comment', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'this', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'also', saw '$(test.ary[7][1])'"; "expected test.ary[8][0] = 'last', saw '$(test.ary[8][0])'"; "expected test.ary[8][1] = 'one', saw '$(test.ary[8][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/501.cf0000644000175100017510000000462712243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test readintarray(), introduce 777 12345 with no other fields # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 12345 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readintarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[12345][0])", "12345"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[12345][1]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[12345][0] = '12345', saw '$(test.ary[12345][0])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/findfiles.cf0000644000175100017510000000656312316547775024340 0ustar00a10038a1003800000000000000####################################################### # # Test findfiles() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common findfiles { vars: # * in filenames not allowed on win windows:: "names" slist => { "a", "bc", "d/e/f", "g/h/i/j", "klm/nop/qrs" }; !windows:: "names" slist => { "a", "bc", "d/e/f", "g/h/i/j", "klm/nop/qrs", "tu/*" }; } ####################################################### bundle agent init { files: "$(G.testdir)/$(findfiles.names)" create => "true"; reports: DEBUG:: "Created $(G.testdir)/$(findfiles.names)"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4730" }; vars: "patterns[a]" string => "$(G.testdir)/?"; "patterns[b]" string => "$(G.testdir)/*"; "patterns[c]" string => "$(G.testdir)/?/*"; "patterns[d]" string => "$(G.testdir)/[ab]*"; "patterns[e]" string => "$(G.testdir)/nosuch/*"; !windows:: "patterns[f]" string => "$(G.testdir)/tu/\\*"; "patterns[g]" string => "$(G.testdir)/**"; "patterns[h]" string => "$(G.testdir)/**/j"; any:: "pnames" slist => getindices("patterns"); "found[$(pnames)]" slist => findfiles("$(patterns[$(pnames)])"); "found_string[$(pnames)]" string => join(",", "found[$(pnames)]"); reports: DEBUG:: "findfiles pattern $(pnames) '$(patterns[$(pnames)])' => '$(found_string[$(pnames)])'"; } ####################################################### bundle agent check { vars: "expected[a]" string => "$(G.testdir)/a,$(G.testdir)/d,$(G.testdir)/g"; windows:: "expected[b]" string => "$(G.testdir)/a,$(G.testdir)/bc,$(G.testdir)/d,$(G.testdir)/g,$(G.testdir)/klm"; !windows:: "expected[b]" string => "$(G.testdir)/a,$(G.testdir)/bc,$(G.testdir)/d,$(G.testdir)/g,$(G.testdir)/klm,$(G.testdir)/tu"; any:: "expected[c]" string => "$(G.testdir)/d/e,$(G.testdir)/g/h"; "expected[d]" string => "$(G.testdir)/a,$(G.testdir)/bc"; "expected[e]" string => ""; !windows:: "expected[f]" string => "$(G.testdir)/tu/*"; "expected[g]" string => "$(G.testdir)/a,$(G.testdir)/bc,$(G.testdir)/d,$(G.testdir)/g,$(G.testdir)/klm,$(G.testdir)/tu,$(G.testdir)/d/e,$(G.testdir)/g/h,$(G.testdir)/klm/nop,$(G.testdir)/tu/*,$(G.testdir)/d/e/f,$(G.testdir)/g/h/i,$(G.testdir)/klm/nop/qrs,$(G.testdir)/g/h/i/j"; "expected[h]" string => "$(G.testdir)/g/h/i/j"; any:: "expects" slist => getindices("expected"); "fstring" slist => getindices("test.found_string"); "joint_condition" string => join(".", "expects"); classes: "$(expects)" expression => strcmp("$(test.found_string[$(expects)])", "$(expected[$(expects)])"); "ok" expression => "$(joint_condition)"; reports: DEBUG:: "pattern $(expects) matches as expected: '$(expected[$(expects)])'" ifvarclass => "$(expects)"; "pattern $(expects) does NOT match expected: '$(test.found_string[$(expects)])' != '$(expected[$(expects)])'" ifvarclass => "!$(expects)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/311.cf0000644000175100017510000000231612316547775022671 0ustar00a10038a1003800000000000000####################################################### # # Test escape() - basic tests inside an slist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "s1" slist => { "bstr", escape("foo"), escape("foo.baz"), escape("foo[baz]"), "estr", }; "t1" string => join(",","s1"); "e1" string => "bstr,foo,foo.baz,foo[baz],estr"; } ####################################################### bundle agent check { classes: "ok" and => { regcmp("$(test.t1)", "$(test.e1)"), }; reports: DEBUG:: "'$(test.t1)' comprises $(s1)"; "Comparing actual vs. expected:"; "'$(test.t1)' vs. '$(test.e1)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/008.cf0000644000175100017510000000547012243421446022661 0ustar00a10038a1003800000000000000# splitstring() body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: # Basic stuff "test1" slist => splitstring("abcXdefXghiXjkl", "X", "100"); "test1_result" string => join(":", "test1"); "test1_expected" string => "abc:def:ghi:jkl"; # Empty last item "test2" slist => splitstring("abcX", "X", "100"); "test2_result" string => join(":", "test2"); "test2_expected" string => "abc:"; # Empty first item "test3" slist => splitstring("Xabc", "X", "100"); "test3_result" string => join(":", "test3"); "test3_expected" string => ":abc"; # Regex "test4" slist => splitstring("abc0123def", "[0-9]", "100"); "test4_result" string => join(":", "test4"); "test4_expected" string => "abc::::def"; # No matches "test5" slist => splitstring("abcYdef", "X", "100"); "test5_result" string => join(":", "test5"); "test5_expected" string => "abcYdef"; # Empty string "test6" slist => splitstring("", "X", "100"); "test6_result" string => join(":", "test6"); "test6_expected" string => "$(const.dollar)(test.test6_result)"; # Limit "test7" slist => splitstring("abcXdefXghiXjklXmno", "X", 3); "test7_result" string => join(":", "test7"); "test7_expected" string => "abc:def:ghi"; } bundle agent check { classes: "ok1" expression => strcmp("$(test.test1_result)", "$(test.test1_expected)"); "ok2" expression => strcmp("$(test.test2_result)", "$(test.test2_expected)"); "ok3" expression => strcmp("$(test.test3_result)", "$(test.test3_expected)"); "ok4" expression => strcmp("$(test.test4_result)", "$(test.test4_expected)"); "ok5" expression => strcmp("$(test.test5_result)", "$(test.test5_expected)"); "ok6" expression => strcmp("$(test.test6_result)", "$(test.test6_expected)"); "ok7" expression => strcmp("$(test.test7_result)", "$(test.test7_expected)"); "ok" and => { "ok1", "ok2", "ok3", "ok4", "ok5", "ok6", "ok7" }; reports: DEBUG.!ok1:: "$(test.test1_result) != $(test.test1_expected)"; DEBUG.!ok2:: "$(test.test2_result) != $(test.test2_expected)"; DEBUG.!ok3:: "$(test.test3_result) != $(test.test3_expected)"; DEBUG.!ok4:: "$(test.test4_result) != $(test.test4_expected)"; DEBUG.!ok5:: "$(test.test5_result) != $(test.test5_expected)"; DEBUG.!ok6:: "$(test.test6_result) != $(test.test6_expected)"; DEBUG.!ok7:: "$(test.test7_result) != $(test.test7_expected)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/strftime.cf0000644000175100017510000000333412332665147024213 0ustar00a10038a1003800000000000000####################################################### # # Test strftime() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: # we don't use locale-sensitive formats! "results" slist => { "1973-03-03 09:46:40", "124 1 18 200000000", $(dow) }; Monday:: "dow" string => "1"; Tuesday:: "dow" string => "2"; Wednesday:: "dow" string => "3"; Thursday:: "dow" string => "4"; Friday:: "dow" string => "5"; Saturday:: "dow" string => "6"; Sunday:: "dow" string => "0"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "vals" slist => { strftime('gmtime', '%F %T', 100000000), strftime('localtime', '%j %w %W %s', 200000000), strftime('localtime', '%w', now()), }; files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } variable_references_from_function_that_never_succeeds.cf0000644000175100017510000000261112316547775035317 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions####################################################### # # Test that FnFailure results in unresolved references # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle common test { classes: "resolved_found" expression => returnszero("$(command) resolved_a557d39e04d666075754b8f78ea17fbc175925d5 2>&1", "useshell"); "unresolved_found" expression => returnszero("$(command) unresolved_76201d0eaac49a884308358aa487147b4db70e8a 2>&1", "useshell"); vars: "command" string => "$(sys.cf_agent) -K -f $(this.promise_filename).sub | $(G.grep) MARKER | $(G.grep)"; } ####################################################### bundle agent check { classes: "ok" and => { "!resolved_found", "unresolved_found" }; reports: DEBUG.!resolved_found:: "Resolved variable not found"; DEBUG.resolved_found:: "Resolved variable found?!?!"; DEBUG.unresolved_found:: "Unresolved variable found"; DEBUG.!unresolved_found:: "Unresolved variable not found?!?!"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/storejson.cf0000644000175100017510000000156612243421446024402 0ustar00a10038a1003800000000000000# Test that the storejson() function will convert a data container back to JSON body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "json" string => '{ "x": [ 1, 2, 3 ] }'; } bundle agent test { vars: "data" data => parsejson($(init.json)); "datas" string => storejson(data); } bundle agent check { classes: "ok" expression => strcmp($(test.datas), $(init.json)); "not_ok" not => strcmp($(test.datas), $(init.json)); reports: DEBUG.ok:: "PASS: converted '$(test.datas)' == expected '$(init.json)'"; DEBUG.not_ok:: "FAIL: converted '$(test.datas)' != expected '$(init.json)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/047.cf0000644000175100017510000000301112243421446022651 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123,,,456,789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/056.x.cf0000644000175100017510000000166512243421446023134 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated("-1",0,0,0,0,100); } ####################################################### bundle agent check { vars: "time" int => "31536100"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "nums: $(time)"; "sum: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/maparray.cf0000644000175100017510000000154412352022221024151 0ustar00a10038a1003800000000000000# maparray() test, https://cfengine.com/dev/issues/5452 body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent test { vars: any:: "bundles[services][afs]" slist => { "afs.cf", "bfs.cf" }; "bundles[services][base]" string => "base.cf"; "actual" slist => maparray("services/$(this.k)/$(this.v)", "bundles[services]"); "actual_sorted" slist => sort(actual, "lex"); "actual_str" string => format('%S', actual_sorted); } bundle agent check { methods: "" usebundle => dcs_check_strcmp($(test.actual_str), '{ "services/afs/afs.cf", "services/afs/bfs.cf", "services/base/base.cf" }', $(this.promise_filename), "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/028.cf0000644000175100017510000000256012243421446022660 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok" and => { "ok_list", "ok123", islessthan("$(test.sum)", "123.457"), isgreaterthan("$(test.sum)", "123.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/fold.cf0000644000175100017510000002252412352022221023262 0ustar00a10038a1003800000000000000####################################################### # # Test folding functions: length(), max(), min(), mean(), range(), and variance() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "a" slist => { "b", "c", "a" }; "b" slist => { "100", "9", "10" }; "c" slist => { }; "d" slist => { "", "a", "", "b" }; "e" slist => { "a", "1", "b" }; "f" rlist => { "100", "200", "300" }; "g" rlist => { "1.11", "-2.22", "-3.33" }; "h" ilist => { "-10", "0", "200" }; "i" data => parsejson('[ 1, 2, 3000 ]'); "j" data => parsejson('[ 1, 2, [ 3, 4, 5 ], null, true, false ]'); "k" data => parsejson('{}'); "l" data => parsejson('{ "a": 100, "b": 200, "c": null}'); "lists" slist => { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l" }; "bad_lists" slist => { "c", "k" }; "good_lists" slist => difference("lists", "bad_lists"); "joined_$(lists)" string => format("%S", $(lists)); "length_$(lists)" int => length($(lists)); "lexmin_$(lists)" string => min($(lists), "lex"); "realmin_$(lists)" string => min($(lists), "real"); "lexmax_$(lists)" string => max($(lists), "lex"); "realmax_$(lists)" string => max($(lists), "real"); "variance_$(lists)" string => format("%.2f", variance($(lists))); "stddev_$(lists)" string => format("%.2f", eval("sqrt($(variance_$(lists)))", "math", "infix")); "mean_$(lists)" string => format("%.2f", mean($(lists))); reports: DEBUG:: "List $(lists): $(joined_$(lists)) had length $(length_$(lists))"; "List $(lists): $(joined_$(lists)) had variance $(variance_$(lists))"; "List $(lists): $(joined_$(lists)) had standard deviation $(stddev_$(lists))"; "List $(lists): $(joined_$(lists)) had mean $(mean_$(lists))"; "List $(lists): $(joined_$(lists)) had lex min $(lexmin_$(lists))"; "List $(lists): $(joined_$(lists)) had lex max $(lexmax_$(lists))"; "List $(lists): $(joined_$(lists)) had real min $(realmin_$(lists))"; "List $(lists): $(joined_$(lists)) had real max $(realmax_$(lists))"; } ####################################################### bundle agent check { vars: "lists" slist => { @(test.lists) }; "good_lists" slist => { @(test.good_lists) }; "methods" slist => { @(test.methods) }; "measurements" slist => { "length", "mean", "variance", "stddev", "lexmin", "lexmax", "realmin", "realmax" }; "expected[a][length]" int => "3"; "expected[b][length]" int => "3"; "expected[c][length]" int => "0"; "expected[d][length]" int => "4"; "expected[e][length]" int => "3"; "expected[f][length]" int => "3"; "expected[g][length]" int => "3"; "expected[h][length]" int => "3"; "expected[i][length]" int => "3"; "expected[j][length]" int => "6"; "expected[k][length]" int => "0"; "expected[l][length]" int => "3"; "expected[a][variance]" string => "0.00"; "expected[b][variance]" string => "2730.33"; "expected[c][variance]" string => "-1"; "expected[d][variance]" string => "0.00"; "expected[e][variance]" string => "0.33"; "expected[f][variance]" string => "10000.00"; "expected[g][variance]" string => "5.34"; "expected[h][variance]" string => "14033.33"; "expected[i][variance]" string => "2997001.00"; "expected[j][variance]" string => "0.92"; "expected[k][variance]" string => "0"; "expected[l][variance]" string => "5000.00"; "expected[a][stddev]" string => "0.00"; "expected[b][stddev]" string => "52.25"; "expected[c][stddev]" string => "-1"; "expected[d][stddev]" string => "0.00"; "expected[e][stddev]" string => "0.57"; "expected[f][stddev]" string => "100.00"; "expected[g][stddev]" string => "2.31"; "expected[h][stddev]" string => "118.46"; "expected[i][stddev]" string => "1731.18"; "expected[j][stddev]" string => "0.96"; "expected[k][stddev]" string => "0"; "expected[l][stddev]" string => "70.71"; "expected[a][mean]" string => "0.00"; "expected[b][mean]" string => "39.67"; "expected[c][mean]" string => "-1"; "expected[d][mean]" string => "0.00"; "expected[e][mean]" string => "0.33"; "expected[f][mean]" string => "200.00"; "expected[g][mean]" string => "-1.48"; "expected[h][mean]" string => "63.33"; "expected[i][mean]" string => "1001.00"; "expected[j][mean]" string => "0.75"; "expected[k][mean]" string => "0"; "expected[l][mean]" string => "150.00"; "expected[a][lexmin]" string => "a"; "expected[b][lexmin]" string => "10"; "expected[c][lexmin]" string => "-1"; "expected[d][lexmin]" string => ""; "expected[e][lexmin]" string => "1"; "expected[f][lexmin]" string => "100"; "expected[g][lexmin]" string => "-2.22"; "expected[h][lexmin]" string => "-10"; "expected[i][lexmin]" string => "1"; "expected[j][lexmin]" string => "1"; "expected[k][lexmin]" string => ""; "expected[l][lexmin]" string => "100"; "expected[a][realmin]" string => "a"; "expected[b][realmin]" string => "9"; "expected[c][realmin]" string => "-1"; "expected[d][realmin]" string => ""; "expected[e][realmin]" string => "a"; "expected[f][realmin]" string => "100"; "expected[g][realmin]" string => "-3.33"; "expected[h][realmin]" string => "-10"; "expected[i][realmin]" string => "1"; "expected[j][realmin]" string => "false"; "expected[k][realmin]" string => ""; "expected[l][realmin]" string => "100"; "expected[a][lexmax]" string => "c"; "expected[b][lexmax]" string => "9"; "expected[c][lexmax]" string => "-1"; "expected[d][lexmax]" string => "b"; "expected[e][lexmax]" string => "b"; "expected[f][lexmax]" string => "300"; "expected[g][lexmax]" string => "1.11"; "expected[h][lexmax]" string => "200"; "expected[i][lexmax]" string => "3000"; "expected[j][lexmax]" string => "true"; "expected[k][lexmax]" string => ""; "expected[l][lexmax]" string => "200"; "expected[a][realmax]" string => "c"; "expected[b][realmax]" string => "100"; "expected[c][realmax]" string => "-1"; "expected[d][realmax]" string => "b"; "expected[e][realmax]" string => "1"; "expected[f][realmax]" string => "300"; "expected[g][realmax]" string => "1.11"; "expected[h][realmax]" string => "200"; "expected[i][realmax]" string => "3000"; "expected[j][realmax]" string => "2"; "expected[k][realmax]" string => ""; "expected[l][realmax]" string => "200"; classes: "ok_$(measurements)_$(lists)" expression => strcmp("$(expected[$(lists)][$(measurements)])", "$(test.$(measurements)_$(lists))"); "no_$(measurements)_$(lists)" not => isvariable("test.$(measurements)_$(lists)"); "ok" and => { "ok_length_a", "ok_length_b", "ok_length_c", "ok_length_d", "ok_length_e", "ok_length_f", "ok_length_g", "ok_length_h", "ok_length_i", "ok_length_j", "ok_length_k", "ok_length_l", "ok_mean_a", "ok_mean_b", "no_mean_c", "ok_mean_d", "ok_mean_e", "ok_mean_f", "ok_mean_g", "ok_mean_h", "ok_mean_i", "ok_mean_j", "no_mean_k", "ok_mean_l", "ok_variance_a", "ok_variance_b", "no_variance_c", "ok_variance_d", "ok_variance_e", "ok_variance_f", "ok_variance_g", "ok_variance_h", "ok_variance_i", "ok_variance_j", "no_variance_k", "ok_variance_l", "ok_stddev_a", "ok_stddev_b", "no_stddev_c", "ok_stddev_d", "ok_stddev_e", "ok_stddev_f", "ok_stddev_g", "ok_stddev_h", "ok_stddev_i", "ok_stddev_j", "no_stddev_k", "ok_stddev_l", "ok_realmax_a", "ok_realmax_b", "no_realmax_c", "ok_realmax_d", "ok_realmax_e", "ok_realmax_f", "ok_realmax_g", "ok_realmax_h", "ok_realmax_i", "ok_realmax_j", "no_realmax_k", "ok_realmax_l", "ok_realmin_a", "ok_realmin_b", "no_realmin_c", "ok_realmin_d", "ok_realmin_e", "ok_realmin_f", "ok_realmin_g", "ok_realmin_h", "ok_realmin_i", "ok_realmin_j", "no_realmin_k", "ok_realmin_l", "ok_lexmax_a", "ok_lexmax_b", "no_lexmax_c", "ok_lexmax_d", "ok_lexmax_e", "ok_lexmax_f", "ok_lexmax_g", "ok_lexmax_h", "ok_lexmax_i", "ok_lexmax_j", "no_lexmax_k", "ok_lexmax_l", "ok_lexmin_a", "ok_lexmin_b", "no_lexmin_c", "ok_lexmin_d", "ok_lexmin_e", "ok_lexmin_f", "ok_lexmin_g", "ok_lexmin_h", "ok_lexmin_i", "ok_lexmin_j", "no_lexmin_k", "ok_lexmin_l", }; reports: DEBUG:: "$(good_lists) $(measurements) check expected '$(expected[$(good_lists)][$(measurements)])' <> actual '$(test.$(measurements)_$(good_lists))'" ifvarclass => "!ok_$(measurements)_$(good_lists)"; "good list $(good_lists) had no $(measurements): '$(test.$(measurements)_$(good_lists))' was not expanded" ifvarclass => "no_$(measurements)_$(good_lists)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/text.txt0000644000175100017510000000001212236160673023554 0ustar00a10038a1003800000000000000Succeeded cfengine-3.6.2/tests/acceptance/01_vars/02_functions/dirname.cf0000644000175100017510000001273312400110676023764 0ustar00a10038a1003800000000000000####################################################### # # Test dirname() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent test { vars: # The tests starting with template will be tested with both types of # directory separators on Windows. "template_input[root]" string => "/"; "template_expected[root]" string => "/"; "template_input[simple]" string => "/foo/bar"; "template_expected[simple]" string => "/foo"; "template_input[slash]" string => "/foo/bar/"; "template_expected[slash]" string => "/foo"; "template_input[sub]" string => "/foo"; "template_expected[sub]" string => "/"; "template_input[subslash]" string => "/foo/"; "template_expected[subslash]" string => "/"; "template_input[dot]" string => "/foo/."; "template_expected[dot]" string => "/foo"; "template_input[dot_subslash]" string => "/foo/./"; "template_expected[dot_subslash]" string => "/foo"; "template_input[multi]" string => "/foo/bar/baz"; "template_expected[multi]" string => "/foo/bar"; "template_input[multislash]" string => "/foo/bar/baz/"; "template_expected[multislash]" string => "/foo/bar"; "template_input[more]" string => "/a/b/c/d/e/f/g/h/i"; "template_expected[more]" string => "/a/b/c/d/e/f/g/h"; "template_input[multislash]" string => "/a///b////c///"; "template_expected[multislash]" string => "/a/b"; # Note: no template, because backslashes will be interpreted as UNC path on Windows. "input[multislash_start]" string => "//a///b////c///"; "expected[multislash_start]" string => "/a/b"; "template_input[rel_one]" string => "foo"; "template_expected[rel_one]" string => "."; "template_input[rel_more]" string => "foo/bar"; "template_expected[rel_more]" string => "foo"; "template_input[rel_one_subslash]" string => "foo/"; "template_expected[rel_one_subslash]" string => "."; "template_input[rel_more_subslash]" string => "foo/bar/"; "template_expected[rel_more_subslash]" string => "foo"; "template_input[rel_dot]" string => "foo/."; "template_expected[rel_dot]" string => "foo"; "template_input[rel_only_dot]" string => "./"; "template_expected[rel_only_dot]" string => "."; "template_input[rel_multislash]" string => "a///b////c///"; "template_expected[rel_multislash]" string => "a/b"; "template_input[noop]" string => ""; "template_expected[noop]" string => ""; "template_keys" slist => getindices("template_input"); windows:: "template_input[full_root]" string => "C:/"; "template_expected[full_root]" string => "C:/"; "template_input[full_root_file]" string => "C:/foo"; "template_expected[full_root_file]" string => "C:/"; "template_input[full_root_file_subslash]" string => "C:/foo/"; "template_expected[full_root_file_subslash]" string => "C:/"; "template_input[full_file]" string => "C:/foo/bar"; "template_expected[full_file]" string => "C:/foo"; "template_input[full_file_subslash]" string => "C:/foo/bar/"; "template_expected[full_file_subslash]" string => "C:/foo"; "template_input[dir]" string => "C:foo"; "template_expected[dir]" string => "C:."; "template_input[two_dirs]" string => "C:foo/bar"; "template_expected[two_dirs]" string => "C:foo"; "template_input[dir_subslash]" string => "C:foo/"; "template_expected[dir_subslash]" string => "C:."; "template_input[two_dirs_subslash]" string => "C:foo/bar/"; "template_expected[two_dirs_subslash]" string => "C:foo"; # UNC paths don't have forward slash equivalents. "input[native_unc_one]" string => "\\\\foo"; "expected[native_unc_one]" string => "\\\\"; "input[native_unc_two]" string => "\\\\foo\\bar"; "expected[native_unc_two]" string => "\\\\foo"; "input[native_unc_three]" string => "\\\\foo\\bar\\charlie\\"; "expected[native_unc_three]" string => "\\\\foo\\bar"; "input[unix_$(template_keys)]" string => "$(template_input[$(template_keys)])"; "input[native_$(template_keys)]" string => translatepath("$(template_input[$(template_keys)])"); "expected[unix_$(template_keys)]" string => "$(template_expected[$(template_keys)])"; "expected[native_$(template_keys)]" string => translatepath("$(template_expected[$(template_keys)])"); !windows:: "input[native_$(template_keys)]" string => "$(template_input[$(template_keys)])"; "expected[native_$(template_keys)]" string => "$(template_expected[$(template_keys)])"; any:: "keys" slist => getindices("input"); "actual[$(keys)]" string => dirname("$(input[$(keys)])"); } ####################################################### bundle agent check { vars: "keys" slist => { @(test.keys) }; classes: "failed_cmp_$(keys)" not => strcmp(dirname("$(test.input[$(keys)])"), "$(test.expected[$(keys)])"); "ok" not => classmatch("failed_cmp_.*"); reports: DEBUG:: "'dirname($(test.input[$(keys)]))' = '$(test.actual[$(keys)])' != '$(test.expected[$(keys)])'" ifvarclass => "failed_cmp_$(keys)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/445.cf0000644000175100017510000001153712243421446022667 0ustar00a10038a1003800000000000000####################################################### # # Test parsestringarray(), weird indices, duplicate and trailing newlines # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one "; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "9"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "# A duplicate follows"), strcmp("$(test.ary[6][1])", " this line is not always a comment"), strcmp("$(test.ary[7][0])", "this"), strcmp("$(test.ary[7][1])", "also"), strcmp("$(test.ary[8][0])", "last"), strcmp("$(test.ary[8][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = '# A duplicate follows', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ' this line is not always a comment', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'this', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'also', saw '$(test.ary[7][1])'"; "expected test.ary[8][0] = 'last', saw '$(test.ary[8][0])'"; "expected test.ary[8][1] = 'one', saw '$(test.ary[8][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/mergedata.cf0000644000175100017510000001063412316547775024320 0ustar00a10038a1003800000000000000####################################################### # # Test mergedata() # This test is unstable until we have canonical JSON output # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "load1" data => parsejson('[ 1, 2, 3]'); "load2" slist => { "element1", "element2", "element3" }; "load3" data => parsejson('{ "x": "y" }'); "load4" slist => { }; "load5[mykey]" slist => { "myvalue" }; "load5[anotherkey]" string => "anothervalue"; "load5[lastkey!]" slist => {}; "X" slist => { "1", "2", "3", "4", "5" }; "Y" slist => { @(X) }; "load_$(X)" data => mergedata("load$(X)"); "load_$(X)_$(Y)" data => mergedata("load$(X)", "load$(Y)"); "bad1" data => mergedata(missingvar); "bad2" data => mergedata(load1, missingvar); "justastring" string => "me"; "bad3" data => mergedata(justastring); "bad4" data => mergedata(load1, justastring); } ####################################################### bundle agent check { vars: "X" slist => { @(test.X) }; "Y" slist => { @(test.X) }; "expected_1" string => '[1,2,3]'; "expected_2" string => '["element1","element2","element3"]'; "expected_3" string => '{"x":"y"}'; "expected_4" string => '[]'; "expected_5" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"]}'; "expected_1_1" string => '[1,2,3,1,2,3]'; "expected_1_2" string => '[1,2,3,"element1","element2","element3"]'; "expected_1_3" string => '{"x":"y","0":1,"1":2,"2":3}'; "expected_1_4" string => '[1,2,3]'; "expected_1_5" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"],"0":1,"1":2,"2":3}'; "expected_2_1" string => '["element1","element2","element3",1,2,3]'; "expected_2_2" string => '["element1","element2","element3","element1","element2","element3"]'; "expected_2_3" string => '{"x":"y","0":"element1","1":"element2","2":"element3"}'; "expected_2_4" string => '["element1","element2","element3"]'; "expected_2_5" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"],"0":"element1","1":"element2","2":"element3"}'; "expected_3_1" string => '{"x":"y","0":1,"1":2,"2":3}'; "expected_3_2" string => '{"x":"y","0":"element1","1":"element2","2":"element3"}'; "expected_3_3" string => '{"x":"y"}'; "expected_3_4" string => '{"x":"y"}'; "expected_3_5" string => '{"x":"y","lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"]}'; "expected_4_1" string => '[1,2,3]'; "expected_4_2" string => '["element1","element2","element3"]'; "expected_4_3" string => '{"x":"y"}'; "expected_4_4" string => '[]'; "expected_4_5" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"]}'; "expected_5_1" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"],"0":1,"1":2,"2":3}'; "expected_5_2" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"],"0":"element1","1":"element2","2":"element3"}'; "expected_5_3" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"],"x":"y"}'; "expected_5_4" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"]}'; "expected_5_5" string => '{"lastkey!":[],"anotherkey":"anothervalue","mykey":["myvalue"]}'; "actual_$(X)_$(Y)" string => format("%S", "test.load_$(X)_$(Y)"); "actual_$(X)" string => format("%S", "test.load_$(X)"); classes: "not_ok_$(X)_$(Y)" not => strcmp("$(actual_$(X)_$(Y))", "$(expected_$(X)_$(Y))"); "not_ok_$(X)" not => strcmp("$(actual_$(X))", "$(expected_$(X))"); "ok" not => classmatch("not_ok_.*"); reports: DEBUG:: "$(X): actual $(actual_$(X)) != $(X) expected $(expected_$(X))" ifvarclass => "not_ok_$(X)"; "$(X)+$(Y): actual $(actual_$(X)_$(Y)) != $(X)+$(Y) expected $(expected_$(X)_$(Y))" ifvarclass => "not_ok_$(X)_$(Y)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/310.cf0000644000175100017510000000317712316547775022676 0ustar00a10038a1003800000000000000####################################################### # # Test escape() - basic tests # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "t1" string => escape("foo"); "e1" string => "foo"; "t2" string => escape("foo.baz"); "e2" string => "foo.baz"; "t3" string => escape("foo[baz]"); "e3" string => "foo[baz]"; "t4" string => escape("(fo?o|baz)+x{3}y*"); "e4" string => "(fo?o|baz)+x{3}y*"; "t5" string => escape("~`!@#%&_=\"';:,/<>"); "e5" string => "~`!@#%&_=\"';:,/<>"; } ####################################################### bundle agent check { classes: "ok" and => { regcmp("$(test.t1)", "$(test.e1)"), regcmp("$(test.t2)", "$(test.e2)"), regcmp("$(test.t3)", "$(test.e3)"), regcmp("$(test.t4)", "$(test.e4)"), regcmp("$(test.t5)", "$(test.e5)"), }; reports: DEBUG:: "Comparing actual vs. expected:"; "'$(test.t1)' vs. '$(test.e1)'"; "'$(test.t2)' vs. '$(test.e2)'"; "'$(test.t3)' vs. '$(test.e3)'"; "'$(test.t4)' vs. '$(test.e4)'"; "'$(test.t5)' vs. '$(test.e5)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/filestat_linktarget.cf0000644000175100017510000000352212316547775026424 0ustar00a10038a1003800000000000000####################################################### # # Test filestat() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { commands: "$(G.ln) -fs $(G.testfile) $(G.testfile)"; reports: DEBUG:: "Created $(G.testfile) linked to itself"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4608" }; vars: "fields" slist => splitstring("linktarget,linktarget_shallow", ",", 999); "stat[$(fields)]" string => filestat($(G.testfile), $(fields)); } ####################################################### bundle agent check { vars: # Note that on W32 the link target is the file itself "expected[linktarget]" string => $(G.testfile); "expected[linktarget_shallow]" string => $(G.testfile); "expects" slist => getindices("expected"); "fields" slist => getindices("test.stat"); "joint_condition" string => join(".", "expects"); classes: "$(expects)" expression => strcmp("$(test.stat[$(expects)])", "$(expected[$(expects)])"); "ok" expression => "$(joint_condition)"; reports: DEBUG:: "got $(G.testfile) field $(fields)=$(test.stat[$(fields)])"; "got $(G.testfile) field $(expects)=$(test.stat[$(expects)]) matches expected" ifvarclass => "$(expects)"; "got $(G.testfile) field $(expects)=$(test.stat[$(expects)]) did NOT match expected $(expected[$(expects)])" ifvarclass => "!$(expects)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/700.cf0000644000175100017510000000145012243421446022652 0ustar00a10038a1003800000000000000# Test that long bundle names are not cut off (Mantis #975) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent long_long_long_long_long_long_long_long_long_name { vars: "foo[ok]" string => "abc"; "bar" slist => getindices("foo"); } bundle agent test { methods: "l" usebundle => "long_long_long_long_long_long_long_long_long_name"; } bundle agent check { vars: "res" string => join("", "long_long_long_long_long_long_long_long_long_name.bar"); classes: "ok" expression => strcmp("${res}", "ok"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/and.cf0000644000175100017510000000166312236160673023120 0ustar00a10038a1003800000000000000####################################################### # # Test and() with ifvarclass in vars # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "foo" expression => "any"; "bar" expression => "any"; "ok" expression => strcmp("$(var)", "whatever"); vars: "var" string => "whatever", ifvarclass => and("foo", "bar"); reports: ok:: "$(this.promise_filename) Pass"; # !ok:: # "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/201.cf0000644000175100017510000000234312243421446022650 0ustar00a10038a1003800000000000000####################################################### # # Test getindices(), size 0 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true"; } ####################################################### bundle agent test { vars: "array" string => "zero"; # Intentionally not an array "keys" slist => getindices("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(keys)"; } bundle edit_line test_insert { vars: "keys" slist => { @{test.keys} }; insert_lines: "$(keys)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/068.cf0000644000175100017510000000276412316547775022711 0ustar00a10038a1003800000000000000####################################################### # # Test getusers() arg0 and arg1 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: # All users except root, bin, and daemon "users" slist => getusers("root,bin,daemon","0,1,2"); files: "$(G.testfile)" delete => init_delete; reports: cfengine_3:: "$(users)" report_to_file => "$(G.testfile)"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: # Try to delete the lines that shouldn't be there anyway "$(G.testfile)" edit_line => test_delete, classes => full_set; } bundle edit_line test_delete { delete_lines: "root"; "daemon"; "bin"; } body classes full_set { promise_kept => { "pass" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { classes: "ok" expression => "pass&!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/050.cf0000644000175100017510000000303012243421446022644 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456.789"; # Is is a real or a set of ints? } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\.",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/040.cf0000644000175100017510000000265012243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\.",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/441.cf0000644000175100017510000000470112243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarrayidx(), introduce a singleton with no other fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 singleton 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "singleton"), strcmp("$(test.ary[2][0])", "1"), strcmp("$(test.ary[2][1])", "2"), strcmp("$(test.ary[2][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][1]"), isvariable("test.ary[2][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = 'singleton', saw '$(test.ary[1][0])'"; "expected test.ary[2][0] = '1', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = '2', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = '3', saw '$(test.ary[2][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/444.cf0000644000175100017510000001153612243421446022665 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarrayidx(), add some weird indices (including a duplicate) # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "9"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "# A duplicate follows"), strcmp("$(test.ary[6][1])", " this line is not always a comment"), strcmp("$(test.ary[7][0])", "this"), strcmp("$(test.ary[7][1])", "also"), strcmp("$(test.ary[8][0])", "last"), strcmp("$(test.ary[8][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = '# A duplicate follows', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ' this line is not always a comment', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'this', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'also', saw '$(test.ary[7][1])'"; "expected test.ary[8][0] = 'last', saw '$(test.ary[8][0])'"; "expected test.ary[8][1] = 'one', saw '$(test.ary[8][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/042.cf0000644000175100017510000000276712243421446022665 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456"; "789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/every_some_none.cf0000644000175100017510000001561512316547775025567 0ustar00a10038a1003800000000000000####################################################### # # Test every(), some(), and none() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { "starting list = 1", "starting list = 2", "starting list = 3", "starting list = one", "starting list = two", "starting list = three", "starting list = long string", "starting list = four", "starting list = fix", "starting list = six", "starting list = one", "starting list = two", "starting list = three", "every() test 1 passed", "every() test 2 passed", "every() test d11 passed", "every() test d12 passed", "every() test d21 passed", "every() test d22 passed", "none() dempty test passed", "none() test 1 passed", "none() test 2 passed", "none() test d11 passed", "none() test d12 passed", "none() test d21 passed", "none() test d22 passed", "some() dempty test passed", "some() test 1 passed", "some() test 2 passed", "some() test d11 passed", "some() test d12 passed", "some() test d21 passed", "some() test d22 passed", "every() dempty test passed", "every() empty test passed", "some() empty test passed", "none() empty test passed", }; files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle common testaide { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "empty" slist => { }; "d1" data => parsejson(' [1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three"]'); "d2" data => parsejson(' { "one": 1, "two": 2, "three": 3, "x": "y", "a": "b", "p": "q" }'); "dempty" data => parsejson('[]'); classes: "every1" expression => every(".*", "test"); "every2" expression => every(".", "test"); "some1" expression => some("long string", "test"); "some2" expression => some("none", "test"); "none1" expression => none("jebadiah", "test"); "none2" expression => none("2", "test"); "every_empty" expression => every(".*", "empty"); "some_empty" expression => some(".*", "empty"); "none_empty" expression => none(".*", "empty"); "everyd11" expression => every(".*", d1); "everyd12" expression => every(".", d1); "somed11" expression => some("long string", d1); "somed12" expression => some("none", d1); "noned11" expression => none("jebadiah", d1); "noned12" expression => none("2", d1); "everyd21" expression => every(".*", d2); "everyd22" expression => every(".", d2); "somed21" expression => some("long string", d2); "somed22" expression => some("none", d2); "noned21" expression => none("jebadiah", d2); "noned22" expression => none("2", d2); "every_dempty" expression => every(".*", dempty); "some_dempty" expression => some(".*", dempty); "none_dempty" expression => none(".*", dempty); } bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "starting list = $(testaide.test)"; every1:: "every() test 1 passed"; !every1:: "every() test 1 failed"; every2:: "every() test 2 failed"; !every2:: "every() test 2 passed"; some1:: "some() test 1 passed"; !some1:: "some() test 1 failed"; some2:: "some() test 2 failed"; !some2:: "some() test 2 passed"; none1:: "none() test 1 passed"; !none1:: "none() test 1 failed"; none2:: "none() test 2 failed"; !none2:: "none() test 2 passed"; !every_empty:: "every() empty test passed"; !some_empty:: "some() empty test passed"; none_empty:: "none() empty test passed"; everyd11:: "every() test d11 passed"; !everyd11:: "every() test d11 failed"; everyd12:: "every() test d12 failed"; !everyd12:: "every() test d12 passed"; somed11:: "some() test d11 passed"; !somed11:: "some() test d11 failed"; somed12:: "some() test d12 failed"; !somed12:: "some() test d12 passed"; noned11:: "none() test d11 passed"; !noned11:: "none() test d11 failed"; noned12:: "none() test d12 failed"; !noned12:: "none() test d12 passed"; everyd21:: "every() test d21 passed"; !everyd21:: "every() test d21 failed"; everyd22:: "every() test d22 passed"; !everyd22:: "every() test d22 failed"; somed21:: "some() test d21 failed"; !somed21:: "some() test d21 passed"; somed22:: "some() test d22 failed"; !somed22:: "some() test d22 passed"; noned21:: "none() test d21 passed"; !noned21:: "none() test d21 failed"; noned22:: "none() test d22 failed"; !noned22:: "none() test d22 passed"; !every_dempty:: "every() dempty test passed"; !some_dempty:: "some() dempty test passed"; none_dempty:: "none() dempty test passed"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/013.cf0000644000175100017510000000277112243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/043.cf0000644000175100017510000000267612243421446022665 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; "789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok789", islessthan("$(test.sum)", "912.457"), isgreaterthan("$(test.sum)", "912.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/038.cf0000644000175100017510000000266212243421446022664 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123"; "456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/strftime_GMT.cf0000644000175100017510000000321512243421446024711 0ustar00a10038a1003800000000000000####################################################### # # Test strftime() against some GMT classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: # These classes don't depend on the locale # we require two digits to filter out GMT_Hr0 through 9 # (note that %k has a leading space, so we can't use it below) "results" slist => classesmatching("^GMT_(Hr|Min|Yr)\d\d+$"); files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "vals" slist => { # note that %k has a leading space, don't use it strftime('gmtime', 'GMT_Hr%H', now()), strftime('gmtime', 'GMT_Min%M', now()), strftime('gmtime', 'GMT_Yr%Y', now()), }; files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(test.vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/014.cf0000644000175100017510000000277012243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\.",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/212.cf0000644000175100017510000000245312243421446022654 0ustar00a10038a1003800000000000000####################################################### # # Test getvalues(), size 1 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "zero"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "vals" slist => getvalues("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } readstringarray_dontread_comment_duplicatekey_lastline.cf0000644000175100017510000001104012332665147035531 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions####################################################### # # Test readstringarray(), don't read comment, duplicate key or last line # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",6,1000); "num" int => "6"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "is"), strcmp("$(test.ary[this][2])", "a"), strcmp("$(test.ary[this][3])", "test"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/003.cf0000644000175100017510000000273712316547775022676 0ustar00a10038a1003800000000000000####################################################### # # Test countlinesmatching() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "zero_regex" string => "impossible line"; "one_regex" string => "root:.*"; "positive_regex" string => ".*:\d+:.*"; "zero" int => countlinesmatching("$(zero_regex)", "$(G.etc_passwd)"); "one" int => countlinesmatching("$(one_regex)", "$(G.etc_passwd)"); "positive" int => countlinesmatching("$(positive_regex)", "$(G.etc_passwd)"); } ####################################################### bundle agent check { classes: "ok" and => { strcmp("$(test.zero)", "0"), strcmp("$(test.one)", "1"), isgreaterthan("$(test.positive)", "1"), }; reports: DEBUG:: "Expected 0 matches to '$(test.zero_regex)', found $(test.zero)"; "Expected 1 matches to '$(test.one_regex)', found $(test.one)"; "Expected >1 matches to '$(test.positive_regex)', found $(test.positive)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/mergedata_with_list_iteration.cf0000644000175100017510000000362612316547775030467 0ustar00a10038a1003800000000000000####################################################### # # Test that mergedata works with list iteration # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { test_1, test_2, default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test_1 { vars: "hosts" meta => { "hosts" }, data => parsejson('{"10.100.250.11": [ "slot2" ], "10.100.250.10": [ "slot1" ], "111": 222 }'); } bundle agent test_2 { vars: "hosts" meta => { "hosts" }, data => parsejson('{"10.100.250.11": [ "cflin111" ], "10.100.250.10": [ "cflin110" ]}'); } # this bundle is not in the bundlesequence but will be evaluated bundle agent test_3 { vars: "hosts" meta => { "hosts" }, data => parsejson('{"10.100.250.12": [ "cflin111" ], "10.100.250.13": [ "cflin110" ]}'); } bundle common test { vars: "variables" slist => variablesmatching(".*", "hosts"); "sorted_vars" slist => sort("variables", "lex"); "merged" data => parsejson('{}'), policy => "free"; "merged" data => mergedata(merged, $(sorted_vars)), policy => "free"; "result" string => format("%S", "merged"), policy => "free"; } ####################################################### bundle agent check { vars: "expected" string => '{"111":222,"10.100.250.11":["cflin111"],"10.100.250.10":["cflin110"],"10.100.250.12":["cflin111"],"10.100.250.13":["cflin110"]}'; classes: "ok" expression => strcmp($(test.result), $(check.expected)); reports: DEBUG.inform_mode:: "Expected: '$(check.expected)'"; "Result: '$(test.result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/300.cf0000644000175100017510000000151712243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test multiline regcmp # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "haystack" string => "foo bar"; "needle" string => ".*"; } ####################################################### bundle agent check { classes: "ok" and => { regcmp("$(test.needle)", "$(test.haystack)") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/227.cf0000644000175100017510000000246312332665147022672 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 0, empty pattern should match nothing # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "zero" string => "zero"; "one" string => "one"; files: "$(G.testfile).expected" create => "true"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep("", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/071.cf0000644000175100017510000000317112316547775022674 0ustar00a10038a1003800000000000000####################################################### # # Test filesize(), simple # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "known_val" int => filesize("$(G.testfile)"); "known_zero" int => filesize("$(G.etc_null)"); "unknown" int => filesize("/There/Is/nosuch/Name/as-this"); } ####################################################### bundle agent check { vars: windows:: "testfilesize" int => "30"; !windows:: "testfilesize" int => "27"; classes: "var" expression => isvariable("test.unknown"); "ok" and => { "!var", strcmp("$(test.known_val)", "$(testfilesize)"), strcmp("$(test.known_zero)", "0"), }; reports: DEBUG:: "expected filesize($(G.testfile)) to be XXX, saw $(test.known_val)"; "expected filesize($(G.etc_null)) to be 0, saw $(test.known_zero)"; "expected filesize('UnknownFile') to be undefined, saw $(test.unknown)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/600.cf0000644000175100017510000000537012243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test readrealarray(), simple # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999.9:888:777:666.6 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readrealarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999.9][0])", "999.9"), strcmp("$(test.ary[999.9][1])", "888"), strcmp("$(test.ary[999.9][2])", "777"), strcmp("$(test.ary[999.9][3])", "666.6"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999.9][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999.9][0] = '999.9', saw '$(test.ary[999.9][0])'"; "expected test.ary[999.9][1] = '888', saw '$(test.ary[999.9][1])'"; "expected test.ary[999.9][2] = '777', saw '$(test.ary[999.9][2])'"; "expected test.ary[999.9][3] = '666.6', saw '$(test.ary[999.9][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/055.cf0000644000175100017510000000167012243421446022661 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(1,0,0,0,0,100); } ####################################################### bundle agent check { vars: "time" int => "31536100"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/missing_functions.cf.sub0000644000175100017510000000112312316547775026711 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3907: supposedly missing functions (in this case, a classes body with parameters) aren't # ############################################################################## body common control { bundlesequence => {"example"}; } bundle agent example { vars: "testme" string => "me?!?!?!", classes => 9fdee2550bec1030e22addb0dc9d7218b9174c70("1"); } body classes 9fdee2550bec1030e22addb0dc9d7218b9174c70(x) { promise_repaired => { "9fdee2550bec1030e22addb0dc9d7218b9174c70" }; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/missing_functions.cf0000644000175100017510000000212112316547775026120 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3907: supposedly missing functions (in this case, a classes body with parameters) aren't # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -KI -f $(this.promise_filename).sub | $(G.grep) 'FnCall'", "useshell"); } bundle agent check { # If the output contains the FnCall warning about 9fdee2550bec1030e22addb0dc9d7218b9174c70, we fail classes: "ok" not => regcmp(".*9fdee2550bec1030e22addb0dc9d7218b9174c70.*", "$(test.subout)"); reports: DEBUG:: "agent output: $(test.subout)"; ok:: "The FnCall bogus warning didn't happen"; !ok:: "The FnCall bogus warning happened"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/033.cf0000644000175100017510000000301012243421446022643 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456 789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/031.cf0000644000175100017510000000275412243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456 789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/difference_intersection.cf0000644000175100017510000001250412332665147027235 0ustar00a10038a1003800000000000000####################################################### # # Test difference() and intersection() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "a" slist => { "x", "y", "z" }; "b" slist => { "100", "9", "10" }; "c" slist => { }; "d" slist => { "" }; "e" slist => { "x" }; } ####################################################### bundle agent test { vars: "list1" slist => { "a", "b", "c", "d", "e" }; "list2" slist => { "a", "b", "c", "d", "e" }; "unique_$(list1)" slist => unique("init.$(list1)"); "difference_$(list1)_$(list2)" slist => difference("init.$(list1)", "init.$(list2)"); "intersection_$(list1)_$(list2)" slist => intersection("init.$(list1)", "init.$(list2)"); } ####################################################### bundle agent check { vars: "call" slist => { "difference", "intersection" }; "list1" slist => { "a", "b", "c", "d", "e" }; "list2" slist => { "a", "b", "c", "d", "e" }; "or_joined_list_names" string => join("|", "list1"); "check_$(call)_$(list1)_$(list2)" string => join(",", "test.$(call)_$(list1)_$(list2)"); "joined_$(list1)" string => join(",", "test.unique_$(list1)"); # the difference of any list with itself is empty "verify_difference_$(list1)_$(list1)" string => ""; # the intersection of any list with itself is the list "verify_intersection_$(list1)_$(list1)" string => "$(joined_$(list1))"; # the difference and intersection of the empty list with any list is itself "verify_$(call)_c_$(list1)" string => ""; # the difference and intersection of list d with any list is empty "verify_$(call)_d_$(list1)" string => ""; # the intersection of any list with the empty list is empty "verify_intersection_$(list1)_c" string => ""; # the difference of any list with the empty list is the list "verify_difference_$(list1)_c" string => "$(joined_$(list1))"; "verify_intersection_b_a" string => ""; "verify_difference_b_a" string => "$(joined_b)"; "verify_intersection_a_b" string => ""; "verify_difference_a_b" string => "$(joined_a)"; "verify_intersection_e_a" string => "x"; "verify_difference_e_a" string => ""; "verify_intersection_e_b" string => ""; "verify_difference_e_b" string => "x"; "verify_intersection_e_d" string => ""; "verify_difference_e_d" string => "$(joined_e)"; "verify_intersection_a_d" string => ""; "verify_difference_a_d" string => "$(joined_a)"; "verify_intersection_a_e" string => "x"; "verify_difference_a_e" string => "y,z"; "verify_intersection_b_d" string => ""; "verify_difference_b_d" string => "$(joined_b)"; "verify_intersection_b_e" string => ""; "verify_difference_b_e" string => "$(joined_b)"; classes: "ok_$(call)_$(list1)_$(list2)" expression => strcmp("$(check_$(call)_$(list1)_$(list2))", "$(verify_$(call)_$(list1)_$(list2))"); "ok" and => { ok_difference_a_a, ok_difference_a_b, ok_difference_a_c, ok_difference_a_d, ok_difference_a_e, ok_difference_b_a, ok_difference_b_b, ok_difference_b_c, ok_difference_b_d, ok_difference_b_e, ok_difference_c_a, ok_difference_c_b, ok_difference_c_c, ok_difference_c_d, ok_difference_c_e, ok_difference_d_a, ok_difference_d_b, ok_difference_d_c, ok_difference_d_d, ok_difference_d_e, ok_difference_e_a, ok_difference_e_b, ok_difference_e_c, ok_difference_e_d, ok_difference_e_e, ok_intersection_a_a, ok_intersection_a_b, ok_intersection_a_c, ok_intersection_a_d, ok_intersection_a_e, ok_intersection_b_a, ok_intersection_b_b, ok_intersection_b_c, ok_intersection_b_d, ok_intersection_b_e, ok_intersection_c_a, ok_intersection_c_b, ok_intersection_c_c, ok_intersection_c_d, ok_intersection_c_e, ok_intersection_d_a, ok_intersection_d_b, ok_intersection_d_c, ok_intersection_d_d, ok_intersection_d_e, ok_intersection_e_a, ok_intersection_e_b, ok_intersection_e_c, ok_intersection_e_d, ok_intersection_e_e }; reports: DEBUG:: "OK: ok_$(call)_$(list1)_$(list2) '$(check_$(call)_$(list1)_$(list2))' == '$(verify_$(call)_$(list1)_$(list2))'" ifvarclass => "ok_$(call)_$(list1)_$(list2)"; "FAIL: ok_$(call)_$(list1)_$(list2) '$(check_$(call)_$(list1)_$(list2))' <> '$(verify_$(call)_$(list1)_$(list2))'" ifvarclass => "!ok_$(call)_$(list1)_$(list2)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/030.cf0000644000175100017510000000267412243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; "789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok789", islessthan("$(test.sum)", "912.457"), isgreaterthan("$(test.sum)", "912.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/execresult_multiples.cf.sub0000644000175100017510000000073012316547775027434 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #2981: execresult and returnszero should not be run so much # ############################################################################## body common control { bundlesequence => {"example"}; } bundle agent example { classes: "y" expression => returnszero("/bin/echo CLASSONCE", "noshell"); vars: "x" string => execresult("/bin/echo RETONCE", "noshell"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/052.cf0000644000175100017510000000162712243421446022660 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,0,0,0,2,100); } ####################################################### bundle agent check { vars: "time" int => "220"; classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/521.cf0000644000175100017510000000472012243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test parseintarray(), introduce 777 12345 with no other fields # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 12345 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parseintarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[12345][0])", "12345"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[12345][1]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[12345][0] = '12345', saw '$(test.ary[12345][0])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/005.cf0000644000175100017510000000504512243421446022654 0ustar00a10038a1003800000000000000####################################################### # # Test product() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "six" ilist => { "1", "2", "3" }; "product_six" real => product("six"); "minus_six" ilist => { "-1", "-2", "-3" }; "product_minus_six" real => product("minus_six"); "zero" ilist => { "-1", "0", "3" }; "product_zero" real => product("zero"); "sixpoint" rlist => { "1.", "2", "3" }; "product_sixpoint" real => product("sixpoint"); "minus_sixpoint" rlist => { "-1.", "-2", "-3" }; "product_minus_sixpoint" real => product("minus_sixpoint"); "zeropoint" rlist => { "-1.", "0", "3" }; "product_zeropoint" real => product("zeropoint"); } ####################################################### bundle agent check { classes: "ok" and => { isgreaterthan("$(test.product_six)", "5.9999999"), islessthan("$(test.product_six)", "6.0000001"), islessthan("$(test.product_minus_six)", "-5.9999999"), isgreaterthan("$(test.product_minus_six)", "-6.0000001"), isgreaterthan("$(test.product_zero)", "-.0000001"), islessthan("$(test.product_zero)", ".0000001"), isgreaterthan("$(test.product_sixpoint)", "5.9999999"), islessthan("$(test.product_sixpoint)", "6.0000001"), islessthan("$(test.product_minus_sixpoint)", "-5.9999999"), isgreaterthan("$(test.product_minus_sixpoint)", "-6.0000001"), isgreaterthan("$(test.product_zeropoint)", "-.0000001"), islessthan("$(test.product_zeropoint)", ".0000001"), }; reports: DEBUG:: "test.product_six = $(test.product_six)"; "test.product_minus_six = $(test.product_minus_six)"; "test.product_zero = $(test.product_zero)"; "test.product_sixpoint = $(test.product_sixpoint)"; "test.product_minus_sixpoint = $(test.product_minus_sixpoint)"; "test.product_zeropoint = $(test.product_zeropoint)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/data_readstringarray.cf.txt0000644000175100017510000000445212316547775027400 0ustar00a10038a1003800000000000000# app_name;instance;mmax;mmin;mperm;zone;tomcat_version;env;setenv;app_properties;newrelic;newrelic_name;newrelic_version;context_static;checks;action;context some_app_config;9123;8192;512;192;europe;tomcat7;live;;this string is short and no problem at all;true;blah;2.0.3;false;true;fix;app_server working_app_config;9123;8192;512;192;europe;tomcat7;live;;.23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789.;true;blah;2.0.3;false;true;fix;app_server not_working_app_config;9123;8192;512;192;europe;tomcat7;live;;.23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..;true;blah;2.0.3;false;true;fix;app_server cfengine-3.6.2/tests/acceptance/01_vars/02_functions/006.cf0000644000175100017510000000270012316547775022667 0ustar00a10038a1003800000000000000####################################################### # # Test diskfree() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "positive_disk" string => "$(G.etc)"; "p_disk" string => "$(G.etc_passwd)"; "zero_disk" string => "/lkjqeroiu"; "positive" int => diskfree("$(positive_disk)"); "p" int => diskfree("$(p_disk)"); "zero" int => diskfree("$(zero_disk)"); meta: "test_suppress_fail" string => "windows", meta => { "redmine4686" }; } ####################################################### bundle agent check { classes: "ok" and => { strcmp("$(test.zero)", "0"), isgreaterthan("$(test.p)", "0"), isgreaterthan("$(test.positive)", "0"), }; reports: DEBUG:: "Expected 0 size on $(test.zero_disk), found $(test.zero)"; "Expected >1 size on $(test.p_disk), found $(test.p)"; "Expected >1 size on $(test.positive_disk), found $(test.positive)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/029.cf0000644000175100017510000000276512243421446022670 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456"; "789"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readstringarrayidx.cf.txt0000644000175100017510000000445212316547775027114 0ustar00a10038a1003800000000000000# app_name;instance;mmax;mmin;mperm;zone;tomcat_version;env;setenv;app_properties;newrelic;newrelic_name;newrelic_version;context_static;checks;action;context some_app_config;9123;8192;512;192;europe;tomcat7;live;;this string is short and no problem at all;true;blah;2.0.3;false;true;fix;app_server working_app_config;9123;8192;512;192;europe;tomcat7;live;;.23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789.;true;blah;2.0.3;false;true;fix;app_server not_working_app_config;9123;8192;512;192;europe;tomcat7;live;;.23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..23456789..;true;blah;2.0.3;false;true;fix;app_server cfengine-3.6.2/tests/acceptance/01_vars/02_functions/variablesmatching.cf0000644000175100017510000000247412316547775026055 0ustar00a10038a1003800000000000000# Test that variablesmatching works correctly body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { vars: "test_fbeae67f3e347b5e0032302200141131" string => "abc", meta => { "x" }; "test_fbeae67f3e347b5e0032302200141131_1" string => "def", meta => { "x" }; "test_fbeae67f3e347b5e0032302200141131_2" string => "ghi", meta => { "y" }; } bundle agent test { vars: "vars" slist => variablesmatching("default:init.test_fbeae67f3e347b5e0032302200141131.*"); "x_vars" slist => variablesmatching("default:init.test_fbeae67f3e347b5e0032302200141131.*", "x"); "z_vars" slist => variablesmatching("default:init.test_fbeae67f3e347b5e0032302200141131.*", "z"); "count" int => length(vars); "x_count" int => length(x_vars); "z_count" int => length(z_vars); } bundle agent check { classes: "ok" and => { strcmp("$(test.count)", "3"), strcmp("$(test.x_count)", "2"), strcmp("$(test.z_count)", "0") }; reports: DEBUG:: "Found variables $(test.vars)"; "Found x variables $(test.x_vars)"; "Found z variables $(test.z_vars)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/401.cf0000644000175100017510000000473312243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarray(), introduce a singleton with no other fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 singleton 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[singleton][0])", "singleton"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[singleton][1]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[singleton][0] = 'singleton', saw '$(test.ary[singleton][0])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/032.cf0000644000175100017510000000255612243421446022660 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment","X",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok" and => { "ok_list", "ok123", islessthan("$(test.sum)", "123.457"), isgreaterthan("$(test.sum)", "123.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/410.cf0000644000175100017510000000501012312573725022651 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarray(), add some weird indices, real comments, character limit # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","^#.*",":+",10,14); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "bad" or => { isvariable("test.ary[he][1]"), isvariable("test.ary[blank][0]"), }; "ok" and => { "!bad", strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[he][0])", "he"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "saw 'bad'-class things"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[he][0] = 'he', saw '$(test.ary[he][0])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/bundlesmatching_dynamicsequence.cf0000644000175100017510000000155712243421446030760 0ustar00a10038a1003800000000000000# Test that bundlesmatching works correctly for dynamic sequences body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { } bundle agent test { vars: "runs" slist => bundlesmatching("default:run.*"); methods: "run them" usebundle => $(runs); } bundle agent check { classes: "ok" and => { ok1, ok2, ok3 }; reports: DEBUG:: "Found bundles $(test.runs)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } bundle agent run_123_456 { classes: "ok1" expression => "any", scope => "namespace"; } bundle agent run_789_0ab { classes: "ok2" expression => "any", scope => "namespace"; } bundle agent run_cde_fgh { classes: "ok3" expression => "any", scope => "namespace"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/002.cf0000644000175100017510000000465512332665147022666 0ustar00a10038a1003800000000000000####################################################### # # Test getgid() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_needs_work" string => "windows"; vars: linux|freebsd|solaris|openbsd|hpux:: "gid_daemon" int => getgid("daemon"); "gid_sys" int => getgid("sys"); darwin:: "gid_daemon" int => getgid("daemon"); aix:: "gid_sys" int => getgid("sys"); !linux.!freebsd.!solaris.!darwin.!openbsd.!hpux.!aix:: "gid_daemon" string => "fixme"; "gid_sys" string => "fixme"; linux|solaris|hpux:: "gid_0" int => getgid("root"); freebsd|darwin|openbsd:: "gid_0" int => getgid("wheel"); aix:: "gid_0" int => getgid("system"); !linux.!freebsd.!solaris.!darwin.!openbsd.!hpux.!aix:: "gid_0" string => "fixme"; archlinux|SuSE|redhat|gentoo:: "num_daemon" int => "2"; (linux.!archlinux.!SuSE.!redhat.!gentoo)|freebsd|darwin|openbsd:: "num_daemon" int => "1"; solaris:: "num_daemon" int => "12"; hpux:: "num_daemon" int => "5"; !linux.!freebsd.!solaris.!darwin.!openbsd.!hpux.!aix:: "num_daemon" string => "fixme"; linux|freebsd|solaris|openbsd|hpux|aix:: "num_sys" int => "3"; !linux.!freebsd.!solaris.!darwin.!openbsd.!hpux.!aix:: "num_sys" string => "fixme"; } ####################################################### bundle agent check { classes: darwin:: "ok_sys" expression => "any"; !darwin:: "ok_sys" expression => strcmp("$(test.gid_sys)", "$(test.num_sys)"); aix:: "ok_daemon" expression => "any"; !aix:: "ok_daemon" expression => strcmp("$(test.gid_daemon)", "$(test.num_daemon)"); any:: "ok" and => { strcmp("$(test.gid_0)", "0"), "ok_sys", "ok_daemon" }; reports: DEBUG:: "root/wheel is GID $(test.gid_0), expected 0"; "daemon is GID $(test.gid_daemon), expected $(test.num_daemon)"; "sys is GID $(test.gid_sys), expected $(test.num_sys)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readstringarrayidx.cf0000644000175100017510000000270412316547775026274 0ustar00a10038a1003800000000000000# Redmine#2926: test long lines with readstringarrayidx() body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "dim" int => readstringarrayidx("parms", "$(this.promise_filename).txt", "\s*#[^\n]*", ";", 9999, 99999); "pk" slist => getindices("parms"); reports: DEBUG:: "$(parms[$(pk)]): $(parms[$(pk)][0]) $(parms[$(pk)][16])"; } bundle agent check { vars: "length" int => length("test.pk"); "last" string => nth("test.value", 599); classes: "ok1" expression => strcmp("$(test.dim)", "3"); "ok2" expression => strcmp("$(test.dim)", "$(length)"); "ok3" expression => strcmp("$(test.parms[2][0])", "not_working_app_config"); "ok" and => { "ok1", "ok2", "ok3" }; reports: DEBUG.ok1:: "passed1"; DEBUG.ok2:: "passed2"; DEBUG.ok3:: "passed3"; DEBUG.!ok1:: "failed1 $(test.dim) != 3"; DEBUG.!ok2:: "failed2 $(test.dim) != $(length)"; DEBUG.!ok3:: "failed3 $(test.parms[2][0]) != not_working_app_config"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/read_long_file.cf.txt0000644000175100017510000001112412316547775026131 0ustar00a10038a1003800000000000000line1 line2 line3 line4 line5 line6 line7 line8 line9 line10 line11 line12 line13 line14 line15 line16 line17 line18 line19 line20 line21 line22 line23 line24 line25 line26 line27 line28 line29 line30 line31 line32 line33 line34 line35 line36 line37 line38 line39 line40 line41 line42 line43 line44 line45 line46 line47 line48 line49 line50 line51 line52 line53 line54 line55 line56 line57 line58 line59 line60 line61 line62 line63 line64 line65 line66 line67 line68 line69 line70 line71 line72 line73 line74 line75 line76 line77 line78 line79 line80 line81 line82 line83 line84 line85 line86 line87 line88 line89 line90 line91 line92 line93 line94 line95 line96 line97 line98 line99 line100 line101 line102 line103 line104 line105 line106 line107 line108 line109 line110 line111 line112 line113 line114 line115 line116 line117 line118 line119 line120 line121 line122 line123 line124 line125 line126 line127 line128 line129 line130 line131 line132 line133 line134 line135 line136 line137 line138 line139 line140 line141 line142 line143 line144 line145 line146 line147 line148 line149 line150 line151 line152 line153 line154 line155 line156 line157 line158 line159 line160 line161 line162 line163 line164 line165 line166 line167 line168 line169 line170 line171 line172 line173 line174 line175 line176 line177 line178 line179 line180 line181 line182 line183 line184 line185 line186 line187 line188 line189 line190 line191 line192 line193 line194 line195 line196 line197 line198 line199 line200 line201 line202 line203 line204 line205 line206 line207 line208 line209 line210 line211 line212 line213 line214 line215 line216 line217 line218 line219 line220 line221 line222 line223 line224 line225 line226 line227 line228 line229 line230 line231 line232 line233 line234 line235 line236 line237 line238 line239 line240 line241 line242 line243 line244 line245 line246 line247 line248 line249 line250 line251 line252 line253 line254 line255 line256 line257 line258 line259 line260 line261 line262 line263 line264 line265 line266 line267 line268 line269 line270 line271 line272 line273 line274 line275 line276 line277 line278 line279 line280 line281 line282 line283 line284 line285 line286 line287 line288 line289 line290 line291 line292 line293 line294 line295 line296 line297 line298 line299 line300 line301 line302 line303 line304 line305 line306 line307 line308 line309 line310 line311 line312 line313 line314 line315 line316 line317 line318 line319 line320 line321 line322 line323 line324 line325 line326 line327 line328 line329 line330 line331 line332 line333 line334 line335 line336 line337 line338 line339 line340 line341 line342 line343 line344 line345 line346 line347 line348 line349 line350 line351 line352 line353 line354 line355 line356 line357 line358 line359 line360 line361 line362 line363 line364 line365 line366 line367 line368 line369 line370 line371 line372 line373 line374 line375 line376 line377 line378 line379 line380 line381 line382 line383 line384 line385 line386 line387 line388 line389 line390 line391 line392 line393 line394 line395 line396 line397 line398 line399 line400 line401 line402 line403 line404 line405 line406 line407 line408 line409 line410 line411 line412 line413 line414 line415 line416 line417 line418 line419 line420 line421 line422 line423 line424 line425 line426 line427 line428 line429 line430 line431 line432 line433 line434 line435 line436 line437 line438 line439 line440 line441 line442 line443 line444 line445 line446 line447 line448 line449 line450 line451 line452 line453 line454 line455 line456 line457 line458 line459 line460 line461 line462 line463 line464 line465 line466 line467 line468 line469 line470 line471 line472 line473 line474 line475 line476 line477 line478 line479 line480 line481 line482 line483 line484 line485 line486 line487 line488 line489 line490 line491 line492 line493 line494 line495 line496 line497 line498 line499 line500 line501 line502 line503 line504 line505 line506 line507 line508 line509 line510 line511 line512 line513 line514 line515 line516 line517 line518 line519 line520 line521 line522 line523 line524 line525 line526 line527 line528 line529 line530 line531 line532 line533 line534 line535 line536 line537 line538 line539 line540 line541 line542 line543 line544 line545 line546 line547 line548 line549 line550 line551 line552 line553 line554 line555 line556 line557 line558 line559 line560 line561 line562 line563 line564 line565 line566 line567 line568 line569 line570 line571 line572 line573 line574 line575 line576 line577 line578 line579 line580 line581 line582 line583 line584 line585 line586 line587 line588 line589 line590 line591 line592 line593 line594 line595 line596 line597 line598 line599 line600 cfengine-3.6.2/tests/acceptance/01_vars/02_functions/500.cf0000644000175100017510000000531712243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test readintarray(), simple # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999:888:777:666 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readintarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999][0])", "999"), strcmp("$(test.ary[999][1])", "888"), strcmp("$(test.ary[999][2])", "777"), strcmp("$(test.ary[999][3])", "666"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999][0] = '999', saw '$(test.ary[999][0])'"; "expected test.ary[999][1] = '888', saw '$(test.ary[999][1])'"; "expected test.ary[999][2] = '777', saw '$(test.ary[999][2])'"; "expected test.ary[999][3] = '666', saw '$(test.ary[999][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/join.cf0000644000175100017510000000617412403637345023320 0ustar00a10038a1003800000000000000####################################################### # # test join() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "a" slist => { "b", "c", "a" }; "b" slist => { "100", "9", "10" }; "c" slist => { }; "d" slist => { "", "a", "", "b" }; "e" slist => { "a", "1", "b" }; "f" rlist => { "100", "200", "300" }; "g" rlist => { "1.11", "-2.22", "-3.33" }; "h" ilist => { "-10", "0", "200" }; "i" data => parsejson('[ 1, 2, "", 3000, "" ]'); "j" data => parsejson('[ 1, 2, [ 3, 4, 5 ], null, true, false ]'); "k" data => parsejson('{}'); "l" data => parsejson('{ "a": 100, "b": 200, "c": null}'); "m" slist => { "cf_null" }; "n" slist => { "a", "b", "c", "cf_null" }; "o" slist => { @(a), @(c) }; "p" slist => { @(c), @(m) }; "q" slist => { ":", ":" }; "r" slist => { ":", @(c) }; "s" slist => { ":", @(c), @(m) }; "t" slist => { @(n), @(m), @(n), ":" }; "lists" slist => { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t" }; } ####################################################### bundle agent test { vars: "lists" slist => { @(init.lists) }; "join_$(lists)" string => join(":", "init.$(lists)"); } ####################################################### bundle agent check { vars: "lists" slist => { @(init.lists) }; "expected_a" string => "b:c:a"; "expected_b" string => "100:9:10"; "expected_c" string => ""; "expected_d" string => ":a::b"; "expected_e" string => "a:1:b"; "expected_f" string => "100:200:300"; "expected_g" string => "1.11:-2.22:-3.33"; "expected_h" string => "-10:0:200"; "expected_i" string => "1:2::3000:"; "expected_j" string => "1:2:true:false"; "expected_k" string => ""; "expected_l" string => "100:200"; "expected_m" string => ""; "expected_n" string => "a:b:c"; "expected_o" string => "b:c:a"; "expected_p" string => ""; "expected_q" string => ":::"; "expected_r" string => ":"; "expected_s" string => ":"; "expected_t" string => "a:b:c:a:b:c::"; classes: "ok_$(lists)" expression => strcmp("$(expected_$(lists))", "$(test.join_$(lists))"); "not_ok_$(lists)" not => strcmp("$(expected_$(lists))", "$(test.join_$(lists))"); "ok" and => { "ok_a", "ok_b", "ok_c", "ok_d", "ok_e", "ok_f", "ok_g", "ok_h", "ok_i", "ok_j", "ok_k", "ok_l", "ok_m", "ok_n", "ok_o", "ok_p", "ok_q", "ok_r", "ok_s", "ok_t" }; reports: DEBUG:: "mismatch: expected '$(expected_$(lists))' vs. actual '$(test.join_$(lists))'" ifvarclass => "not_ok_$(lists)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/442.cf0000644000175100017510000000577612243421446022674 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarrayidx(), introduce a duplicate key # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test this:too 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "4"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "this"), strcmp("$(test.ary[1][1])", "is"), strcmp("$(test.ary[1][2])", "a"), strcmp("$(test.ary[1][3])", "test"), strcmp("$(test.ary[2][0])", "this"), strcmp("$(test.ary[2][1])", "too"), strcmp("$(test.ary[3][0])", "1"), strcmp("$(test.ary[3][1])", "2"), strcmp("$(test.ary[3][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][4]"), isvariable("test.ary[2][2]"), isvariable("test.ary[3][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = 'this', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = 'is', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = 'a', saw '$(test.ary[1][2])'"; "expected test.ary[1][3] = 'test', saw '$(test.ary[1][3])'"; "expected test.ary[2][0] = 'this', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'too', saw '$(test.ary[2][1])'"; "expected test.ary[3][0] = '1', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = '2', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '3', saw '$(test.ary[3][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/unique.cf0000644000175100017510000000423412316547775023674 0ustar00a10038a1003800000000000000####################################################### # # Test unique() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { "starting list = 1,2,3,one,two,three,long string,four,fix,six,one,two,three", "starting length = 13", "unique list = 1,2,3,one,two,three,long string,four,fix,six", "unique length = 10", }; files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "test_str" string => join(",", "test"); "test_len" int => length(test); "test_unique" slist => unique("test"); "unique_str" string => join(",", "test_unique"); "unique_len" int => length(test_unique); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "starting list = $(test.test_str)"; "starting length = $(test.test_len)"; "unique list = $(test.unique_str)"; "unique length = $(test.unique_len)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/read_sys_file.cf0000644000175100017510000000414712243421446025162 0ustar00a10038a1003800000000000000# Redmine#1032: Test that /sys and /proc files with 0 length are succesfully read by readfile() function body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { classes: "have_sys" expression => fileexists("/sys/kernel/vmcoreinfo"); "have_proc0" expression => fileexists("/proc/meminfo"); "have_proc1" expression => fileexists("/proc/kallsyms"); vars: have_sys:: "sys_info" string => readfile("/sys/kernel/vmcoreinfo", 0); !have_sys:: "sys_info" string => "42"; have_proc0:: "proc0_info" string => readfile("/proc/meminfo", 0); !have_proc0:: "proc0_info" string => "42"; have_proc1:: "proc1_info" string => readfile("/proc/kallsyms", 0); !have_proc1:: "proc1_info" string => "42"; } bundle agent check { classes: "ok_proc0" expression => regcmp(".*\d+.*", $(test.proc0_info)); "ok_proc1" expression => regcmp(".*\d+.*", $(test.proc1_info)); "not_ok_proc0" not => regcmp(".*\d+.*", $(test.proc0_info)); "not_ok_proc1" not => regcmp(".*\d+.*", $(test.proc1_info)); "ok_sys" expression => regcmp(".*\d+.*", $(test.sys_info)); "not_ok_sys" not => regcmp(".*\d+.*", $(test.sys_info)); "ok" not => classmatch("not_ok_.+"); reports: DEBUG:: "/proc0 test OK" ifvarclass => "ok_proc0"; "/proc1 test OK" ifvarclass => "ok_proc1"; "/sys test OK" ifvarclass => "ok_sys"; "/proc0 test NOT OK: data '$(test.proc0_info)' did not contain digits" ifvarclass => "not_ok_proc0"; "/proc1 test NOT OK: data '$(test.proc1_info)' did not contain digits" ifvarclass => "not_ok_proc1"; "/sys test NOT OK: data '$(test.sys_info)' did not contain digits" ifvarclass => "not_ok_sys"; DEBUG.inform_mode:: "/proc0 test got data '$(test.proc0_info)'"; "/proc1 test got data '$(test.proc1_info)'"; "/sys test got data '$(test.sys_info)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/450.cf0000644000175100017510000000500612312573725022662 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarrayidx(), add some weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","^#.*",":+",10,14); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "bad" or => { isvariable("test.ary[2][1]"), isvariable("test.ary[3][0]"), }; "ok" and => { "!bad", strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "he"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "saw 'bad'-class things"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'he', saw '$(test.ary[2][0])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/067.cf0000644000175100017510000000307412332665147022673 0ustar00a10038a1003800000000000000####################################################### # # Test getusers() arg1 only # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: # All users except root, bin, and daemon freebsd|openbsd:: "users" slist => getusers("","0,1,3"); !freebsd.!openbsd:: "users" slist => getusers("","0,1,2"); files: "$(G.testfile)" delete => init_delete; reports: cfengine_3:: "$(users)" report_to_file => "$(G.testfile)"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: # Try to delete the lines that shouldn't be there anyway "$(G.testfile)" edit_line => test_delete, classes => full_set; } bundle edit_line test_delete { delete_lines: "root"; "daemon"; "bin"; } body classes full_set { promise_kept => { "pass" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { classes: "ok" expression => "pass&!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/bundlesmatching.cf0000644000175100017510000000503712316547775025537 0ustar00a10038a1003800000000000000# Test that bundlesmatching works correctly body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { } bundle agent test { vars: "runs" slist => bundlesmatching("default:run.*"); "run_123s" slist => bundlesmatching("default:run_123.*"); "bundle_123" string => nth(run_123s, 0); "run_meta_deprecated_unsorted" slist => bundlesmatching("default:run_meta.*", "deprecated"); "run_meta_deprecated" slist => sort(run_meta_deprecated_unsorted, "lex"); "bundle_deprecated" string => nth(run_meta_deprecated, 0); "run_meta_obsoleted_unsorted" slist => bundlesmatching("default:run_meta.*", "obs.*", "deprecated"); "run_meta_obsoleted" slist => sort(run_meta_obsoleted_unsorted, "lex"); "bundle_obsoleted" string => nth(run_meta_obsoleted, 0); "count" int => length(runs); "123_count" int => length(run_123s); "deprecated_count" int => length(run_meta_deprecated); "obsoleted_count" int => length(run_meta_obsoleted); } bundle agent check { classes: "ok" and => { strcmp("$(test.count)", "6"), strcmp("$(test.123_count)", "1"), strcmp("$(test.deprecated_count)", "2"), strcmp("$(test.bundle_deprecated)", "default:run_meta_deprecated"), strcmp("$(test.obsoleted_count)", "1"), strcmp("$(test.bundle_obsoleted)", "default:run_meta_deprecated"), strcmp("$(test.bundle_123)", "default:run_123_456") }; reports: DEBUG:: "Runs count $(test.count)"; "123 count $(test.123_count)"; "Deprecated count $(test.deprecated_count)"; "'obs.*' && deprecated count $(test.obsoleted_count)"; "Found bundles $(test.runs)"; "Found 123 bundles $(test.run_123s)"; "First 123 bundle is $(test.bundle_123)"; "Found deprecated bundles $(test.run_meta_deprecated)"; "First deprecated bundle is $(test.bundle_deprecated)"; "Found obsoleted bundles $(test.run_meta_obsoleted)"; "First obsoleted bundle is $(test.bundle_obsoleted)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } bundle agent run_123_456 { } bundle agent run_789_0ab { } bundle agent run_cde_fgh { } bundle agent run_meta_deprecated { meta: "tags" slist => { "deprecated", "obsoleted" }; } bundle agent run_meta_string_tags { meta: "tags" string => "deprecated"; } bundle agent run_meta_missing_tags { } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/0000755000175100017510000000000012411001073023451 5ustar00a10038a1003800000000000000parsestringarray_weird_indices_real_comments2.cf0000644000175100017510000001101112243421446035175 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, real comments # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","^#.*",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "this"), strcmp("$(test.ary[6][1])", "also"), strcmp("$(test.ary[7][0])", "last"), strcmp("$(test.ary[7][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = 'this', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = 'also', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'last', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'one', saw '$(test.ary[7][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readintarray_non_integers.cf0000644000175100017510000000521512243421446031242 0ustar00a10038a1003800000000000000####################################################### # # Test parseintarray(), introduce 777 duplicate key # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999:888:777:666 999:000 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parseintarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; # 4 lines, but 3 unique keys } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), # The second value should overwrite the first strcmp("$(test.ary[999][0])", "999"), strcmp("$(test.ary[999][1])", "0"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999][2]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999][0] = '999', saw '$(test.ary[999][0])'"; "expected test.ary[999][1] = '0', saw '$(test.ary[999][1])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readintarray_duplicate_key.cf0000644000175100017510000000512412243421446031371 0ustar00a10038a1003800000000000000####################################################### # # Test readintarray(), introduce 777 duplicate key # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999:888:777:666 999:000 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readintarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; # 4 lines, but 3 unique keys } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), # The second value should overwrite the first strcmp("$(test.ary[999][0])", "999"), strcmp("$(test.ary[999][1])", "0"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999][2]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999][0] = '999', saw '$(test.ary[999][0])'"; "expected test.ary[999][1] = '0', saw '$(test.ary[999][1])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/datatype.cf0000644000175100017510000002054712332665147025632 0ustar00a10038a1003800000000000000####################################################### # # Test datatype() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" string => 'jsonstring = { "person": { "first": "miyamoto", "last": "musashi" }, "birth": null, "death": 16450613, "go rin no sho": { "1": "ground", "2": "water", "3": "fire", "4": "wind", "5": "void" }, "dokkōdō": [ "accept everything just the way it is.", "do not seek pleasure for its own sake.", "do not, under any circumstances, depend on a partial feeling.", "think lightly of yourself and deeply of the world.", "be detached from desire your whole life.", "do not regret what you have done.", "never be jealous.", "never let yourself be saddened by a separation.", "resentment and complaint are appropriate neither for oneself nor others.", "do not let yourself be guided by the feeling of lust or love.", "In all things, have no preferences.", "be indifferent to where you live.", "do not pursue the taste of good food.", "do not hold on to possessions you no longer need.", "do not act following customary beliefs.", "do not collect weapons or practice with weapons beyond what is useful.", "do not fear death.", "do not seek to possess either goods or fiefs for your old age.", "respect buddha and the gods without counting on their help.", "you may abandon your own body but you must preserve your honor.", "never stray from the way." ], "styles": [ "two heavens as one", "two swords as one" ], "decidable": false, "dituri was here": 3.1416 }'; "results2" string => '--------------------- toplevel:key = person toplevel:key = birth toplevel:key = death toplevel:key = go rin no sho toplevel:key = dokkōdō toplevel:key = styles toplevel:key = decidable toplevel:key = dituri was here toplevel[person]:type = json_object toplevel[birth]:type = json_null toplevel[death]:type = json_integer toplevel[go rin no sho]:type = json_object toplevel[dokkōdō]:type = json_array toplevel[styles]:type = json_array toplevel[decidable]:type = json_bool toplevel[dituri was here]:type = json_real ------------------------------------------ toplevel[person]:key= first toplevel[go rin no sho]:key= 1 toplevel[dokkōdō]:key= 0 toplevel[styles]:key= 0 toplevel[person]:key= last toplevel[go rin no sho]:key= 2 toplevel[go rin no sho]:key= 3 toplevel[go rin no sho]:key= 4 toplevel[go rin no sho]:key= 5 toplevel[dokkōdō]:key= 1 toplevel[dokkōdō]:key= 2 toplevel[dokkōdō]:key= 3 toplevel[dokkōdō]:key= 4 toplevel[dokkōdō]:key= 5 toplevel[dokkōdō]:key= 6 toplevel[dokkōdō]:key= 7 toplevel[dokkōdō]:key= 8 toplevel[dokkōdō]:key= 9 toplevel[dokkōdō]:key= 10 toplevel[dokkōdō]:key= 11 toplevel[dokkōdō]:key= 12 toplevel[dokkōdō]:key= 13 toplevel[dokkōdō]:key= 14 toplevel[dokkōdō]:key= 15 toplevel[dokkōdō]:key= 16 toplevel[dokkōdō]:key= 17 toplevel[dokkōdō]:key= 18 toplevel[dokkōdō]:key= 19 toplevel[dokkōdō]:key= 20 toplevel[styles]:key= 1'; "results3" string => 'toplevel[person][first]:type = json_string toplevel[go rin no sho][1]:type = json_string toplevel[dokkōdō][0]:type = json_string toplevel[styles][0]:type = json_string toplevel[person][last]:type = json_string toplevel[go rin no sho][2]:type = json_string toplevel[go rin no sho][3]:type = json_string toplevel[go rin no sho][4]:type = json_string toplevel[go rin no sho][5]:type = json_string toplevel[dokkōdō][1]:type = json_string toplevel[dokkōdō][2]:type = json_string toplevel[dokkōdō][3]:type = json_string toplevel[dokkōdō][4]:type = json_string toplevel[dokkōdō][5]:type = json_string toplevel[dokkōdō][6]:type = json_string toplevel[dokkōdō][7]:type = json_string toplevel[dokkōdō][8]:type = json_string toplevel[dokkōdō][9]:type = json_string toplevel[dokkōdō][10]:type = json_string toplevel[dokkōdō][11]:type = json_string toplevel[dokkōdō][12]:type = json_string toplevel[dokkōdō][13]:type = json_string toplevel[dokkōdō][14]:type = json_string toplevel[dokkōdō][15]:type = json_string toplevel[dokkōdō][16]:type = json_string toplevel[dokkōdō][17]:type = json_string toplevel[dokkōdō][18]:type = json_string toplevel[dokkōdō][19]:type = json_string toplevel[dokkōdō][20]:type = json_string toplevel[styles][1]:type = json_string ok: datatype(datastr) failed properly'; files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; "$(init.results2)"; "$(init.results3)"; } ####################################################### bundle common test_common { vars: "datastr" string => storejson("data"); "data" data => parsejson(' { "person": { "first": "miyamoto", "last": "musashi" }, "birth": null, "death": 16450613, "go rin no sho": { "1": "ground", "2": "water", "3": "fire", "4": "wind", "5": "void" }, "dokkōdō": [ "accept everything just the way it is.", "do not seek pleasure for its own sake.", "do not, under any circumstances, depend on a partial feeling.", "think lightly of yourself and deeply of the world.", "be detached from desire your whole life.", "do not regret what you have done.", "never be jealous.", "never let yourself be saddened by a separation.", "resentment and complaint are appropriate neither for oneself nor others.", "do not let yourself be guided by the feeling of lust or love.", "In all things, have no preferences.", "be indifferent to where you live.", "do not pursue the taste of good food.", "do not hold on to possessions you no longer need.", "do not act following customary beliefs.", "do not collect weapons or practice with weapons beyond what is useful.", "do not fear death.", "do not seek to possess either goods or fiefs for your old age.", "respect buddha and the gods without counting on their help.", "you may abandon your own body but you must preserve your honor.", "never stray from the way." ], "styles": ["two heavens as one","two swords as one"], "decidable": false "dituri was here": 3.14159265 } '); "typenames" slist => { "person", "go rin no sho", "dokkōdō", "styles" }; "keys[top]" slist => getindices("data"); "types[top][$(keys[top])]" string => datatype("data[$(keys[top])]"); "keys[$(typenames)]" slist => getindices("data[$(typenames)]"); "types[$(typenames)][$(keys[$(typenames)])]" string => datatype("data[$(typenames)][$(keys[$(typenames)])]"); "bad_type_test" string => datatype("datastr"); classes: "ok_invalid_test_failed" not => isvariable("bad_type_test"); } bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: cfengine:: "jsonstring = $(test_common.datastr)"; "---------------------"; "toplevel:key = $(test_common.keys[top])"; "toplevel[$(test_common.keys[top])]:type = $(test_common.types[top][$(test_common.keys[top])])"; "------------------------------------------"; "toplevel[$(test_common.typenames)]:key= $(test_common.keys[$(test_common.typenames)])"; "toplevel[$(test_common.typenames)][$(test_common.keys[$(test_common.typenames)])]:type = $(test_common.types[$(test_common.typenames)][$(test_common.keys[$(test_common.typenames)])])"; ok_invalid_test_failed:: "------------------------------------------"; "ok: datatype(datastr) failed properly"; !ok_invalid_test_failed:: "------------------------------------------"; "NOT_OK: datatype(datastr) was supposed to fail"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readintarray_non_integers3.cf0000644000175100017510000000544212243421446031327 0ustar00a10038a1003800000000000000####################################################### # # Test readintarray(), introduce non-integers (issue 313 and 368) # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999::bogus:666 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parseintarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999][0])", "999"), strcmp("$(test.ary[999][1])", "0"), strcmp("$(test.ary[999][2])", "0"), strcmp("$(test.ary[999][3])", "666"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999][0] = '999', saw '$(test.ary[999][0])'"; "expected test.ary[999][1] = '0', saw '$(test.ary[999][1])'"; "expected test.ary[999][2] = '0', saw '$(test.ary[999][2])'"; "expected test.ary[999][3] = '999', saw '$(test.ary[999][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarrayidx_weird_indices_duplicate.cf0000644000175100017510000001162412243421446034754 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarrayidx(), add some weird indices (including a duplicate) # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "9"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "# A duplicate follows"), strcmp("$(test.ary[6][1])", " this line is not always a comment"), strcmp("$(test.ary[7][0])", "this"), strcmp("$(test.ary[7][1])", "also"), strcmp("$(test.ary[8][0])", "last"), strcmp("$(test.ary[8][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = '# A duplicate follows', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ' this line is not always a comment', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'this', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'also', saw '$(test.ary[7][1])'"; "expected test.ary[8][0] = 'last', saw '$(test.ary[8][0])'"; "expected test.ary[8][1] = 'one', saw '$(test.ary[8][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_dontread_comment_duplicate_lastline.cf0000644000175100017510000001113212243421446036646 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), don't read comment, duplicate key or last line # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(testfile)","NoComment",":",6,1000); "num" int => "6"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "is"), strcmp("$(test.ary[this][2])", "a"), strcmp("$(test.ary[this][3])", "test"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } readstringarray_introduce_nonparsed_comment.cf0000644000175100017510000000634612243421446035002 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarray(), introduce a non-parsed comment # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 # Not parsed as a comment this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "4"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[# Not parsed as a comment][0])", "# Not parsed as a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "is"), strcmp("$(test.ary[this][2])", "a"), strcmp("$(test.ary[this][3])", "test"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[# Not parsed as a comment][1]"), isvariable("test.ary[this][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[# Not parsed as a comment][0] = '# Not parsed as a comment', saw 'expected $(test.ary[# Not parsed as a comment][0])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_real_comments_noemptyfields4.cf0000644000175100017510000001045112243421446040150 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)","^#.*",":+"1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","^#.*",":+",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", "in here"), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "this"), strcmp("$(test.ary[6][1])", "also"), strcmp("$(test.ary[7][0])", "last"), strcmp("$(test.ary[7][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = 'in here', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = 'this', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = 'also', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'last', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'one', saw '$(test.ary[7][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/accumulated2.cf0000644000175100017510000000171012243421446026350 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,1000,1000,1000,1000,40000); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/parsestringarrayidx_duplicate_key.cf0000644000175100017510000000606412243421446033015 0ustar00a10038a1003800000000000000####################################################### # # Test parsestringarrayidx(), introduce a duplicate key # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test this:too 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "4"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "this"), strcmp("$(test.ary[1][1])", "is"), strcmp("$(test.ary[1][2])", "a"), strcmp("$(test.ary[1][3])", "test"), strcmp("$(test.ary[2][0])", "this"), strcmp("$(test.ary[2][1])", "too"), strcmp("$(test.ary[3][0])", "1"), strcmp("$(test.ary[3][1])", "2"), strcmp("$(test.ary[3][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][4]"), isvariable("test.ary[2][2]"), isvariable("test.ary[3][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = 'this', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = 'is', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = 'a', saw '$(test.ary[1][2])'"; "expected test.ary[1][3] = 'test', saw '$(test.ary[1][3])'"; "expected test.ary[2][0] = 'this', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'too', saw '$(test.ary[2][1])'"; "expected test.ary[3][0] = '1', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = '2', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '3', saw '$(test.ary[3][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readstringarray_introduce_duplicate.cf0000644000175100017510000000520512243421446033311 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarray(), introduce a duplicate key # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test this:too 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; # 4 lines, but 3 unique keys } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), # The second value should overwrite the first strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "too"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[this][2]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'too', saw '$(test.ary[this][1])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } readstringarray_weird_indices_real_comments.cf0000644000175100017510000001156212243421446034727 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarray(), weird indices, real comments # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","^#.*",":",10,1000); "num" int => "7"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][0])", "fields"), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[blank][0])", "in here"), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = 'fields', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = 'in here', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarrayidx_nonparsed_comment.cf0000644000175100017510000000612112243421446033621 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarrayidx(), introduce a non-parsed comment # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 # Not parsed as a comment this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "4"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "# Not parsed as a comment"), strcmp("$(test.ary[2][0])", "this"), strcmp("$(test.ary[2][1])", "is"), strcmp("$(test.ary[2][2])", "a"), strcmp("$(test.ary[2][3])", "test"), strcmp("$(test.ary[3][0])", "1"), strcmp("$(test.ary[3][1])", "2"), strcmp("$(test.ary[3][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][1]"), isvariable("test.ary[2][4]"), isvariable("test.ary[3][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/host2ip.cf0000644000175100017510000000324612243421446025375 0ustar00a10038a1003800000000000000####################################################### # # Test host2ip() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: # Neither of these are likely to change... "localhost" string => ip2host("127.0.0.1"); "localhost_6" string => ip2host("::1"); "a" string => ip2host("198.41.0.4"); "a_6" string => ip2host("2001:503:ba3e::2:30"); } ####################################################### bundle agent check { vars: "localhost" string => "localhost"; "a" string => "a.root-servers.net"; classes: "ok_a" and => { strcmp("$(test.a)", "$(a)"), strcmp("$(test.a_6)", "$(a)"), }; "ok_localhost" and => { strcmp("$(test.localhost)", "$(localhost)"), strcmp("$(test.localhost_6)", "$(localhost)"), }; "ok" and => { "ok_a", "ok_localhost", }; reports: DEBUG:: "Expected ($(test.localhost) and $(test.localhost_6)) == $(localhost)"; "Expected ($(test.a) and $(test.a_6)) == $(a)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readrealarray_non_integers2.cf0000644000175100017510000000551312243421446031456 0ustar00a10038a1003800000000000000####################################################### # # Test readrealarray(), introduce non-integers (issue 313 and 368) # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999.9::bogus:666.6 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parserealarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999.9][0])", "999.9"), strcmp("$(test.ary[999.9][1])", "0"), strcmp("$(test.ary[999.9][2])", "0"), strcmp("$(test.ary[999.9][3])", "666.6"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999.9][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999.9][0] = '999.9', saw '$(test.ary[999.9][0])'"; "expected test.ary[999.9][1] = '0', saw '$(test.ary[999.9][1])'"; "expected test.ary[999.9][2] = '0', saw '$(test.ary[999.9][2])'"; "expected test.ary[999.9][3] = '666.6', saw '$(test.ary[999.9][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_introduce_duplicate_key.cf0000644000175100017510000000527612243421446034311 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), introduce a duplicate key # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test this:too 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; # 4 lines, but 3 unique keys } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), # The second value should overwrite the first strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "too"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[this][2]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'too', saw '$(test.ary[this][1])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readintlist.cf0000644000175100017510000000300712243421446026322 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123, ,456,789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readreallist2.cf0000644000175100017510000000302212243421446026532 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123,broken,456,789"; # non-numeric fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_change_comment_parsing.cf0000644000175100017510000001213512243421446036765 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, change comment parsing # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[# A duplicate follows][0])", "# A duplicate follows"), strcmp("$(test.ary[# A duplicate follows][1])", "this line is not always a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/parserealarray_duplicate_key.cf0000644000175100017510000000525012243421446031721 0ustar00a10038a1003800000000000000####################################################### # # Test parserealarray(), introduce 777 duplicate key # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999.9:888:777:666.6 999.9:000 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parserealarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; # 4 lines, but 3 unique keys } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), # The second value should overwrite the first strcmp("$(test.ary[999.9][0])", "999.9"), strcmp("$(test.ary[999.9][1])", "0"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999.9][2]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999.9][0] = '999.9', saw '$(test.ary[999.9][0])'"; "expected test.ary[999.9][1] = '0', saw '$(test.ary[999.9][1])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/accumulated.cf0000644000175100017510000000167212243421446026275 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(315,0,0,0,0,0); } ####################################################### bundle agent check { vars: "time" int => "9933840000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_change_separator_to_s.cf0000644000175100017510000000715412243421446033741 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), change separator to 's' # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","^#.*","s+",10,1000); "num" int => "7"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0:1:2][0])", "0:1:2"), strcmp("$(test.ary[1:2:3][0])", "1:2:3"), strcmp("$(test.ary[here i][0])", "here i"), strcmp("$(test.ary[here i][1])", ":a line: with space"), strcmp("$(test.ary[here i][2])", " : in it"), strcmp("$(test.ary[blank field][0])", "blank field"), strcmp("$(test.ary[blank field][2])", "::: in here::"), strcmp("$(test.ary[:leading blank field][0])", "leading blank field"), strcmp("$(test.ary[thi][0])", "thi"), strcmp("$(test.ary[thi][1])", ":also"), strcmp("$(test.ary[thi][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[thi][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[la][0])", "la"), strcmp("$(test.ary[la][1])", "t:one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0:1:2][0] = '0:1:2', saw '$(test.ary[0:1:2][0])'"; "expected test.ary[1:2:3][0] = '1:2:3', saw '$(test.ary[1:2:3][0])'"; "expected test.ary[here i][0] = 'here i', saw '$(test.ary[here i][0])'"; "expected test.ary[here i][1] = ':a line: with space', saw '$(test.ary[here i][1])'"; "expected test.ary[here i][2] = ' : in it', saw '$(test.ary[here i][2])'"; "expected test.ary[blank field][0] = 'blank field', saw '$(test.ary[blank field][0])'"; "expected test.ary[blank field][2] = '::: in here::', saw '$(test.ary[blank field][2])'"; "expected test.ary[:leading blank field][0] = 'leading blank field', saw '$(test.ary[:leading blank field][0])'"; "expected test.ary[thi][0] = 'thi', saw '$(test.ary[thi][0])'"; "expected test.ary[thi][1]) = ':also', saw '$(test.ary[thi][1]))'"; "expected test.ary[thi][2]) = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[thi][2]))'"; "expected test.ary[thi][3]) = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[thi][3]))'"; "expected test.ary[la][0]) = 'la', saw '$(test.ary[la][0]))'"; "expected test.ary[la][1]) = 't:one', saw '$(test.ary[la][1]))'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_duplicates_trailing_newlines2.cf0000644000175100017510000001162412243421446040311 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, duplicate and trailing newlines # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one "; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "9"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "# A duplicate follows"), strcmp("$(test.ary[6][1])", " this line is not always a comment"), strcmp("$(test.ary[7][0])", "this"), strcmp("$(test.ary[7][1])", "also"), strcmp("$(test.ary[8][0])", "last"), strcmp("$(test.ary[8][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = '# A duplicate follows', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ' this line is not always a comment', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'this', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'also', saw '$(test.ary[7][1])'"; "expected test.ary[8][0] = 'last', saw '$(test.ary[8][0])'"; "expected test.ary[8][1] = 'one', saw '$(test.ary[8][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } readstringarray_change_separator_to_s.cf0000644000175100017510000000706312243421446033541 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarray(), change separator to 's' # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","^#.*","s+",10,1000); "num" int => "7"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0:1:2][0])", "0:1:2"), strcmp("$(test.ary[1:2:3][0])", "1:2:3"), strcmp("$(test.ary[here i][0])", "here i"), strcmp("$(test.ary[here i][1])", ":a line: with space"), strcmp("$(test.ary[here i][2])", " : in it"), strcmp("$(test.ary[blank field][0])", "blank field"), strcmp("$(test.ary[blank field][2])", "::: in here::"), strcmp("$(test.ary[:leading blank field][0])", "leading blank field"), strcmp("$(test.ary[thi][0])", "thi"), strcmp("$(test.ary[thi][1])", ":also"), strcmp("$(test.ary[thi][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[thi][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[la][0])", "la"), strcmp("$(test.ary[la][1])", "t:one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0:1:2][0] = '0:1:2', saw '$(test.ary[0:1:2][0])'"; "expected test.ary[1:2:3][0] = '1:2:3', saw '$(test.ary[1:2:3][0])'"; "expected test.ary[here i][0] = 'here i', saw '$(test.ary[here i][0])'"; "expected test.ary[here i][1] = ':a line: with space', saw '$(test.ary[here i][1])'"; "expected test.ary[here i][2] = ' : in it', saw '$(test.ary[here i][2])'"; "expected test.ary[blank field][0] = 'blank field', saw '$(test.ary[blank field][0])'"; "expected test.ary[blank field][2] = '::: in here::', saw '$(test.ary[blank field][2])'"; "expected test.ary[:leading blank field][0] = 'leading blank field', saw '$(test.ary[:leading blank field][0])'"; "expected test.ary[thi][0] = 'thi', saw '$(test.ary[thi][0])'"; "expected test.ary[thi][1]) = ':also', saw '$(test.ary[thi][1]))'"; "expected test.ary[thi][2]) = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[thi][2]))'"; "expected test.ary[thi][3]) = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[thi][3]))'"; "expected test.ary[la][0]) = 'la', saw '$(test.ary[la][0]))'"; "expected test.ary[la][1]) = 't:one', saw '$(test.ary[la][1]))'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } getvalues_size5_with_duplicate_triplicate.cf0000644000175100017510000000306412332665147034356 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test getvalues(), size 5 with a duplicate and a triplicate # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "zero" string => "zero"; "one" string => "one"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "zero"; "one"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "$(zero)"; "array[gamma's]" string => "one"; "array[delta-delta:delta]" string => "$(one)"; "array[last]" string => "one"; "vals" slist => getvalues("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } readstringarrayidx_change_separator_to_s.cf0000644000175100017510000000720312243421446034242 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarrayidx(), change separator to 's' # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","^#.*","s+",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0:1:2"), strcmp("$(test.ary[1][0])", "1:2:3"), strcmp("$(test.ary[2][0])", "here i"), strcmp("$(test.ary[2][1])", ":a line: with "), strcmp("$(test.ary[2][2])", "pace"), strcmp("$(test.ary[2][3])", " : in it"), strcmp("$(test.ary[3][0])", "blank:field"), strcmp("$(test.ary[3][1])", ":::in here::"), strcmp("$(test.ary[4][0])", ":leading blank field"), strcmp("$(test.ary[5][0])", "thi"), strcmp("$(test.ary[5][1])", ":i"), strcmp("$(test.ary[5][2])", ":a:te"), strcmp("$(test.ary[5][3])", "t"), strcmp("$(test.ary[6][0])", "thi"), strcmp("$(test.ary[6][1])", ":al"), strcmp("$(test.ary[6][2])", "o"), strcmp("$(test.ary[7][0])", "la"), strcmp("$(test.ary[7][1])", "t:one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0:1:2', saw '$(test.ary[0][0])'"; "expected test.ary[1][0] = '1:2:3', saw '$(test.ary[1][0])'"; "expected test.ary[2][0] = 'here i', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = ':a line: with ', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = 'pace', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' : in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank:field', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = ':::in here::', saw '$(test.ary[3][1])'"; "expected test.ary[4][0] = ':leading blank field', saw '$(test.ary[4][0])'"; "expected test.ary[5][0] = 'thi', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = ':i', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = ':a:te', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 't', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = 'thi', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ':al', saw '$(test.ary[6][1])'"; "expected test.ary[6][2] = 'o', saw '$(test.ary[6][2])'"; "expected test.ary[7][0] = 'la', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 't:one', saw '$(test.ary[7][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/getvalues_size2.cf0000644000175100017510000000256112332665147027126 0ustar00a10038a1003800000000000000####################################################### # # Test getvalues(), size 2 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "zero"; "one"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "two"; "vals" slist => getvalues("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } parsestringarray_weird_indices_real_comments_noemptyfields.cf0000644000175100017510000001076512243421446040074 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","^#.*",":+",10,1000); "num" int => "7"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", "in here"), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = 'in here', saw '$(test.ary[blank][2])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readrealarray_duplicate_key.cf0000644000175100017510000000515712243421446031530 0ustar00a10038a1003800000000000000####################################################### # # Test readrealarray(), introduce 777 duplicate key # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999.9:888:777:666.6 999.9:000 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readrealarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; # 4 lines, but 3 unique keys } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), # The second value should overwrite the first strcmp("$(test.ary[999.9][0])", "999.9"), strcmp("$(test.ary[999.9][1])", "0"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999.9][2]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999.9][0] = '999.9', saw '$(test.ary[999.9][0])'"; "expected test.ary[999.9][1] = '0', saw '$(test.ary[999.9][1])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readstringarray_weird_indices.cf0000644000175100017510000001206612243421446032076 0ustar00a10038a1003800000000000000####################################################### # # Test readstringarray(), add some weird indices (including a duplicate) # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[# A duplicate follows][0])", "# A duplicate follows"), strcmp("$(test.ary[# A duplicate follows][1])", "this line is not always a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readintlist2.cf0000644000175100017510000000302012243421446026377 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123,broken,456,789"; # non-numeric fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readreallist.cf0000644000175100017510000000301112243421446026446 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123, ,456,789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/parsestringarrayinx_simple.cf0000644000175100017510000000542412243421446031475 0ustar00a10038a1003800000000000000####################################################### # # Test parsestringarrayidx(), simple # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "this"), strcmp("$(test.ary[1][1])", "is"), strcmp("$(test.ary[1][2])", "a"), strcmp("$(test.ary[1][3])", "test"), strcmp("$(test.ary[2][0])", "1"), strcmp("$(test.ary[2][1])", "2"), strcmp("$(test.ary[2][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][4]"), isvariable("test.ary[2][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = 'this', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = 'is', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = 'a', saw '$(test.ary[1][2])'"; "expected test.ary[1][3] = 'test', saw '$(test.ary[1][3])'"; "expected test.ary[2][0] = '1', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = '2', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = '3', saw '$(test.ary[2][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/getvalues_size5.cf0000644000175100017510000000307312332665147027130 0ustar00a10038a1003800000000000000####################################################### # # Test getvalues(), size 5 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "zero"; "one"; "three's"; "four-fore:quatre"; "last"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "two"; "array[gamma's]" string => "three's"; "array[delta-delta:delta]" string => "four-fore:quatre"; "array[last]" string => "last"; "vals" slist => getvalues("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/getindices_size5_namespaces.cf0000644000175100017510000000271412243421446031440 0ustar00a10038a1003800000000000000####################################################### # # Test getindices() across namespaces, size 5 # ####################################################### body common control { inputs => { "../../../default.cf.sub", "206-namespaced.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "alpha"; "beta"; "gamma's"; "delta-delta:delta"; "last"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "array[beta]" string => "two"; "array[gamma's]" string => "three's"; "array[delta-delta:delta]" string => "four-fore:quatre"; "array[last]" string => "last"; methods: "run" usebundle => testing_arrays:namespaced_test("$(G.testfile).actual", "default:test.array"); } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readrealarray_non_integers.cf0000644000175100017510000000542312243421446031374 0ustar00a10038a1003800000000000000####################################################### # # Test readrealarray(), introduce non-integers (issue 313 and 368) # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999.9::bogus:666.6 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readrealarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999.9][0])", "999.9"), strcmp("$(test.ary[999.9][1])", "0"), strcmp("$(test.ary[999.9][2])", "0"), strcmp("$(test.ary[999.9][3])", "666.6"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999.9][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999.9][0] = '999.9', saw '$(test.ary[999.9][0])'"; "expected test.ary[999.9][1] = '0', saw '$(test.ary[999.9][1])'"; "expected test.ary[999.9][2] = '0', saw '$(test.ary[999.9][2])'"; "expected test.ary[999.9][3] = '666.6', saw '$(test.ary[999.9][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_duplicates_trailing_newlines.cf0000644000175100017510000001216712243421446040232 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, duplicate and trailing newlines # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one "; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)", strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[# A duplicate follows][0])", "# A duplicate follows"), strcmp("$(test.ary[# A duplicate follows][1])", "this line is not always a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/functions_and_nulls.cf0000644000175100017510000000426412243421446030055 0ustar00a10038a1003800000000000000####################################################### # # Test hash() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { vars: # The nulls terminate the string here "test1" string => execresult("$(G.perl) -e 'print \"Test of \0\1\2\n nulls in a string\";'", "noshell"); # Write the same string to a file and read it in again, they are converted "test2" string => execresult("$(G.perl) -e 'print \"Test of \0\1\2\n nulls in a string\";' > $(G.testfile)", "useshell"); "test3" string => readfile("$(G.testfile)","100"); # They are converted here, too, so the split fails "test4a" slist => readstringlist("$(G.testfile)","#no comments", "\0", "2", "100"); # And simply quoting the backslash doesn't work, because I think the # regex is also converted "test4b" slist => readstringlist("$(G.testfile)","#no comments", "\\0", "2", "100"); # So this doubly incorrect split succeeds because of the two conversions "test4c" slist => readstringlist("$(G.testfile)","#no comments", "\\\0", "2", "100"); # readstringarray() (or perhaps getindices) simply breaks "i" int => readstringarray("test5", "$(G.testfile)","#no comments", "no split", "2", "100"); "test5_idx" slist => getindices("test5"); # readstringarrayidx() converts the results (same split issues as test4) "j" int => readstringarrayidx("test6", "$(G.testfile)","#no comments", "no split", "2", "100"); "test6_idx" slist => getindices("test6"); # This shows that the nulls are really there in the file "od_file" string => execresult("$(G.od) -c $(G.testfile)", "noshell"); reports: cfengine_3:: "test1: $(test1)"; "test2: $(test2) (<== we expect nothing here)"; "test3: $(test3)"; "test4a: $(test4a)"; "test4b: $(test4b)"; "test4c: $(test4c)"; "test5, $(i) entries: $(test5[$(test5_idx)])"; "test5_idx: $(test5_idx)"; "test6, $(j) entries: $(test6[$(test6_idx)][0])"; "od_file: $(od_file)"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/maparray.cf0000644000175100017510000000154412411001073025603 0ustar00a10038a1003800000000000000# maparray() test, https://cfengine.com/dev/issues/5452 body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent test { vars: any:: "bundles[services][afs]" slist => { "afs.cf", "bfs.cf" }; "bundles[services][base]" string => "base.cf"; "actual" slist => maparray("services/$(this.k)/$(this.v)", "bundles[services]"); "actual_sorted" slist => sort(actual, "lex"); "actual_str" string => format('%S', actual_sorted); } bundle agent check { methods: "" usebundle => dcs_check_strcmp($(test.actual_str), '{ "services/afs/afs.cf", "services/afs/bfs.cf", "services/base/base.cf" }', $(this.promise_filename), "no"); } parsestringarray_weird_indices_with_duplicate.cf0000644000175100017510000001215712243421446035304 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), add some weird indices (including a duplicate) # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[# A duplicate follows][0])", "# A duplicate follows"), strcmp("$(test.ary[# A duplicate follows][1])", "this line is not always a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } readstringarray_weird_indices_change_comment_parsing.cf0000644000175100017510000001204412243421446036565 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarray(), weird indices, change comment parsing # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[# A duplicate follows][0])", "# A duplicate follows"), strcmp("$(test.ary[# A duplicate follows][1])", "this line is not always a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/execresult_large.cf0000644000175100017510000000264512316547775027363 0ustar00a10038a1003800000000000000####################################################### # # Test execresult() of large files # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { } ####################################################### bundle agent check { vars: "testlengths" ilist => { "1024", "4096", "100000", "500000" }; "result_$(testlengths)" string => execresult("$(G.perl) -e 'my $x = qw/x/ x $(testlengths); print $x;'", "useshell"); "length_$(testlengths)" int => strlen("$(result_$(testlengths))"); classes: "ok_$(testlengths)" expression => strcmp("$(length_$(testlengths))", $(testlengths)); "ok" and => { "ok_1024", "ok_4096", "ok_100000", "ok_500000", }; reports: DEBUG:: "the read of $(testlengths) bytes gave $(length_$(testlengths)) bytes"; "the read of $(testlengths) bytes failed to match the expected $(testlengths) bytes, actual = $(length_$(testlengths))" ifvarclass => "!ok_$(testlengths)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_real_comments3.cf0000644000175100017510000001111012243421446035176 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, real comments # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)","^#.*",":"1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","^#.*",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "this"), strcmp("$(test.ary[6][1])", "also"), strcmp("$(test.ary[7][0])", "last"), strcmp("$(test.ary[7][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = 'this', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = 'also', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'last', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'one', saw '$(test.ary[7][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_real_comments_noemptyfields3.cf0000644000175100017510000001035112243421446040146 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","^#.*",":+",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", "in here"), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "this"), strcmp("$(test.ary[6][1])", "also"), strcmp("$(test.ary[7][0])", "last"), strcmp("$(test.ary[7][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = 'in here', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = 'this', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = 'also', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'last', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'one', saw '$(test.ary[7][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readintarray_non_integers2.cf0000644000175100017510000000535212243421446031326 0ustar00a10038a1003800000000000000####################################################### # # Test readintarray(), introduce non-integers (issue 313 and 368) # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999::bogus:666 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readintarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999][0])", "999"), strcmp("$(test.ary[999][1])", "0"), strcmp("$(test.ary[999][2])", "0"), strcmp("$(test.ary[999][3])", "666"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999][0] = '999', saw '$(test.ary[999][0])'"; "expected test.ary[999][1] = '0', saw '$(test.ary[999][1])'"; "expected test.ary[999][2] = '0', saw '$(test.ary[999][2])'"; "expected test.ary[999][3] = '999', saw '$(test.ary[999][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } bundlesmatching_dynamicbundlesequence.cf0000644000175100017510000000151212243421446033516 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging# Test that bundlesmatching works correctly for dynamic sequences body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)"), @(init.runs) }; } bundle common init { vars: "runs" slist => bundlesmatching("default:run.*"); } bundle agent test { } bundle agent check { classes: "ok" and => { ok1, ok2, ok3 }; reports: DEBUG:: "Found bundles $(test.runs)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } bundle agent run_123_456 { classes: "ok1" expression => "any", scope => "namespace"; } bundle agent run_789_0ab { classes: "ok2" expression => "any", scope => "namespace"; } bundle agent run_cde_fgh { classes: "ok3" expression => "any", scope => "namespace"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/getvalues_size2_with_expansion.cf0000644000175100017510000000324712332665147032247 0ustar00a10038a1003800000000000000####################################################### # # Test getvalues(), size 2 with variable expansion # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "one extra line" "the end$(const.dollar)fini"; "XXX dummy XXX"; "YYY $(init.dummy) YYY"; } ####################################################### bundle agent test { vars: "array[the fini$end]" string => "additional line again"; "array[the end$(const.dollar)fini]" string => "one$(const.n)extra line"; "array[XXX dummy XXX]" string => "XXX dummy XXX"; "array[YYY $(init.dummy) YYY]" string => "YYY $(init.dummy) YYY"; "vals" slist => getvalues("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } parsestringarray_weird_indices_change_comment_parsing2.cf0000644000175100017510000001160512243421446037050 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, change comment parsing # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)","",":"1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","",":",10,1000); "num" int => "9"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), strcmp("$(test.ary[6][0])", "# A duplicate follows"), strcmp("$(test.ary[6][1])", " this line is not always a comment"), strcmp("$(test.ary[7][0])", "this"), strcmp("$(test.ary[7][1])", "also"), strcmp("$(test.ary[8][0])", "last"), strcmp("$(test.ary[8][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = '# A duplicate follows', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ' this line is not always a comment', saw '$(test.ary[6][1])'"; "expected test.ary[7][0] = 'this', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 'also', saw '$(test.ary[7][1])'"; "expected test.ary[8][0] = 'last', saw '$(test.ary[8][0])'"; "expected test.ary[8][1] = 'one', saw '$(test.ary[8][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarrayidx_change_separator_to_s.cf0000644000175100017510000000730012243421446034437 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarrayidx(), change separator to 's' # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)","^#.*",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","^#.*","s+",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0:1:2"), strcmp("$(test.ary[1][0])", "1:2:3"), strcmp("$(test.ary[2][0])", "here i"), strcmp("$(test.ary[2][1])", ":a line: with "), strcmp("$(test.ary[2][2])", "pace"), strcmp("$(test.ary[2][3])", " : in it"), strcmp("$(test.ary[3][0])", "blank:field"), strcmp("$(test.ary[3][1])", ":::in here::"), strcmp("$(test.ary[4][0])", ":leading blank field"), strcmp("$(test.ary[5][0])", "thi"), strcmp("$(test.ary[5][1])", ":i"), strcmp("$(test.ary[5][2])", ":a:te"), strcmp("$(test.ary[5][3])", "t"), strcmp("$(test.ary[6][0])", "thi"), strcmp("$(test.ary[6][1])", ":al"), strcmp("$(test.ary[6][2])", "o"), strcmp("$(test.ary[7][0])", "la"), strcmp("$(test.ary[7][1])", "t:one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0:1:2', saw '$(test.ary[0][0])'"; "expected test.ary[1][0] = '1:2:3', saw '$(test.ary[1][0])'"; "expected test.ary[2][0] = 'here i', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = ':a line: with ', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = 'pace', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' : in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank:field', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = ':::in here::', saw '$(test.ary[3][1])'"; "expected test.ary[4][0] = ':leading blank field', saw '$(test.ary[4][0])'"; "expected test.ary[5][0] = 'thi', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = ':i', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = ':a:te', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 't', saw '$(test.ary[5][3])'"; "expected test.ary[6][0] = 'thi', saw '$(test.ary[6][0])'"; "expected test.ary[6][1] = ':al', saw '$(test.ary[6][1])'"; "expected test.ary[6][2] = 'o', saw '$(test.ary[6][2])'"; "expected test.ary[7][0] = 'la', saw '$(test.ary[7][0])'"; "expected test.ary[7][1] = 't:one', saw '$(test.ary[7][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarrayidx_weird_indices_real_comments_noemptyfields.cf0000644000175100017510000000510512243421446040571 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarrayidx(), add some weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)","^#.*",":+"14); "cnt" int => parsestringarrayidx("ary", "$(teststr)","^#.*",":+",10,14); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "bad" or => { isvariable("test.ary[2][1]"), isvariable("test.ary[3][0]"), }; "ok" and => { "!bad", strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "he"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "saw 'bad'-class things"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'he', saw '$(test.ary[2][0])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readstringlist.cf0000644000175100017510000000301512243421446027035 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123, ,456,789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/readstringlist2.cf0000644000175100017510000000302612243421446027121 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123,broken,456,789"; # non-numeric fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } readstringarray_weird_indices_trailing_newlines.cf0000644000175100017510000001207112243421446035610 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarray(), weird indices, duplicate and trailing newlines # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one "; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","NoComment",":",10,1000); "num" int => "8"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", ""), strcmp("$(test.ary[blank][3])", ""), strcmp("$(test.ary[blank][4])", "in here"), strcmp("$(test.ary[blank][5])", ""), strcmp("$(test.ary[blank][6])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[# A duplicate follows][0])", "# A duplicate follows"), strcmp("$(test.ary[# A duplicate follows][1])", "this line is not always a comment"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = '', saw '$(test.ary[blank][2])'"; "expected test.ary[blank][3] = '', saw '$(test.ary[blank][3])'"; "expected test.ary[blank][4] = 'in here', saw '$(test.ary[blank][4])'"; "expected test.ary[blank][5] = '', saw '$(test.ary[blank][5])'"; "expected test.ary[blank][6] = '', saw '$(test.ary[blank][6])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_weird_indices_real_comments.cf0000644000175100017510000001165312243421446035127 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), weird indices, real comments # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","^#.*",":",10,1000); "num" int => "7"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][0])", "fields"), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[blank][0])", "in here"), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[blank][0])", ""), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = 'fields', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = 'in here', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][0] = '', saw '$(test.ary[blank][0])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } readstringarray_weird_indices_real_comments_noemptyfields.cf0000644000175100017510000001067412243421446037674 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test readstringarray(), weird indices, real comments, no empty fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarray("ary", "$(G.testfile)","^#.*",":+",10,1000); "num" int => "7"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "ok" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[here is][0])", "here is"), strcmp("$(test.ary[here is][1])", "a line"), strcmp("$(test.ary[here is][2])", " with spaces "), strcmp("$(test.ary[here is][3])", " in it"), strcmp("$(test.ary[blank][0])", "blank"), strcmp("$(test.ary[blank][1])", "fields"), strcmp("$(test.ary[blank][2])", "in here"), strcmp("$(test.ary[][0])", ""), strcmp("$(test.ary[][1])", "leading blank field"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "also"), strcmp("$(test.ary[this][2])", "$(const.dollar)test.ary[this][2]"), strcmp("$(test.ary[this][3])", "$(const.dollar)test.ary[this][3]"), strcmp("$(test.ary[last][0])", "last"), strcmp("$(test.ary[last][1])", "one"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[here is][0] = 'here is', saw '$(test.ary[here is][0])'"; "expected test.ary[here is][1] = 'a line', saw '$(test.ary[here is][1])'"; "expected test.ary[here is][2] = ' with spaces ', saw '$(test.ary[here is][2])'"; "expected test.ary[here is][3] = ' in it', saw '$(test.ary[here is][3])'"; "expected test.ary[blank][0] = 'blank', saw '$(test.ary[blank][0])'"; "expected test.ary[blank][1] = 'fields', saw '$(test.ary[blank][1])'"; "expected test.ary[blank][2] = 'in here', saw '$(test.ary[blank][2])'"; "expected test.ary[][0] = '', saw '$(test.ary[][0])'"; "expected test.ary[][1] = 'leading blank field', saw '$(test.ary[][1])'"; "expected test.ary[# A duplicate follows][0] = '# A duplicate follows', saw '$(test.ary[# A duplicate follows][0])'"; "expected test.ary[# A duplicate follows][1] = 'this line is not always a comment', saw '$(test.ary[# A duplicate follows][1])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'also', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = '$(const.dollar)test.ary[this][2]', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = '$(const.dollar)test.ary[this][3]', saw '$(test.ary[this][3])'"; "expected test.ary[last][0] = 'last', saw '$(test.ary[last][0])'"; "expected test.ary[last][1] = 'one', saw '$(test.ary[last][1])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_introduce_nonparsed_comment.cf0000644000175100017510000000643712243421446035202 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), introduce a non-parsed comment # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "g", default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 # Not parsed as a comment this:is:a:test 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parsestringarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "4"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[this][0])", "this"), strcmp("$(test.ary[this][1])", "is"), strcmp("$(test.ary[this][2])", "a"), strcmp("$(test.ary[this][3])", "test"), strcmp("$(test.ary[# Not parsed as a comment][0])", "# Not parsed as a comment"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[# Not parsed as a comment][1]"), isvariable("test.ary[this][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[# Not parsed as a comment][0] = '# Not parsed as a comment', saw 'expected $(test.ary[# Not parsed as a comment][0])'"; "expected test.ary[this][0] = 'this', saw '$(test.ary[this][0])'"; "expected test.ary[this][1] = 'is', saw '$(test.ary[this][1])'"; "expected test.ary[this][2] = 'a', saw '$(test.ary[this][2])'"; "expected test.ary[this][3] = 'test', saw '$(test.ary[this][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarray_dontread_comment_duplicate_lastline3.cf0000644000175100017510000001064112243421446036735 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarray(), don't read comment, duplicate key or last line # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",6,1000); "num" int => "6"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "bad" or => { isvariable("test.ary[6][0]"), isvariable("test.ary[6][1]"), isvariable("test.ary[7][0]"), isvariable("test.ary[7][1]"), isvariable("test.ary[8][0]"), isvariable("test.ary[8][1]"), }; "ok" and => { "!bad", strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } parsestringarrayinx_singleton_nootherfields.cf0000644000175100017510000000476712243421446035065 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging####################################################### # # Test parsestringarrayidx(), introduce a singleton with no other fields # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 singleton 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" str => readfile("$(G.testfile)",1000); "cnt" int => parsestringarrayidx("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "singleton"), strcmp("$(test.ary[2][0])", "1"), strcmp("$(test.ary[2][1])", "2"), strcmp("$(test.ary[2][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[1][1]"), isvariable("test.ary[2][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = 'singleton', saw '$(test.ary[1][0])'"; "expected test.ary[2][0] = '1', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = '2', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = '3', saw '$(test.ary[2][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/staging/getindices_size5_namespaces.cf.sub0000644000175100017510000000076612236160673032241 0ustar00a10038a1003800000000000000body file control { namespace => "testing_arrays"; } bundle agent namespaced_test(file, arrayname) { vars: "keys" slist => getindices("$(arrayname)"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Working in namespace; array name $(arrayname)"; "Inserting line: $(keys)"; } bundle edit_line test_insert { vars: "keys" slist => { @{namespaced_test.keys} }; insert_lines: "$(keys)"; } variable_references_from_function_that_never_succeeds.cf.sub0000644000175100017510000000112212316547775036103 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions####################################################### # # Subtest that FnFailure results in unresolved references # ####################################################### body common control { bundlesequence => { test }; } bundle agent test { vars: "unresolved_76201d0eaac49a884308358aa487147b4db70e8a" slist => { canonify($(missing)) }; "resolved_a557d39e04d666075754b8f78ea17fbc175925d5" slist => { "a", "b" }; reports: "MARKER$(unresolved_76201d0eaac49a884308358aa487147b4db70e8a)MARKER MARKER$(resolved_a557d39e04d666075754b8f78ea17fbc175925d5)MARKER"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/041.cf0000644000175100017510000000256212243421446022655 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok" and => { "ok_list", "ok123", islessthan("$(test.sum)", "123.457"), isgreaterthan("$(test.sum)", "123.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/061.x.cf0000644000175100017510000000171012243421446023117 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,1000,1000,1001,1000,40000); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/long_string_from_text_file.cf0000644000175100017510000000651012332665147027770 0ustar00a10038a1003800000000000000####################################################### # # Test that we dont crash when reading in large strings from a file # Redmine:3957 (https://cfengine.com/dev/issues/3957) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).data" create => "true", edit_defaults => empty, edit_line => seed_data; } ####################################################### bundle agent test { vars: "keyfile" string => "$(G.testfile).data"; "keys" slist => readstringlist("$(keyfile)", "#[^\n]*", "\n", 10, 3072); } ####################################################### bundle agent check { classes: "ok" expression => "any", comment => "If we made it to here, we didnt crash"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } bundle edit_line seed_data { insert_lines: "ssh-dss YavBsyK3sHDac4Gj4nDbVH9E7OfRPi16DADNOWGKEjWiBB0cCe0UY6xxEgcYuwOOl8HUGqqzLOByvUbo1hENDQldKFt8N7WIb2E9gXFtGm0Sf0NlYARALj1nhLju9hodpGxkr4vKioW1fZQBmBqsI7Ky8ZhzU5p4CAm4uCbxAZuiIhDTAcxj7RlDy3fe9WBw7v0cSIbu8E3zEbPn0VQjTduLCJtFOb5LvUxpxUsHMhHu0xS8DvXIwf7l83cQ0XZtwyIgbF3ZxjIZaPyYhKZRAV1qCze4BlcOerJeVYOiKjpXJlOoBprxy2SfEYVS4Khun0efkmsmBAfllKUUNCqsK9j6oWo7BvNbXqzkl2ULJd6h0LNy9jW8IXnnrfWknLGa7lksVmL3afSAufDAb7yRESaUP5KmcD3ghP3Nvu7fy9hz7nIAPgj2dQOwnFRbkv9Svoi9YmCtvBWYAcwIUVNJBmwXe5j5xJyt5vOyRSI2ooJ9mk69UOCsIM8PEnEXwtHcsg9fDjfu9ChFY2HWZPWeNXH05SATnSyLgclQsZcazhQXPoxZbcqR80mfuRX9ymEzNwZJ1jJUERnj9PZkSInu6mFVRjTaQjg8yvqMGRxWknP8aURCDh5rr4Na23jULVVI66heWOi7nzLqBg5U8GsbLsocM8zBam8bhXfU0KvpBo5wlUtHnDWHoMlS3ktr25ldrp3zLuywhHe5vGUbg2E0gr4xB3oPAyaDa3MGQiVXPfngu5CJhwIXmeN5JtIBA0S46ihg7lQ6IU8kAaRHwhWh3TokoNFOYE8R5i24gpYNF8dgCRGqSZIT5V7wuR3qG1Wau963ILuX8EFOSu7xDc5qnGTem3FwICTpSdnZNqpzRt4Ipqsn4Pa2tFFpHlzDwKFRPS7r8v4QX7acqdTSCUOuZ68GwDRlvHIz5mHUf1XLY3FH2InuWFsonJAZwmEbX5evWXFgyJHFlplQcGJvyNdL0T6oBmbG3ssSMoRnqnsk8XjGWtUyvYoQmOY8HWlMhf4V3v78C4k4TnCbN4LmnDYaDcnXMejrUMYDk6QwW3fdTF5ZyjJMy4ANu2fJfKysZMc1Cc== root@host1"; "ssh-dss a58AZSxQlmcq33EBCW1GuhpkYCgUfr7o5A1arQZ2dr8I4kldCF76mpl6o2CFthZs4YUU8LewbIDDPqjhS2WwafTXeMEvPMtmLufk6E5njNy2WQtAnmGc9R21qIteTgikY9ubRCM3hlhzJ1wGSKCsE5oBHDQC0thk1ljJGHzsEl0AuVClkUq3yz4eWAsiRdbD9QY7ddD6zA61aHomuczKU5F0VvyO8gRQmWV7b6lysoUFcMgCPVf3UaDdg7L7vvBVkQN2vGCh9CCJz5OkBShlZVNaAXd5TkKJNmsTuBDscPyxeCBAk8sai69f1NNtTeAyWTtSu1KiqTDvD9aal93MhpZnPdOZzNr7etK4C7HuPD0uFjdvKZy1H55rpwNHnJ4GojqiNG1VvN5bGLa3sSLiKOngtMBCokdtHpZn2eHD7oLUROTIG3ZXqFGGvfKEP5zlpvJz3392n4PDQ7EKuNFPhyNQpVXEIAQEDcmeWMopVTGezLoFJG01hKMPxs5QWF7qetVLi1pCjmlUpqgE8c81WGxvMe7ooMtQbeVNulX3qBC3rZhYKtk0R5AA8JxmxHSLYlLFbtnR1PA97hnRvnvlfk92i7WL1hjJsMl29LOrubi554Dr9N2uVUrCFcPZMK45PY0TiRH82AKFmkM8mbM0rndJxoJobZsqRAGHVIkcS53hxMT69liRxlCyubwcxgDaqmeQnJU2Ug0YyFs1uxt4NT9laJ0CO2IxhkbmGeDGw1FJqKyc8Haov263cFMcB97I3gyNHccsAynQnxpMS1ltTFXalghuochdue4unbq0Ty2PfS4jPMkavBlMYN8UZdnyZHuUhycwBJri1Grv5kf2SP00P6NQhuB8kwjqoTG8ay5fKWvhDrVetd7tPuj4dMouHuDeaLJInc7Cz0S5tQOuMfRhpPqk1E8A0YnuNCyPDNuW75rkXZkxP9cYSVWeDa1wgOyNLZDTzYts82qiu9kxLbZ184jowJ8rru4UB20JRtoehnD2nGU1NfegD1qOBgQHtDuB18xggfvOgvUNXBrQpICSz0JqszpftAgV5TJq1FjOdjUo1kOCFuqqi6C4S0Siho== root@host2"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/520.cf0000644000175100017510000000541012243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test parseintarray(), simple # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readintarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999:888:777:666 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parseintarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999][0])", "999"), strcmp("$(test.ary[999][1])", "888"), strcmp("$(test.ary[999][2])", "777"), strcmp("$(test.ary[999][3])", "666"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999][0] = '999', saw '$(test.ary[999][0])'"; "expected test.ary[999][1] = '888', saw '$(test.ary[999][1])'"; "expected test.ary[999][2] = '777', saw '$(test.ary[999][2])'"; "expected test.ary[999][3] = '999', saw '$(test.ary[999][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/regextract.cf0000644000175100017510000000277212316547775024543 0ustar00a10038a1003800000000000000####################################################### # # Test regextract # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "text" string => "node-01-10.0"; classes: "parsed_text" expression => regextract("^\w+-(\d+)-(\d+\.\d+)", "$(text)", "pair"); reports: DEBUG.!parsed_text:: "Failed to parse $(text)"; } ####################################################### bundle agent test { vars: "lefts" string => "$(init.pair[1])"; "lefti" int => "$(init.pair[1])"; "rights" string => "$(init.pair[2])"; "rightr" real => "$(init.pair[2])"; } ####################################################### bundle agent check { classes: "sok" expression => strcmp("$(test.lefts):$(test.rights)", "01:10.0"); "iok" expression => strcmp("$(test.lefti)", "1"); "rok" expression => strcmp("$(test.rightr)", "10.000000"); "ok" and => { "sok", "iok", "rok" }; reports: DEBUG.!iok:: "Parsed integer '$(test.lefti)' isn't 1"; DEBUG.!rok:: "Parsed real '$(test.rightr)' isn't 10.000000"; DEBUG.!sok:: "Parsed numbers '$(test.lefts)' and '$(test.rights)' aren't '01' and '10.0'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/202.cf0000644000175100017510000000245612243421446022656 0ustar00a10038a1003800000000000000####################################################### # # Test getindices(), size 1 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "alpha"; } ####################################################### bundle agent test { vars: "array[alpha]" string => "zero"; "keys" slist => getindices("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(keys)"; } bundle edit_line test_insert { vars: "keys" slist => { @{test.keys} }; insert_lines: "$(keys)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/join_mapped_list.cf0000644000175100017510000000172112243421446025665 0ustar00a10038a1003800000000000000####################################################### # # Redmine #2614: join should iterate over all elements of a mapped list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "elements" slist => { "a", "b", "c" }; "expected" string => "a_x:b_x:c_x"; } ####################################################### bundle agent test { vars: "map" slist => maplist("$(this)_x", "init.elements"); "join" string => join(":","map"); } ####################################################### bundle agent check { classes: "ok" expression => strcmp($(init.expected), $(test.join)); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/223.cf0000644000175100017510000000256112332665147022665 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 2 local array # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "Two"; "Three"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep("T.*", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } parsestringarray_dontread_comment_duplicate_lastline2.cf0000644000175100017510000001055412332665147035312 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/02_functions####################################################### # # Test parsestringarray(), don't read comment, duplicate key or last line # # The 4xx tests are all related, and 400-419 are the readstringarray tests, # 420-439 the same for readstringarrayidx, 440-459 parsestringarray, and # 460-479 parsestringarrayidx # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 1:2:3 here is:a line: with spaces : in it blank:fields:::in here:: :leading blank field this:is:a:test # A duplicate follows: this line is not always a comment this:also last:one"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "cnt" int => readstringarrayidx("ary", "$(G.testfile)","NoComment",":",6,1000); "num" int => "6"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "bad" or => { isvariable("test.ary[6][0]"), isvariable("test.ary[6][1]"), isvariable("test.ary[7][0]"), isvariable("test.ary[7][1]"), isvariable("test.ary[8][0]"), isvariable("test.ary[8][1]"), }; "ok" and => { "!bad", strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), strcmp("$(test.ary[2][0])", "here is"), strcmp("$(test.ary[2][1])", "a line"), strcmp("$(test.ary[2][2])", " with spaces "), strcmp("$(test.ary[2][3])", " in it"), strcmp("$(test.ary[3][0])", "blank"), strcmp("$(test.ary[3][1])", "fields"), strcmp("$(test.ary[3][2])", ""), strcmp("$(test.ary[3][3])", ""), strcmp("$(test.ary[3][4])", "in here"), strcmp("$(test.ary[3][5])", ""), strcmp("$(test.ary[3][6])", ""), strcmp("$(test.ary[4][0])", ""), strcmp("$(test.ary[4][1])", "leading blank field"), strcmp("$(test.ary[5][0])", "this"), strcmp("$(test.ary[5][1])", "is"), strcmp("$(test.ary[5][2])", "a"), strcmp("$(test.ary[5][3])", "test"), }; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; "expected test.ary[2][0] = 'here is', saw '$(test.ary[2][0])'"; "expected test.ary[2][1] = 'a line', saw '$(test.ary[2][1])'"; "expected test.ary[2][2] = ' with spaces ', saw '$(test.ary[2][2])'"; "expected test.ary[2][3] = ' in it', saw '$(test.ary[2][3])'"; "expected test.ary[3][0] = 'blank', saw '$(test.ary[3][0])'"; "expected test.ary[3][1] = 'fields', saw '$(test.ary[3][1])'"; "expected test.ary[3][2] = '', saw '$(test.ary[3][2])'"; "expected test.ary[3][3] = '', saw '$(test.ary[3][3])'"; "expected test.ary[3][4] = 'in here', saw '$(test.ary[3][4])'"; "expected test.ary[3][5] = '', saw '$(test.ary[3][5])'"; "expected test.ary[3][6] = '', saw '$(test.ary[3][6])'"; "expected test.ary[4][0] = '', saw '$(test.ary[4][0])'"; "expected test.ary[4][1] = 'leading blank field', saw '$(test.ary[4][1])'"; "expected test.ary[5][0] = 'this', saw '$(test.ary[5][0])'"; "expected test.ary[5][1] = 'is', saw '$(test.ary[5][1])'"; "expected test.ary[5][2] = 'a', saw '$(test.ary[5][2])'"; "expected test.ary[5][3] = 'test', saw '$(test.ary[5][3])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/080.cf0000644000175100017510000000274612316547775022703 0ustar00a10038a1003800000000000000####################################################### # # Test getuid() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: # NOTE: We need to make this test work on Windows by finding a good # registry value to use (and we always expect it to fail on non-Windows # # Always execute this - the return value depends on the OS used, but # we always expect registryvalue() to not crash "regval" string => registryvalue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Currentversion", "ProgramFilesDir"); } ####################################################### bundle agent check { classes: windows:: "ok" and => { strcmp("$(test.regval)", "C:\Program Files"), }; !windows:: "ok" not => isvariable("test.regval"); reports: DEBUG:: "Registry value is $(test.regval)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/021.cf0000644000175100017510000000314012243421446022644 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123,,,456,789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/001.cf0000644000175100017510000000406212316547775022665 0ustar00a10038a1003800000000000000####################################################### # # Test getuid() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_needs_work" string => "windows"; vars: any:: "uid_root" int => getuid("root"); "uid_daemon" int => getuid("daemon"); !darwin:: "uid_bin" int => getuid("bin"); (linux.!archlinux.!SuSE.!redhat.!gentoo)|solaris|hpux|aix:: "num_root" int => "0"; "num_daemon" int => "1"; "num_bin" int => "2"; archlinux|SuSE|redhat|gentoo:: "num_root" int => "0"; "num_daemon" int => "2"; "num_bin" int => "1"; freebsd|openbsd:: "num_root" int => "0"; "num_daemon" int => "1"; "num_bin" int => "3"; darwin:: "num_root" int => "0"; "num_daemon" int => "1"; !linux.!solaris.!hpux.!aix.!freebsd.!openbsd.!darwin:: "num_root" string => "fixme"; "num_daemon" string => "fixme"; "num_bin" string => "fixme"; } ####################################################### bundle agent check { classes: darwin:: "ok_bin" expression => "any"; !darwin:: "ok_bin" expression => strcmp("$(test.uid_bin)", "$(test.num_bin)"); any:: "ok" and => { strcmp("$(test.uid_root)", "$(test.num_root)"), strcmp("$(test.uid_daemon)", "$(test.num_daemon)"), "ok_bin" }; reports: DEBUG:: "root is UID $(test.uid_root), expected $(test.num_root)"; "daemon is UID $(test.uid_daemon), expected $(test.num_daemon)"; "bin is UID $(test.uid_bin), expected $(test.num_bin)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/066.cf0000644000175100017510000000275412316547775022706 0ustar00a10038a1003800000000000000####################################################### # # Test getusers(), arg0 only # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: # All users except root, bin, and daemon "users" slist => getusers("root,daemon,bin",""); files: "$(G.testfile)" delete => init_delete; reports: cfengine_3:: "$(users)" report_to_file => "$(G.testfile)"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: # Try to delete the lines that shouldn't be there anyway "$(G.testfile)" edit_line => test_delete, classes => full_set; } bundle edit_line test_delete { delete_lines: "root"; "daemon"; "bin"; } body classes full_set { promise_kept => { "pass" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { classes: "ok" expression => "pass&!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/data_readstringarray.cf0000644000175100017510000000273312316547775026562 0ustar00a10038a1003800000000000000# Redmine#2926: test long lines with readstringarrayidx() body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "params" data => data_readstringarray("$(this.promise_filename).txt", "\s*#[^\n]*", ";", 9999, 99999); "params_str" string => format("%S", params); "pk" slist => getindices(params); reports: DEBUG:: "params: $(params_str)"; } bundle agent check { vars: "dim" int => length("test.params"); "length" int => length("test.pk"); "last" string => nth("test.value", 599); classes: "ok1" expression => strcmp($(dim), "3"); "ok2" expression => strcmp($(dim), $(length)); "ok3" expression => strcmp("$(test.params[not_working_app_config][0])", "9123"); "ok" and => { "ok1", "ok2", "ok3" }; reports: DEBUG.ok1:: "passed1"; DEBUG.ok2:: "passed2"; DEBUG.ok3:: "passed3"; DEBUG.!ok1:: "failed1 $(dim) != 3"; DEBUG.!ok2:: "failed2 $(dim) != $(length)"; DEBUG.!ok3:: "failed3 $(test.params[not_working_app_config][0]) != 9123"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/packagesmatching.cf0000644000175100017510000000713512400110676025636 0ustar00a10038a1003800000000000000####################################################### # # Test packagesmatching() and that the env prefix is stripped # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { packages: "cfe-no-such-package" package_policy => "add", package_method => mock1; "cfe-no-such-package" package_policy => "add", package_method => mock2; # the parsing of env X="y z" fails # "cfe-no-such-package" # package_policy => "add", # package_method => mock3; "cfe-no-such-package" package_policy => "add", package_method => mock4; } body package_method mock1 { package_changes => "individual"; package_list_command => "$(G.printf) 'bfoobar-1-besm6'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock2 { package_changes => "individual"; package_list_command => "/usr/bin/env $(G.printf) 'bfoobar-1-besm6'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock3 { package_changes => "individual"; package_list_command => '/usr/bin/env X="y z" $(G.printf) "bfoobar-1-besm6"'; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock4 { package_changes => "individual"; package_list_command => "/usr/bin/env X=Y $(G.printf) 'bfoobar-1-besm6'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4741" }; vars: "all_packages" data => packagesmatching(".*", ".*", ".*", ".*"); "all_string" string => format("packages = %S", all_packages); } ####################################################### bundle agent check { vars: "e" string => '{"name":"bfoobar","version":"1","arch":"besm6","method":"printf"}'; methods: "" usebundle => dcs_check_strcmp($(test.all_string), 'packages = [$(e)]', $(this.promise_filename), "no"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/019.cf0000644000175100017510000000270012243421446022654 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123.456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","X",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123.456", "$(nums)"); "ok" and => { "ok_list", "ok123", islessthan("$(test.sum)", "123.457"), isgreaterthan("$(test.sum)", "123.455") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/split.cf0000644000175100017510000000241412332665147023507 0ustar00a10038a1003800000000000000####################################################### # # Test string_split() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ############################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "expected" string => "one two:three"; files: "$(G.testfile).expected" create => "true", edit_line => ensure_lines("$(init.expected)"), edit_defaults => empty; } ####################################################### bundle agent test { vars: "result" slist => string_split("one:two:three", ":", "2"); files: "$(G.testfile).actual" create => "true", edit_defaults => empty, edit_line => ensure_lines(@(result)); } ####################################################### bundle edit_line ensure_lines(list) { insert_lines: "$(list)"; } bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/620.cf0000644000175100017510000000546112243421446022661 0ustar00a10038a1003800000000000000####################################################### # # Test parserealarray(), simple # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 999.9:888:777:666.6 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parserealarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[999.9][0])", "999.9"), strcmp("$(test.ary[999.9][1])", "888"), strcmp("$(test.ary[999.9][2])", "777"), strcmp("$(test.ary[999.9][3])", "666.6"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[999.9][4]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[999.9][0] = '999.9', saw '$(test.ary[999.9][0])'"; "expected test.ary[999.9][1] = '888', saw '$(test.ary[999.9][1])'"; "expected test.ary[999.9][2] = '777', saw '$(test.ary[999.9][2])'"; "expected test.ary[999.9][3] = '999.9', saw '$(test.ary[999.9][3])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/readtcp_connection_fail.cf0000644000175100017510000000150112316547775027214 0ustar00a10038a1003800000000000000# Test that failure to connect to remote host does not result in "Could not # close socket" error messages. body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "useshell"); } bundle agent check { classes: "ok_output" not => regcmp(".*Bad file descriptor.*", "$(test.subout)"); "ok_no_crash" expression => isvariable("test.subout"); "ok" and => { "ok_output", "ok_no_crash" }; reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/filter.cf0000644000175100017510000001512012316547775023647 0ustar00a10038a1003800000000000000####################################################### # # Test filter() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "results" slist => { 'This filtering of d1 should have only exact "." entries: { --empty-list-- }', 'This filtering of d1 should have only one-character entries: { "1", "2", "3" }', 'This filtering of d2 should have only exact "." entries: { --empty-list-- }', 'This filtering of d2 should have only one-character entries: { "1", "2", "3", "y", "b", "q" }', 'This filtering of dempty should have only exact "." entries: { --empty-list-- }', 'This filtering of dempty should have only one-character entries: { --empty-list-- }', 'This filtering of s1 should have only exact "." entries: { --empty-list-- }', 'This filtering of s1 should have only one-character entries: { "1", "2", "3" }', 'filter-bound d1, matching at most 2 items = { "1", "2" }', 'filter-bound d2, matching at most 2 items = { "1", "2" }', 'filter-bound dempty, matching at most 2 items = { --empty-list-- }', 'filter-bound s1, matching at most 2 items = { "1", "2" }', 'filter-exact d1, looking for "one" = { "one", "one" }', 'filter-exact d2, looking for "one" = { --empty-list-- }', 'filter-exact dempty, looking for "one" = { --empty-list-- }', 'filter-exact s1, looking for "one" = { "one", "one" }', 'filter-grep09 d1 = { "1", "2", "3" }', 'filter-grep09 d2 = { "1", "2", "3" }', 'filter-grep09 dempty = { --empty-list-- }', 'filter-grep09 s1 = { "1", "2", "3" }', 'filter-invert d1, looking for non-digits = { "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three" }', 'filter-invert d2, looking for non-digits = { "y", "b", "q" }', 'filter-invert dempty, looking for non-digits = { --empty-list-- }', 'filter-invert s1, looking for non-digits = { "one", "two", "three", "long string", "one", "two", "three" }', 'grep09 d1 = { "1", "2", "3" }', 'grep09 d2 = { "1", "2", "3" }', 'grep09 dempty = { --empty-list-- }', 'grep09 s1 = { "1", "2", "3" }', 'max0 filtering of d1 should be empty: { --empty-list-- }', 'max0 filtering of d2 should be empty: { --empty-list-- }', 'max0 filtering of dempty should be empty: { --empty-list-- }', 'max0 filtering of s1 should be empty: { --empty-list-- }', 'starting d1 = [1,2,3,"one","two","three","long string","four","fix","six","one","two","three"]', 'starting d2 = {"one":1,"two":2,"three":3,"x":"y","a":"b","p":"q"}', 'starting dempty = []', 'starting s1 = { "1", "2", "3", "one", "two", "three", "long string", "one", "two", "three" }' }; files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_insert; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert { insert_lines: "$(init.results)"; } ####################################################### bundle agent test { vars: "tests" slist => { "fgrep09", "exact1", "exactdot", "regexdot", "invert", "max2", "max0", "grep09" }; "lists" slist => { "s1", "d1", "d2", "dempty" }; "s1" slist => { 1,2,3, "one", "two", "three", "long string", "one", "two", "three", }; "d1" data => parsejson(' [1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three"]'); "d2" data => parsejson(' { "one": 1, "two": 2, "three": 3, "x": "y", "a": "b", "p": "q" }'); "dempty" data => parsejson('[]'); "$(lists)_fgrep09" slist => filter("[0-9]", $(lists), "true", "false", 999); "$(lists)_exact1" slist => filter("one", $(lists), "false", "false", 999); "$(lists)_exactdot" slist => filter(".", $(lists), "false", "false", 999); "$(lists)_regexdot" slist => filter(".", $(lists), "true", "false", 999); "$(lists)_invert" slist => filter("[0-9]", $(lists), "true", "true", 999); "$(lists)_max2" slist => filter(".*", $(lists), "true", "false", 2); "$(lists)_max0" slist => filter(".*", $(lists), "true", "false", 0); "$(lists)_grep09" slist => grep("[0-9]", $(lists)); "$(lists)_str" string => format("%S", "$(lists)"); "$(lists)_$(tests)_str" string => format("%S", "$(lists)_$(tests)"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { vars: "lists" slist => { @(test.lists) }; insert_lines: "starting $(lists) = $(test.$(lists)_str)"; "grep09 $(lists) = $(test.$(lists)_grep09_str)"; "filter-grep09 $(lists) = $(test.$(lists)_fgrep09_str)"; "filter-exact $(lists), looking for \"one\" = $(test.$(lists)_exact1_str)"; "This filtering of $(lists) should have only exact \".\" entries: $(test.$(lists)_exactdot_str)"; "This filtering of $(lists) should have only one-character entries: $(test.$(lists)_regexdot_str)"; "filter-invert $(lists), looking for non-digits = $(test.$(lists)_invert_str)"; "filter-bound $(lists), matching at most 2 items = $(test.$(lists)_max2_str)"; "max0 filtering of $(lists) should be empty: $(test.$(lists)_max0_str)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/039.cf0000644000175100017510000000265112243421446022663 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/classesmatching.cf0000644000175100017510000000256712316547775025545 0ustar00a10038a1003800000000000000# Test that classesmatching works correctly body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common init { classes: "test_fbeae67f3e347b5e0032302200141131" expression => "any", meta => { "x" }; "test_fbeae67f3e347b5e0032302200141131_1" expression => "any", meta => { "x" }; "test_fbeae67f3e347b5e0032302200141131_2" expression => "any", meta => { "y" }; } bundle agent test { vars: "classes" slist => classesmatching("test_fbeae67f3e347b5e0032302200141131.*"); "x_classes" slist => classesmatching("test_fbeae67f3e347b5e0032302200141131.*", "x"); "z_classes" slist => classesmatching("test_fbeae67f3e347b5e0032302200141131.*", "z"); "count" int => length(classes); "x_count" int => length(x_classes); "z_count" int => length(z_classes); } bundle agent check { classes: "ok" and => { strcmp("$(test.count)", "3"), strcmp("$(test.x_count)", "2"), strcmp("$(test.z_count)", "0") }; reports: DEBUG:: "Found classes $(test.classes), length $(test.count)"; "Found x classes $(test.x_classes), length $(test.x_count)"; "Found z classes $(test.z_classes), length $(test.z_count)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/read_empty_file.cf0000644000175100017510000000207212243421446025475 0ustar00a10038a1003800000000000000# Test that empty file is succesfully read by readfile() function body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" create => "true"; } bundle agent test { vars: "value1" string => readfile("$(G.testfile)", 10000); "value2" string => readfile("$(G.testfile)", 0); } bundle agent check { classes: "ok1" expression => strcmp("$(test.value1)", ""); "ok2" expression => strcmp("$(test.value2)", ""); "not_ok1" not => strcmp("$(test.value1)", ""); "not_ok2" not => strcmp("$(test.value2)", ""); "ok" and => { "ok1", "ok2" }; reports: DEBUG.ok1:: "passed1: '$(test.value1)' == ''"; DEBUG.ok2:: "passed2: '$(test.value1)' == ''"; DEBUG.not_ok1:: "failed1: '$(test.value1)' != ''"; DEBUG.not_ok2:: "failed2: '$(test.value2)' != ''"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/221.cf0000644000175100017510000000216312243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test grep(), size 0, local slist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true"; } ####################################################### bundle agent test { vars: "array" slist => { "One", "Two", "Three", "Four", "Five" }; "vals" slist => grep("Z.*", "array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(vals)"; } bundle edit_line test_insert { vars: "vals" slist => { @{test.vals} }; insert_lines: "$(vals)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/621.cf0000644000175100017510000000472312243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test parserealarray(), introduce 777 12345 with no other fields # # The 5xx tests look at the same thing as their corresponding 4xx tests # 500-519 are readrealarray, 520-539 test the same things for parseintarray # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "0:1:2 12345 1:2:3"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "teststr" string => readfile("$(G.testfile)",1000); "cnt" int => parserealarray("ary", "$(teststr)","NoComment",":",10,1000); "num" int => "3"; } ####################################################### bundle agent check { vars: "idx" slist => getindices("test.ary"); classes: "good" and => { strcmp("$(test.num)", "$(test.cnt)"), strcmp("$(test.ary[0][0])", "0"), strcmp("$(test.ary[0][1])", "1"), strcmp("$(test.ary[0][2])", "2"), strcmp("$(test.ary[12345][0])", "12345"), strcmp("$(test.ary[1][0])", "1"), strcmp("$(test.ary[1][1])", "2"), strcmp("$(test.ary[1][2])", "3"), }; # Make sure there are no trailing elements "bad" or => { isvariable("test.ary[0][3]"), isvariable("test.ary[12345][1]"), isvariable("test.ary[1][3]"), }; "ok" expression => "good&!bad"; reports: DEBUG:: "expected $(test.num) entries, saw $(test.cnt)"; "saw array indices '$(idx)'"; "expected test.ary[0][0] = '0', saw '$(test.ary[0][0])'"; "expected test.ary[0][1] = '1', saw '$(test.ary[0][1])'"; "expected test.ary[0][2] = '2', saw '$(test.ary[0][2])'"; "expected test.ary[12345][0] = '12345', saw '$(test.ary[12345][0])'"; "expected test.ary[1][0] = '1', saw '$(test.ary[1][0])'"; "expected test.ary[1][1] = '2', saw '$(test.ary[1][1])'"; "expected test.ary[1][2] = '3', saw '$(test.ary[1][2])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/getindices_size2_with_expansion.cf0000644000175100017510000000325012332665147030724 0ustar00a10038a1003800000000000000####################################################### # # Test getindices(), size 2 with variable expansion # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert; } bundle edit_line init_insert { insert_lines: "the fini$end"; "the end$(const.dollar)fini"; "XXX dummy XXX"; "YYY $(init.dummy) YYY"; } ####################################################### bundle agent test { vars: "array[the fini$end]" string => "additional line again"; "array[the end$(const.dollar)fini]" string => "one$(const.n)extra line"; "array[XXX dummy XXX]" string => "XXX dummy XXX"; "array[YYY $(init.dummy) YYY]" string => "YYY $(init.dummy) YYY"; "keys" slist => getindices("array"); files: "$(G.testfile).actual" create => "true", edit_line => test_insert; reports: DEBUG:: "Inserting line: $(keys)"; } bundle edit_line test_insert { vars: "keys" slist => { @{test.keys} }; insert_lines: "$(keys)"; } ####################################################### bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/010.cf0000644000175100017510000000164112243421446022646 0ustar00a10038a1003800000000000000####################################################### # # Test hostsseen() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "hosts" slist => hostsseen("inf", "lastseen", "name"); } ####################################################### bundle agent check { vars: "hosts" slist => { @{test.hosts} }; classes: "ok" expression => "any"; # XXX # I don't know how to test hostsseen! reports: DEBUG:: "$(hosts)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/059.x.cf0000644000175100017510000000171012243421446023126 0ustar00a10038a1003800000000000000####################################################### # # Test accumulated() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "time" int => accumulated(0,1001,1000,1000,1000,40000); } ####################################################### bundle agent check { vars: "time" int => "2682100000"; # 1 year == 365 days classes: "ok" expression => strcmp("$(time)", "$(test.time)"); reports: DEBUG:: "time: $(time)"; "test.time: $(test.time)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/034.cf0000644000175100017510000000300712243421446022652 0ustar00a10038a1003800000000000000####################################################### # # Test readintlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123,,,456,789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" ilist => readintlist("$(G.testfile)","NoComment",",",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" ilist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/on.cf0000644000175100017510000000135612400110676022760 0ustar00a10038a1003800000000000000####################################################### # # Test on(), especially integer out of bounds on some Unices # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent test { vars: "unix_timestamp" int => on(2014, 7 , 21 , 23 , 13 ,0); } ####################################################### bundle agent check { classes: "ok" expression => isvariable("test.unix_timestamp"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/012.cf0000644000175100017510000000300212243421446022641 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123"; "456"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", islessthan("$(test.sum)", "579.1"), isgreaterthan("$(test.sum)", "578.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/execresult.cf0000644000175100017510000002234112316547775024550 0ustar00a10038a1003800000000000000####################################################### # # Test returnszero() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "cwd" string => dirname("$(this.promise_filename)"); windows:: "zero_rel" string => "type $(cwd)$(const.dirsep)text.txt"; "one_rel" string => "type $(cwd)$(const.dirsep)text.txt.doesnotexist"; "nxe_rel" string => "nosuchprogramexists"; "zero_abs" string => "c:\windows\system32\cmd.exe /C type $(cwd)$(const.dirsep)text.txt"; "one_abs" string => "c:\windows\system32\cmd.exe /C type $(cwd)$(const.dirsep)text.txt.doesnotexist"; "nxe_abs" string => "c:\xbin\nosuchprogramexists"; "zero_powershell" string => "Get-Content $(cwd)$(const.dirsep)text.txt"; "one_powershell" string => "Get-Content $(cwd)$(const.dirsep)text.txt.doesnotexist"; "nxe_powershell" string => "nosuchprogramexists"; !windows:: "zero_rel" string => "cat $(cwd)$(const.dirsep)text.txt"; "one_rel" string => "cat $(cwd)$(const.dirsep)text.txt.doesnotexist"; "nxe_rel" string => "nosuchprogramexists"; "zero_abs" string => "/bin/cat $(cwd)$(const.dirsep)text.txt"; "one_abs" string => "/bin/cat $(cwd)$(const.dirsep)text.txt.doesnotexist"; "nxe_abs" string => "/xbin/nosuchprogramexists"; classes: # Test whether we extracted the expected string. "zero_noshell_rel" expression => regcmp(".*Succeeded.*", execresult("$(zero_rel)", "noshell")); "zero_useshell_rel" expression => regcmp(".*Succeeded.*", execresult("$(zero_rel)", "useshell")); "zero_noshell_abs" expression => regcmp(".*Succeeded.*", execresult("$(zero_abs)", "noshell")); "zero_useshell_abs" expression => regcmp(".*Succeeded.*", execresult("$(zero_abs)", "useshell")); "one_noshell_rel" expression => regcmp(".*Succeeded.*", execresult("$(one_rel)", "noshell")); "one_useshell_rel" expression => regcmp(".*Succeeded.*", execresult("$(one_rel)", "useshell")); "one_noshell_abs" expression => regcmp(".*Succeeded.*", execresult("$(one_abs)", "noshell")); "one_useshell_abs" expression => regcmp(".*Succeeded.*", execresult("$(one_abs)", "useshell")); "nxe_noshell_rel" expression => regcmp(".*Succeeded.*", execresult("$(nxe_rel)", "noshell")); "nxe_useshell_rel" expression => regcmp(".*Succeeded.*", execresult("$(nxe_rel)", "useshell")); "nxe_noshell_abs" expression => regcmp(".*Succeeded.*", execresult("$(nxe_abs)", "noshell")); "nxe_useshell_abs" expression => regcmp(".*Succeeded.*", execresult("$(nxe_abs)", "useshell")); # Test whether any assignment happens at all. "does_assign_zero_noshell_rel" expression => regcmp(".*", execresult("$(zero_rel)", "noshell")); "does_assign_zero_useshell_rel" expression => regcmp(".*", execresult("$(zero_rel)", "useshell")); "does_assign_zero_noshell_abs" expression => regcmp(".*", execresult("$(zero_abs)", "noshell")); "does_assign_zero_useshell_abs" expression => regcmp(".*", execresult("$(zero_abs)", "useshell")); "does_assign_one_noshell_rel" expression => regcmp(".*", execresult("$(one_rel)", "noshell")); "does_assign_one_useshell_rel" expression => regcmp(".*", execresult("$(one_rel)", "useshell")); "does_assign_one_noshell_abs" expression => regcmp(".*", execresult("$(one_abs)", "noshell")); "does_assign_one_useshell_abs" expression => regcmp(".*", execresult("$(one_abs)", "useshell")); "does_assign_nxe_noshell_rel" expression => regcmp(".*", execresult("$(nxe_rel)", "noshell")); "does_assign_nxe_useshell_rel" expression => regcmp(".*", execresult("$(nxe_rel)", "useshell")); "does_assign_nxe_noshell_abs" expression => regcmp(".*", execresult("$(nxe_abs)", "noshell")); "does_assign_nxe_useshell_abs" expression => regcmp(".*", execresult("$(nxe_abs)", "useshell")); windows:: # Test whether we extracted the expected string. "zero_powershell" expression => regcmp(".*Succeeded.*", execresult("$(zero_powershell)", "powershell")); "one_powershell" expression => regcmp(".*Succeeded.*", execresult("$(one_powershell)", "powershell")); "nxe_powershell" expression => regcmp(".*Succeeded.*", execresult("$(nxe_powershell)", "powershell")); # Test whether any assignment happens at all. "does_assign_zero_powershell" expression => regcmp(".*", execresult("$(zero_powershell)", "powershell")); "does_assign_one_powershell" expression => regcmp(".*", execresult("$(one_powershell)", "powershell")); "does_assign_nxe_powershell" expression => regcmp(".*", execresult("$(nxe_powershell)", "powershell")); any:: "ok_common" and => { "!zero_noshell_rel", "zero_useshell_rel", "zero_noshell_abs", "zero_useshell_abs", "!one_noshell_rel", "!one_useshell_rel", "!one_noshell_abs", "!one_useshell_abs", "!nxe_noshell_rel", "!nxe_useshell_rel", "!nxe_noshell_abs", "!nxe_useshell_abs", "!does_assign_zero_noshell_rel", "does_assign_zero_useshell_rel", "does_assign_zero_noshell_abs", "does_assign_zero_useshell_abs", "!does_assign_one_noshell_rel", "does_assign_one_useshell_rel", "does_assign_one_noshell_abs", "does_assign_one_useshell_abs", "!does_assign_nxe_noshell_rel", "does_assign_nxe_useshell_rel", "!does_assign_nxe_noshell_abs", "!does_assign_nxe_useshell_abs", }; windows:: "ok_windows" and => { "zero_powershell", "!one_powershell", "!nxe_powershell", "does_assign_zero_powershell", "does_assign_one_powershell", "does_assign_nxe_powershell", }; "ok" and => { "ok_common", "ok_windows", }; !windows:: "ok" and => { "ok_common" }; reports: DEBUG.zero_noshell_rel:: "'$(zero_rel)' executes command successfully with noshell"; DEBUG.!zero_useshell_rel:: "'$(zero_rel)' executes command unsuccessfully with useshell"; DEBUG.one_noshell_rel:: "'$(one_rel)' executes command successfully with noshell"; DEBUG.one_useshell_rel:: "'$(one_rel)' executes command successfully with useshell"; DEBUG.nxe_noshell_rel:: "'$(nxe_rel)' executes command successfully with noshell"; DEBUG.nxe_useshell_rel:: "'$(nxe_rel)' executes command successfully with useshell"; DEBUG.!zero_noshell_abs:: "'$(zero_abs)' executes command unsuccessfully with noshell"; DEBUG.!zero_useshell_abs:: "'$(zero_abs)' executes command unsuccessfully with useshell"; DEBUG.one_noshell_abs:: "'$(one_abs)' executes command successfully with noshell"; DEBUG.one_useshell_abs:: "'$(one_abs)' executes command successfully with useshell"; DEBUG.nxe_noshell_abs:: "'$(nxe_abs)' executes command successfully with noshell"; DEBUG.nxe_useshell_abs:: "'$(nxe_abs)' executes command successfully with useshell"; DEBUG.does_assign_zero_noshell_rel:: "'$(zero_rel)' executes command with noshell"; DEBUG.!does_assign_zero_useshell_rel:: "'$(zero_rel)' does not execute command with useshell"; DEBUG.does_assign_one_noshell_rel:: "'$(one_rel)' executes command with noshell"; DEBUG.!does_assign_one_useshell_rel:: "'$(one_rel)' does not execute command with useshell"; DEBUG.does_assign_nxe_noshell_rel:: "'$(nxe_rel)' executes command with noshell"; DEBUG.!does_assign_nxe_useshell_rel:: "'$(nxe_rel)' does not execute command with useshell"; DEBUG.!does_assign_zero_noshell_abs:: "'$(zero_abs)' does not execute command with noshell"; DEBUG.!does_assign_zero_useshell_abs:: "'$(zero_abs)' does not execute command with useshell"; DEBUG.!does_assign_one_noshell_abs:: "'$(one_abs)' does not execute command with noshell"; DEBUG.!does_assign_one_useshell_abs:: "'$(one_abs)' does not execute command with useshell"; DEBUG.does_assign_nxe_noshell_abs:: "'$(nxe_abs)' executes command with noshell"; DEBUG.does_assign_nxe_useshell_abs:: "'$(nxe_abs)' executes command with useshell"; windows.DEBUG.!zero_powershell:: "'$(zero_powershell)' executes command unsuccessfully with powershell"; windows.DEBUG.one_powershell:: "'$(one_powershell)' executes command successfully with powershell"; windows.DEBUG.nxe_powershell:: "'$(nxe_powershell)' executes command successfully with powershell"; windows.DEBUG.!does_assign_zero_powershell:: "'$(zero_powershell)' does not execute command with powershell"; windows.DEBUG.!does_assign_one_powershell:: "'$(one_powershell)' does not execute command with powershell"; windows.DEBUG.!does_assign_nxe_powershell:: "'$(nxe_powershell)' does not execute command with powershell"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/020.cf0000644000175100017510000000314112243421446022644 0ustar00a10038a1003800000000000000####################################################### # # Test readstringlist() issue 364, also 366 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123 456 789"; # "empty" fields } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" slist => readstringlist("$(G.testfile)","NoComment","\s",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" slist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok456" expression => strcmp("456", "$(nums)"); "ok789" expression => strcmp("789", "$(nums)"); "ok" and => { "ok_list", "ok123", "ok456", "ok789", islessthan("$(test.sum)", "1368.1"), isgreaterthan("$(test.sum)", "1367.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/101.cf0000644000175100017510000000202012243421446022637 0ustar00a10038a1003800000000000000####################################################### # # Test countlinesmatching() with some kind of failure expected # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "zero_regex" string => "impossible line"; "fail" int => countlinesmatching("$(zero_regex)", "/asd/fgh/qwertyio0p"); } ####################################################### bundle agent check { classes: "ok" and => { strcmp("$(test.fail)", "0"), }; reports: DEBUG:: "Expected 0 matches to '$(test.zero_regex)', found $(test.fail)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/02_functions/037.cf0000644000175100017510000000253512243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test readreallist() issue 364 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile)" create => "true", edit_line => init_fill_in; } bundle edit_line init_fill_in { insert_lines: "123"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "nums" rlist => readreallist("$(G.testfile)","NoComment","\s+",5,100); "sum" real => sum("nums"); } ####################################################### bundle agent check { vars: "nums" rlist => { @{test.nums} }; classes: "ok_list" not => strcmp("won't match", "$(nums)"); "ok123" expression => strcmp("123", "$(nums)"); "ok" and => { "ok_list", islessthan("$(test.sum)", "123.1"), isgreaterthan("$(test.sum)", "122.9") }; reports: DEBUG:: "nums: $(nums)"; "sum: $(test.sum)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/0000755000175100017510000000000012403637345021107 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/01_basic/uptime_systime_and_sysday.cf0000644000175100017510000000250112400110676026703 0ustar00a10038a1003800000000000000# Test $(sys.uptime), $(sys.systime) and $(sys.sysday) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: # Quite crude testing, only test that it is a number, and not zero. "regexp" string => "^[0-9]+$"; "notregexp" string => "^0$"; } ####################################################### bundle agent check { classes: "uptime_ok" expression => regcmp("$(init.regexp)", "$(sys.uptime)"); "systime_ok" expression => regcmp("$(init.regexp)", "$(sys.systime)"); "sysday_ok" expression => regcmp("$(init.regexp)", "$(sys.sysday)"); "uptime_ok_zero" not => regcmp("$(init.notregexp)", "$(sys.uptime)"); "systime_ok_zero" not => regcmp("$(init.notregexp)", "$(sys.systime)"); "sysday_ok_zero" not => regcmp("$(init.notregexp)", "$(sys.sysday)"); "ok" and => { "uptime_ok", "systime_ok", "sysday_ok", "uptime_ok_zero", "systime_ok_zero", "sysday_ok_zero" }; reports: DEBUG:: "sys.uptime: $(sys.uptime)"; "sys.systime: $(sys.systime)"; "sys.sysday: $(sys.sysday)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/fncall-invalid-type.x.cf0000644000175100017510000000027512332665147025537 0ustar00a10038a1003800000000000000body common control { bundlesequence => { test }; } bundle agent test { vars: "mylist" slist => { "a", "b" }; "canonified_$(mylist)" slist => canonify("$(mylist)"); } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/sysvars.cf0000644000175100017510000000340512316547775023147 0ustar00a10038a1003800000000000000# Test $(sys.inputdir), $(sys.masterdir), $(sys.libdir), $(sys.bindir), $(sys.failsafe_policy_path), $(sys.update_policy_path), $(sys.local_libdir) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: "expected[bindir]" string => "$(sys.workdir)$(const.dirsep)bin"; "expected[failsafe_policy_path]" string => "$(sys.workdir)$(const.dirsep)inputs$(const.dirsep)failsafe.cf"; "expected[inputdir]" string => "$(sys.workdir)$(const.dirsep)inputs"; "expected[libdir]" string => "$(sys.workdir)$(const.dirsep)inputs$(const.dirsep)lib$(const.dirsep)$(sys.cf_version_major).$(sys.cf_version_minor)"; "expected[local_libdir]" string => "lib$(const.dirsep)$(sys.cf_version_major).$(sys.cf_version_minor)"; "expected[masterdir]" string => "$(sys.workdir)$(const.dirsep)masterfiles"; "expected[update_policy_path]" string => "$(sys.workdir)$(const.dirsep)inputs$(const.dirsep)update.cf"; "sysvars" slist => getindices("expected"); } ####################################################### bundle agent test { } ####################################################### bundle agent check { classes: "$(init.sysvars)_ok" expression => strcmp("$(sys.$(init.sysvars))", "$(init.expected[$(init.sysvars)])"); "ok" and => { "inputdir_ok", "masterdir_ok", "libdir_ok", "bindir_ok", "failsafe_policy_path_ok", "update_policy_path_ok", "local_libdir_ok" }; reports: DEBUG:: "$(init.sysvars) actual='$(sys.$(init.sysvars))', expected '$(init.expected[$(init.sysvars)])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/110.cf.sub0000644000175100017510000000052312236160673022511 0ustar00a10038a1003800000000000000body file control { namespace => "ns110"; } bundle agent pass(given_dummy) { vars: "returned_dummy" string => "$(given_dummy)"; reports: "$(returned_dummy)" bundle_return_value_index => "dummy"; DEBUG:: "ns110:pass: given_dummy = '$(given_dummy)'"; "ns110:pass: returned_dummy = '$(returned_dummy)'"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/105.cf0000644000175100017510000000243412243421446021724 0ustar00a10038a1003800000000000000####################################################### # # Test Scoping of "this" variables (issue 349) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: # $(this.promiser) is not available in this context "not_valid" not => strcmp("xyzzy", "$(this.promiser)"); "valid" expression => strcmp("xyzzy", "$(this.promiser)"); "any_promiser" and => { "not_valid", "valid" }; "ok" not => "any_promiser"; reports: DEBUG.not_valid:: "not_valid IS set (and should not be)"; DEBUG.!not_valid:: "not_valid is not set (and should not be)"; DEBUG.valid:: "valid IS set (and should not be)"; DEBUG.!valid:: "valid is not set (and should not be)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/vars_in_arrays.cf0000644000175100017510000000251112400110676024430 0ustar00a10038a1003800000000000000 # # Parsing paramaterized arrays # body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "init", "check" }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).actual" create => "true", edit_line => write, edit_defaults => empty; "$(G.testfile).expected" create => "true", edit_line => write_control, edit_defaults => empty; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).expected", "$(G.testfile).actual", "$(this.promise_filename)"); } ####################################################### bundle edit_line write_control { insert_lines: "1 3 2 one two three four"; } bundle edit_line write { vars: "a[1]" string => "a"; "a[2]" string => "b"; "a[3]" string => "c"; "alias" string => "a"; "list" slist => getindices($(alias)); "one[$(sys.uqhost)]" slist => { "one", "two" }; "two" slist => { "three", "four" }; "oneandtwo" slist => { @(one[$(sys.uqhost)]), @(two) }; insert_lines: "$(list)"; "$(oneandtwo)"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/qualified_array_with_spaced_index.cf0000644000175100017510000000162512243421446030322 0ustar00a10038a1003800000000000000####################################################### # # Test that an array variable will resolve when fully # qualified and the index contains spaces # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "array[one two three]" string => "snookie"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("snookie", "$(test.array[one two three])"); reports: DEBUG:: "array: $(test.array[one two])"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/107.cf0000644000175100017510000000134512243421446021726 0ustar00a10038a1003800000000000000# Test that function call with computed ifvarclass does not lead to incorrect # use of values (Mantis #864) (Mantis #1084) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "useshell"); } bundle agent check { classes: "ok" not => regcmp(".*Unable to parse class expression.*", "$(test.subout)"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/this_promiser_with_readjson.cf0000644000175100017510000000221112332665147027226 0ustar00a10038a1003800000000000000# Test that this.promiser can be used in a call with readjson # Redmine:4680 (https://cfengine.com/dev/issues/4680) body common control { inputs => { "../../default.cf.sub", "namespaced-bundles.cf.sub1", "namespaced-bundles.cf.sub2" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "cf_promises_validated_mock_data" string => '{ "timestamp": 1393095384 }'; files: "$(G.testfile).cf_promises_validated" create => "true", edit_defaults => empty, edit_line => insert_lines($(cf_promises_validated_mock_data)), comment => "we need example data to parse"; } bundle agent test { vars: "cf_promises_validated" data => readjson("$(G.testfile).$(this.promiser)", 1K); "printable" string => format("%S", "cf_promises_validated"); reports: DEBUG:: "$(printable)"; } bundle agent check { classes: "ok" expression => strcmp("1393095384", $(test.cf_promises_validated[timestamp])); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/duplicate_bundles.cf0000644000175100017510000000147112352022221025072 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "one" usebundle => gvar( "x", "one" ); !FAIL:: "two" usebundle => gvar( "y", "two" ); } bundle agent gvar ( name, value ) { vars: "${name}" string => "${value}"; } bundle agent check { classes: "pass_x" expression => strcmp( "one", "${gvar.x}" ); "pass_y" expression => strcmp( "two", "${gvar.y}" ); methods: "" usebundle => dcs_passif_expected("pass_x,pass_y", "", $(this.promise_filename)), inherit => "true"; reports: EXTRA:: "gvar.x => ${gvar.x}"; "gvar.y => ${gvar.y}"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/006.x.cf0000644000175100017510000000137712243421446022177 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" real => "."; # Not a float } ####################################################### bundle agent check { reports: DEBUG:: "The real variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/var_expansion_in_meta.cf0000644000175100017510000000232212316547775026002 0ustar00a10038a1003800000000000000# Test that variables in meta tags are expanded # Redmine:4885 (https://cfengine.com/dev/issues/4885) body common control { inputs => { "../../default.cf.sub", "namespaced-bundles.cf.sub1", "namespaced-bundles.cf.sub2" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "variables" slist => { "item1", "item2" }; "variable_tag" string => "mytag"; classes: "$(variables)_class" expression => "any", scope => "namespace", meta => { "$(variable_tag)" }; } bundle agent test { vars: "found_classes" slist => classesmatching(".*", $(init.variable_tag)); "joined_found_classes" string => join(",", found_classes); } bundle agent check { vars: "expected_joined_found_classes" string => "item2_class,item1_class"; classes: "ok" expression => strcmp($(expected_joined_found_classes), $(test.joined_found_classes)); reports: DEBUG:: "$(this.promise_filename) Expected: $(expected_joined_found_classes)"; "$(this.promise_filename) Found: $(test.joined_found_classes)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/namespaced-bundles.cf.sub10000644000175100017510000000035512316547775026041 0ustar00a10038a1003800000000000000body file control { namespace => "namespaced_bundles_1"; } bundle agent unique { reports: DEBUG:: "$(this.bundle): run"; } bundle agent unique2(x,y) { reports: DEBUG:: "$(this.bundle): run($(x), $(y))"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/promise_dirname.cf0000644000175100017510000000142212243421446024570 0ustar00a10038a1003800000000000000# Test $(this.promise_dirname) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: "expected" string => dirname($(this.promise_filename)); } ####################################################### bundle agent test { } ####################################################### bundle agent check { classes: "ok" expression => strcmp($(init.expected), $(this.promise_dirname)); reports: DEBUG:: "$(this.promise_filename) expected dirname $(init.expected), actual $(this.promise_dirname)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/005.x.cf0000644000175100017510000000140412243421446022165 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" real => "1.2e.3"; # Not a float } ####################################################### bundle agent check { reports: DEBUG:: "The real variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/109.cf0000644000175100017510000000132712243421446021730 0ustar00a10038a1003800000000000000# Test that variables can be passed across bundles and namespaces body common control { inputs => { "../../default.cf.sub", "109.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { methods: "namespaced" usebundle => ns109:pass($(init.dummy)); } bundle agent check { classes: "ok" expression => strcmp("$(init.dummy)", "$(ns109:pass.passed_dummy)"); reports: DEBUG:: "We passed '$(init.dummy)' to ns109:pass() and it recorded '$(ns109:pass.passed_dummy)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/008.x.cf0000644000175100017510000000141412243421446022171 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" real => "1e2345678"; # Exponent too big } ####################################################### bundle agent check { reports: DEBUG:: "The real variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/013.cf0000644000175100017510000000264212316547775021742 0ustar00a10038a1003800000000000000####################################################### # # Test that 'classes' body works on 'vars' promises # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "foo" string => execresult("/nonexisting", "noshell"), classes => setclasses("nonexisting_t", "nonexisting_f"); "bar" string => execresult("$(G.true)", "noshell"), classes => setclasses("true_t", "true_f"); } body classes setclasses(t,f) { promise_repaired => { "$(t)" }; promise_kept => { "$(t)" }; repair_failed => { "$(f)" }; repair_denied => { "$(f)" }; repair_timeout => { "$(f)" }; } ####################################################### bundle agent check { classes: "ok" expression => "!nonexisting_f.!nonexisting_t.true_t.!true_f"; reports: DEBUG.nonexisting_t:: "nonexisting_t"; DEBUG.nonexisting_f:: "nonexisting_f"; DEBUG.true_t:: "true_t"; DEBUG.true_f:: "true_f"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/106.cf.sub0000644000175100017510000000036012236160673022515 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "test" }; } bundle agent test { vars: "index" slist => { "index" }; "array[$(index)]" string => "value"; "indices" slist => getindices("array"); "values" slist => getvalues("array"); } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/unresolved_variables.cf.sub0000644000175100017510000000327312316547775026446 0ustar00a10038a1003800000000000000# # Unresolved variables end up in reports and files prommises # body common control { bundlesequence => { run, dmi, etc_nologin }; } bundle agent run { classes: "dim_found" expression => regcmp("^[1-9][0-9]*$", $(dim)); vars: "data" string => "PURPLE_DINOSAUR: Ubuntu"; "dim" int => parsestringarray( "lsb", $(data), "\s*#[^\n]*", "\s*:\s+", "15", "4095" ); dim_found:: "PURPLE_DINOSAUR" string => canonify("$(lsb[PURPLE_DINOSAUR][1])"); files: "$(PURPLE_DINOSAUR)" create => "true"; "$(sys.workdir)/state/anotherfile" create => $(PURPLE_DINOSAUR); reports: dim_found:: "$(this.bundle): value = $(PURPLE_DINOSAUR)"; } # inventory DMI decoder, simplified for this test bundle agent dmi { vars: "dmivars" slist => { "PURPLE_DINOSAUR" }; secondpass:: "dmi[$(dmivars)]" string => execresult("echo Not A Dinosaur", "useshell"); classes: "secondpass" expression => "any"; reports: "$(this.bundle): Obtained qualified '$(dmi.dmi[$(dmivars)])'"; # fails "$(this.bundle): Obtained unqualified '$(dmi[$(dmivars)])'"; # fails } # the System::nologin sketch, simplified for this test bundle agent etc_nologin() { vars: secondpass:: "PURPLE_DINOSAUR" string => "$(sys.workdir)/state", policy => "free"; classes: "secondpass" expression => "any"; vars: "etc_nologin" string => "$(PURPLE_DINOSAUR)/etc/nologin"; files: "$(etc_nologin)" create => "true"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/long_string_from_embedded.cf0000644000175100017510000000613412316547775026620 0ustar00a10038a1003800000000000000####################################################### # # Test that we dont crash when slist has very long elements # Redmine:3957 (https://cfengine.com/dev/issues/3957) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "keys" slist => { "ssh-dss YavBsyK3sHDac4Gj4nDbVH9E7OfRPi16DADNOWGKEjWiBB0cCe0UY6xxEgcYuwOOl8HUGqqzLOByvUbo1hENDQldKFt8N7WIb2E9gXFtGm0Sf0NlYARALj1nhLju9hodpGxkr4vKioW1fZQBmBqsI7Ky8ZhzU5p4CAm4uCbxAZuiIhDTAcxj7RlDy3fe9WBw7v0cSIbu8E3zEbPn0VQjTduLCJtFOb5LvUxpxUsHMhHu0xS8DvXIwf7l83cQ0XZtwyIgbF3ZxjIZaPyYhKZRAV1qCze4BlcOerJeVYOiKjpXJlOoBprxy2SfEYVS4Khun0efkmsmBAfllKUUNCqsK9j6oWo7BvNbXqzkl2ULJd6h0LNy9jW8IXnnrfWknLGa7lksVmL3afSAufDAb7yRESaUP5KmcD3ghP3Nvu7fy9hz7nIAPgj2dQOwnFRbkv9Svoi9YmCtvBWYAcwIUVNJBmwXe5j5xJyt5vOyRSI2ooJ9mk69UOCsIM8PEnEXwtHcsg9fDjfu9ChFY2HWZPWeNXH05SATnSyLgclQsZcazhQXPoxZbcqR80mfuRX9ymEzNwZJ1jJUERnj9PZkSInu6mFVRjTaQjg8yvqMGRxWknP8aURCDh5rr4Na23jULVVI66heWOi7nzLqBg5U8GsbLsocM8zBam8bhXfU0KvpBo5wlUtHnDWHoMlS3ktr25ldrp3zLuywhHe5vGUbg2E0gr4xB3oPAyaDa3MGQiVXPfngu5CJhwIXmeN5JtIBA0S46ihg7lQ6IU8kAaRHwhWh3TokoNFOYE8R5i24gpYNF8dgCRGqSZIT5V7wuR3qG1Wau963ILuX8EFOSu7xDc5qnGTem3FwICTpSdnZNqpzRt4Ipqsn4Pa2tFFpHlzDwKFRPS7r8v4QX7acqdTSCUOuZ68GwDRlvHIz5mHUf1XLY3FH2InuWFsonJAZwmEbX5evWXFgyJHFlplQcGJvyNdL0T6oBmbG3ssSMoRnqnsk8XjGWtUyvYoQmOY8HWlMhf4V3v78C4k4TnCbN4LmnDYaDcnXMejrUMYDk6QwW3fdTF5ZyjJMy4ANu2fJfKysZMc1Cc== root@host1", "ssh-dss a58AZSxQlmcq33EBCW1GuhpkYCgUfr7o5A1arQZ2dr8I4kldCF76mpl6o2CFthZs4YUU8LewbIDDPqjhS2WwafTXeMEvPMtmLufk6E5njNy2WQtAnmGc9R21qIteTgikY9ubRCM3hlhzJ1wGSKCsE5oBHDQC0thk1ljJGHzsEl0AuVClkUq3yz4eWAsiRdbD9QY7ddD6zA61aHomuczKU5F0VvyO8gRQmWV7b6lysoUFcMgCPVf3UaDdg7L7vvBVkQN2vGCh9CCJz5OkBShlZVNaAXd5TkKJNmsTuBDscPyxeCBAk8sai69f1NNtTeAyWTtSu1KiqTDvD9aal93MhpZnPdOZzNr7etK4C7HuPD0uFjdvKZy1H55rpwNHnJ4GojqiNG1VvN5bGLa3sSLiKOngtMBCokdtHpZn2eHD7oLUROTIG3ZXqFGGvfKEP5zlpvJz3392n4PDQ7EKuNFPhyNQpVXEIAQEDcmeWMopVTGezLoFJG01hKMPxs5QWF7qetVLi1pCjmlUpqgE8c81WGxvMe7ooMtQbeVNulX3qBC3rZhYKtk0R5AA8JxmxHSLYlLFbtnR1PA97hnRvnvlfk92i7WL1hjJsMl29LOrubi554Dr9N2uVUrCFcPZMK45PY0TiRH82AKFmkM8mbM0rndJxoJobZsqRAGHVIkcS53hxMT69liRxlCyubwcxgDaqmeQnJU2Ug0YyFs1uxt4NT9laJ0CO2IxhkbmGeDGw1FJqKyc8Haov263cFMcB97I3gyNHccsAynQnxpMS1ltTFXalghuochdue4unbq0Ty2PfS4jPMkavBlMYN8UZdnyZHuUhycwBJri1Grv5kf2SP00P6NQhuB8kwjqoTG8ay5fKWvhDrVetd7tPuj4dMouHuDeaLJInc7Cz0S5tQOuMfRhpPqk1E8A0YnuNCyPDNuW75rkXZkxP9cYSVWeDa1wgOyNLZDTzYts82qiu9kxLbZ184jowJ8rru4UB20JRtoehnD2nGU1NfegD1qOBgQHtDuB18xggfvOgvUNXBrQpICSz0JqszpftAgV5TJq1FjOdjUo1kOCFuqqi6C4S0Siho== root@host2",}; } ####################################################### bundle agent check { classes: "ok" expression => "any", comment => "If we made it to here, we didnt crash"; reports: DEBUG:: "$(this.bundle): Got key $(test.keys)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/009.cf0000644000175100017510000000226612243421446021732 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "zero_p" real => "0e2345678"; # Exponent too big, but still zero "zero_n" real => "0e-2345678"; # Exponent too big, but still zero } ####################################################### bundle agent check { classes: "ok" and => { isgreaterthan("$(test.zero_p)", "-0.1"), islessthan("$(test.zero_p)", "0.1"), isgreaterthan("$(test.zero_n)", "-0.1"), islessthan("$(test.zero_n)", "0.1"), }; reports: DEBUG:: "zero_p == $(test.zero_p)"; "zero_n == $(test.zero_n)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/110.cf0000644000175100017510000000136012243421446021715 0ustar00a10038a1003800000000000000# Test that variables can be passed across bundles and namespaces body common control { inputs => { "../../default.cf.sub", "110.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { methods: "namespaced" usebundle => ns110:pass($(init.dummy)), useresult => "nsresult"; } bundle agent check { classes: "ok" expression => strcmp("$(init.dummy)", "$(test.nsresult[dummy])"); reports: DEBUG:: "We passed '$(init.dummy)' to ns110:pass() and it returned '$(test.nsresult[dummy])'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/002.x.cf0000644000175100017510000000145312243421446022166 0ustar00a10038a1003800000000000000####################################################### # # Test that a variable cannot be defined twice in the # same promise. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "twice" string => "plus ca change..", int => 42; } ####################################################### bundle agent check { reports: DEBUG:: "Assignment should fail"; cfengine_3: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/0000755000175100017510000000000012352022221022523 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/025.cf0000644000175100017510000000507612243421446023366 0ustar00a10038a1003800000000000000####################################################### # # Test irange # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: # Normal order "r1" string => irange(10,20); "r2" string => irange("10","20"); "r3" string => irange("1k","2K"); "r4" string => irange("1m","2M"); "r5" string => irange("1g","2G"); "r6" string => irange("-20",10); # Reverse order "x1" string => irange(20,10); "x2" string => irange("20","10"); "x3" string => irange("2K","1k"); "x4" string => irange("2M","1m"); "x5" string => irange("2G","1g"); "x6" string => irange(10,"-20"); # String equivalent "s1" string => "10,20"; "s2" string => "10,20"; "s3" string => "1000,2048"; "s4" string => "1000000,2097152"; "s5" string => "1000000000,2147483648"; "s6" string => "-20,10"; } ####################################################### bundle agent check { classes: "ok1" and => { strcmp("$(test.r1)", "$(test.x1)"), strcmp("$(test.r1)", "$(test.s1)"), }; "ok2" and => { strcmp("$(test.r2)", "$(test.x2)"), strcmp("$(test.r2)", "$(test.s2)"), }; "ok3" and => { strcmp("$(test.r3)", "$(test.x3)"), strcmp("$(test.r3)", "$(test.s3)"), }; "ok4" and => { strcmp("$(test.r4)", "$(test.x4)"), strcmp("$(test.r4)", "$(test.s4)"), }; "ok5" and => { strcmp("$(test.r5)", "$(test.x5)"), strcmp("$(test.r5)", "$(test.s5)"), }; "ok6" and => { strcmp("$(test.r6)", "$(test.x6)"), strcmp("$(test.r6)", "$(test.s6)"), }; "ok" and => { "ok1", "ok2", "ok3", "ok4", "ok5", "ok6" }; reports: DEBUG.!ok1:: "Mismatch 1: '$(test.r1)' '$(test.x1)' '$(test.s1)'"; DEBUG.!ok2:: "Mismatch 2: '$(test.r2)' '$(test.x2)' '$(test.s2)'"; DEBUG.!ok3:: "Mismatch 3: '$(test.r3)' '$(test.x3)' '$(test.s3)'"; DEBUG.!ok4:: "Mismatch 4: '$(test.r4)' '$(test.x4)' '$(test.s4)'"; DEBUG.!ok5:: "Mismatch 5: '$(test.r5)' '$(test.x5)' '$(test.s5)'"; DEBUG.!ok6:: "Mismatch 6: '$(test.r6)' '$(test.x6)' '$(test.s6)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/026.cf0000644000175100017510000000611712243421446023364 0ustar00a10038a1003800000000000000####################################################### # # Test rrange # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: # Normal order "r1" string => rrange(10,20); "r2" string => rrange("10.1","20.2"); "r3" string => rrange("1.1k","2.2K"); "r4" string => rrange("1.1m","2.2M"); "r5" string => rrange("1.1g","2.2G"); "r6" string => rrange("-20.2",10); "r7" string => rrange("10.1%","20.2%"); # Reverse order "x1" string => rrange(20,10); "x2" string => rrange("20.2","10.1"); "x3" string => rrange("2.2K","1.1k"); "x4" string => rrange("2.2M","1.1m"); "x5" string => rrange("2.2G","1.1g"); "x6" string => rrange("20.2",10); "x7" string => rrange("20.2%","10.1%"); # String equivalent "s1" string => "10.000000,20.000000"; "s2" string => "10.100000,20.200000"; "s3" string => "1100.000000,2252.800000"; "s4" string => "1100000.000000,2306867.200000"; "s5" string => "1100000000.000000,2362232012.800000"; "s6" string => "-20.200000,10.000000"; # Unsure that this is correct behavior... and it do this now anyway "s7" string => "20.200000,10.100000"; } ####################################################### bundle agent check { classes: "ok1" and => { strcmp("$(test.r1)", "$(test.x1)"), strcmp("$(test.r1)", "$(test.s1)"), }; "ok2" and => { strcmp("$(test.r2)", "$(test.x2)"), strcmp("$(test.r2)", "$(test.s2)"), }; "ok3" and => { strcmp("$(test.r3)", "$(test.x3)"), strcmp("$(test.r3)", "$(test.s3)"), }; "ok4" and => { strcmp("$(test.r4)", "$(test.x4)"), strcmp("$(test.r4)", "$(test.s4)"), }; "ok5" and => { strcmp("$(test.r5)", "$(test.x5)"), strcmp("$(test.r5)", "$(test.s5)"), }; "ok6" and => { strcmp("$(test.r6)", "$(test.x6)"), strcmp("$(test.r6)", "$(test.s6)"), }; "ok7" and => { strcmp("$(test.r7)", "$(test.x7)"), strcmp("$(test.r7)", "$(test.s7)"), }; "ok" and => { "ok1", "ok2", "ok3", "ok4", "ok5", "ok6", "ok7" }; reports: DEBUG.!ok1:: "Mismatch 1: '$(test.r1)' '$(test.x1)' '$(test.s1)'"; DEBUG.!ok2:: "Mismatch 2: '$(test.r2)' '$(test.x2)' '$(test.s2)'"; DEBUG.!ok3:: "Mismatch 3: '$(test.r3)' '$(test.x3)' '$(test.s3)'"; DEBUG.!ok4:: "Mismatch 4: '$(test.r4)' '$(test.x4)' '$(test.s4)'"; DEBUG.!ok5:: "Mismatch 5: '$(test.r5)' '$(test.x5)' '$(test.s5)'"; DEBUG.!ok6:: "Mismatch 6: '$(test.r6)' '$(test.x6)' '$(test.s6)'"; DEBUG.!ok7:: "Mismatch 7: '$(test.r7)' '$(test.x7)' '$(test.s7)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/107.cf0000644000175100017510000000205412243421446023360 0ustar00a10038a1003800000000000000####################################################### # # Test $(this.promise_filename) in body referenced from bundle called from # another file. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -vKf $(this.promise_filename).sub -DAUTO | grep Q:", "useshell"); } ####################################################### bundle agent check { classes: "default" expression => regcmp(".*default\\.cf.*", "$(test.subout)"); "itself" expression => regcmp(".*107\\.cf.*", "$(test.subout)"); "ok" and => { "!default", "itself" }; reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/011.cf0000644000175100017510000000546012243421446023356 0ustar00a10038a1003800000000000000####################################################### # # Test missing variable expansion consistency # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "foo" int => "42"; "baz[a]" string => "alpha"; "gar" string => "$(missing)"; "bletch" string => "$(gar)"; classes: # Known values should test easily "s_foo" expression => strcmp("$(foo)", "42"); "s_baz_a" expression => strcmp("$(baz[a])", "alpha"); # Missing variable names expand to $(varname) in reports and should # expand to the same value in strcmp... "s_missing" expression => strcmp("$(missing)", "$(const.dollar)(missing)"); "s_baz_b" expression => strcmp("$(baz[b])", "$(const.dollar)(baz[b])"); # We test the rest two ways because we assigned a missing variable to # another variable - first the literal assigned value and then the # expanded version testing for missing vars "s_gar" expression => strcmp("$(gar)", "$(missing)"); "s_gar2" expression => strcmp("$(gar)", "$(const.dollar)(missing)"); "s_bletch" expression => strcmp("$(bletch)", "$(missing)"); "s_bletch2" expression => strcmp("$(bletch)", "$(const.dollar)(missing)"); "good" and => { "s_foo", "s_baz_a", "s_gar", "s_gar2", "s_bletch", "s_bletch2", }; "v_missing" expression => isvariable("missing"); "v_baz" expression => isvariable("baz"); "v_baz_b" expression => isvariable("baz[b]"); "bad" or => { "v_missing", "v_baz", "v_baz_b", "v_baz_x", }; "ok" expression => "good&!bad"; reports: DEBUG.ok:: "Saw exactly what we expected"; DEBUG.!ok:: "Saw unexpected results!!"; DEBUG.v_missing:: "$(const.dollar)missing is a variable, and shouldn't be!"; DEBUG.v_baz:: "$(const.dollar)baz is a variable, and shouldn't be!"; DEBUG.v_baz_b:: "$(const.dollar)baz[b] is a variable, and shouldn't be!"; DEBUG.!s_foo:: "expected $(const.dollar)foo = '42', saw '$(foo)'"; DEBUG.!s_baz_a:: "expected $(const.dollar)baz[a] = 'alpha', saw '$(baz[a])'"; DEBUG.!(s_gar.s_gar2):: "expected $(const.dollar)gar = '$(const.dollar)(missing)', saw '$(gar)'"; DEBUG.!(s_bletch.s_bletch2):: "expected $(const.dollar)bletch = '$(const.dollar)(missing)', saw '$(bletch)'"; } bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/107.cf.ext0000644000175100017510000000071112236160673024161 0ustar00a10038a1003800000000000000body package_method simplepkg(abug) { package_list_command => "/bin/sh -c 'echo $(this.promise_filename)'"; package_list_update_command => "/bin/sh -c 'echo $(this.promise_filename)'"; package_list_update_ifelapsed => "0"; package_installed_regex => ".*"; package_list_name_regex => ".*"; package_list_version_regex => ".*"; package_list_arch_regex => ".*"; package_add_command => "$(G.false)"; package_delete_command => "$(G.false)"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/002.x.cf0000644000175100017510000000140312243421446023615 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" int => "10.0"; # Not an integer } ####################################################### bundle agent check { reports: DEBUG:: "The int variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/003.x.cf0000644000175100017510000000142412243421446023621 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" int => "12345678901234567890"; # Integer too big } ####################################################### bundle agent check { reports: DEBUG:: "The int variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/this_promises_in_command_args.cf0000644000175100017510000000134112352022221031124 0ustar00a10038a1003800000000000000####################################################### # # Redmine#5959 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent test { commands: # should expand to "touch testfile touch testfile.2" "$(G.touch) $(G.testfile)" args => "$(this.promiser).2"; } ####################################################### bundle agent check { methods: "" usebundle => dcs_passif_fileexists("$(G.testfile).2", $(this.promise_filename)); } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/staging/107.cf.sub0000644000175100017510000000106612236160673024156 0ustar00a10038a1003800000000000000# # Test reading single-line list of packages # body common control { inputs => { "../../default.cf", "107.cf.ext" }; bundlesequence => { "g", default("$(this.promise_filename)") }; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "p" package_version => "", package_architectures => { "" }, package_method => simplepkg("abug"), package_policy => "add", package_select => "=="; } bundle agent check { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/namespaced-bundles.cf0000644000175100017510000000142712316547775025171 0ustar00a10038a1003800000000000000# Test that variables can be passed across bundles and namespaces body common control { inputs => { "../../default.cf.sub", "namespaced-bundles.cf.sub1", "namespaced-bundles.cf.sub2" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { methods: "1" usebundle => namespaced_bundles_1:unique; "2" usebundle => namespaced_bundles_2:unique; "3" usebundle => namespaced_bundles_1:unique2("a", "b"); "4" usebundle => namespaced_bundles_2:unique2("one value"); } bundle agent check { classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/109.cf.sub0000644000175100017510000000041512236160673022521 0ustar00a10038a1003800000000000000body file control { namespace => "ns109"; } bundle agent pass(given_dummy) { vars: "passed_dummy" string => "$(given_dummy)"; reports: DEBUG:: "ns109:pass: given_dummy = '$(given_dummy)'"; "ns109:pass: passed_dummy = '$(passed_dummy)'"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/111.cf0000644000175100017510000000240312316547775021734 0ustar00a10038a1003800000000000000####################################################### # # Check that similar command promises are not skipped # (cf redmine #2182) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### body classes if_touched(x) { visited:: promise_repaired => { "revisited" }; !visited:: promise_repaired => { "visited" }; } ####################################################### bundle agent init { } ####################################################### bundle agent test { commands: "$(G.echo) restart" classes => if_touched("called"); methods: "any" usebundle => call; } bundle agent call { commands: "$(G.echo) restart" classes => if_touched("called"); } ####################################################### bundle agent check { classes: any:: "ok" and => { "visited", "revisited" }; reports: DEBUG.visited:: "visited defined"; DEBUG.revisited:: "revisited defined"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/004.x.cf0000644000175100017510000000140312243421446022163 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" real => "1.2.3"; # Not a float } ####################################################### bundle agent check { reports: DEBUG:: "The real variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/unresolved_variables.cf0000644000175100017510000000136212316547775025653 0ustar00a10038a1003800000000000000# Redmine#4889: avoid unresolved variables in promiser or attributes body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub -DAUTO,DEBUG 2>&1 | $(G.grep) PURPLE_DINOSAUR", "useshell"); } bundle agent check { classes: "ok" not => regcmp("PURPLE_DINOSAUR", $(test.subout)); reports: ok.EXTRA:: "The output was OK: $(test.subout)"; !ok.DEBUG:: "The output was NOT OK: $(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/001.cf0000644000175100017510000000211612243421446021714 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" int => "10"; "ten[ten]" int => "11"; "nine" string => "hello", policy => "free"; "nine" int => "9", policy => "free"; } ####################################################### bundle agent check { classes: "ok_10" not => strcmp("$(test.ten)", "$(test.ten[ten])"); "ok" and => { "ok_10", strcmp("$(test.nine)", "9") }; reports: DEBUG:: "ten == $(test.ten)"; "ten[ten] == $(test.ten[ten])"; "nine == $(test.nine)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/108.cf.sub0000644000175100017510000000041512236160673022520 0ustar00a10038a1003800000000000000body file control { namespace => "ns108"; } bundle agent pass(given_dummy) { vars: "passed_dummy" string => "$(given_dummy)"; reports: DEBUG:: "ns108:pass: given_dummy = '$(given_dummy)'"; "ns108:pass: passed_dummy = '$(passed_dummy)'"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/namespaced-bundles.cf.sub20000644000175100017510000000036212316547775026040 0ustar00a10038a1003800000000000000body file control { namespace => "namespaced_bundles_2"; } bundle agent unique { reports: DEBUG:: "$(this.bundle): run"; } bundle agent unique2(justone) { reports: DEBUG:: "$(this.bundle): run($(justone))"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/parse_number_3572.cf0000644000175100017510000000264212316547775024601 0ustar00a10038a1003800000000000000####################################################### # # Regression test for RedMine #3572. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "digits" string => "42"; } ####################################################### bundle agent test { vars: "number" int => "$(init.digits)"; "floaty" real => "$(init.digits)"; # RedMine #3572: this stanza should make no difference, but actually # caused the numbers to be unexpanded, hence not "42" but literally # "$(init.digits)", which doesn't parse as a number ! classes: "ignored" not => "any"; # (In fact, even an empty classes stanza provoked the bug - but is # that even valid ?) } ####################################################### bundle agent check { classes: "iok" expression => strcmp("$(test.number)", "$(init.digits)"); "rok" expression => strcmp("$(test.floaty)", "42.000000"); "ok" and => { "iok", "rok" }; reports: DEBUG.!iok:: "Read $(init.digits) as int $(test.number)"; DEBUG.!rok:: "Read $(init.digits) as real $(test.floaty)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/parse_number.cf0000644000175100017510000000644212316547775024123 0ustar00a10038a1003800000000000000####################################################### # # Test basic interpretation of digits as numbers. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "digits" string => "42"; "zero" string => "00000"; "negate" string => "-137"; "spacey" string => "17 "; # Spaces ignored after number "kilo" string => "42k"; "kibi" string => "42K"; "mega" string => "42m"; "mibi" string => "42M"; # NB: 42g fails on 32-bit - many places go via int, which overflows (Redmine 4404). "giga" string => "1g"; "gibi" string => "1G"; "pi" string => "3.141592653589793238462643383279502884197169399375105820974"; "nowt" string => "-000.0000e137"; "nogiga" string => "0e0G "; # quantifier and spaces "me2pi" string => "-.5354916555247646e-3M"; # minus exp(two pi) "whole" slist => { "digits", "zero", "negate", "spacey", "kilo", "kibi", "mega", "mibi", "giga", "gibi" }; "float" slist => { "pi", "nowt", "nogiga", "me2pi" }; # Expected answers: "round[digits]" string => "$(digits)"; "round[zero]" string => "0"; "round[negate]" string => "$(negate)"; "round[spacey]" string => "17"; "round[kilo]" string => "42000"; "round[kibi]" string => "43008"; "round[mega]" string => "42000000"; "round[mibi]" string => "44040192"; "round[giga]" string => "1000000000"; "round[gibi]" string => "1073741824"; "ratio[$(whole)]" string => "$(round[$(whole)]).000000"; "ratio[pi]" string => "3.14159265"; "ratio[nowt]" string => "$(ratio[zero])"; "ratio[nogiga]" string => "$(ratio[zero])"; "ratio[me2pi]" string => "535.491656"; } ####################################################### bundle agent test { vars: "round[$(init.whole)]" int => "$(init.$(init.whole))"; "ratio[$(init.whole)]" real => "$(init.$(init.whole))"; "ratio[$(init.float)]" real => "$(init.$(init.float))"; } ####################################################### bundle agent check { vars: "float" slist => { @(init.whole), @(init.float) }; classes: "whole_$(init.whole)" expression => strcmp("$(test.round[$(init.whole)])", "$(init.round[$(init.whole)])"); "float_$(float)" expression => strcmp("$(test.ratio[$(float)])", "$(init.ratio[$(float)])"); "$(init.whole)" and => { "whole_$(init.whole)", "float_$(init.whole)" }; "$(init.float)" and => { "float_$(init.whole)" }; "iok" and => { @(init.whole) }; "rok" and => { @(init.float) }; "ok" and => { "iok", "rok" }; reports: DEBUG.!iok:: "Read $(init.$(init.whole)) as int $(test.round[$(init.whole)]), expected $(init.round[$(init.whole)])"; DEBUG.!rok:: "Read $(init.$(float)) as real $(test.ratio[$(float)]), expected $(init.ratio[$(float)])"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/108.cf0000644000175100017510000000132712243421446021727 0ustar00a10038a1003800000000000000# Test that variables can be passed across bundles and namespaces body common control { inputs => { "../../default.cf.sub", "108.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { methods: "namespaced" usebundle => ns108:pass($(init.dummy)); } bundle agent check { classes: "ok" expression => strcmp("$(init.dummy)", "$(ns108:pass.passed_dummy)"); reports: DEBUG:: "We passed '$(init.dummy)' to ns108:pass() and it recorded '$(ns108:pass.passed_dummy)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/010.cf0000644000175100017510000000231312403637345021720 0ustar00a10038a1003800000000000000####################################################### # # Test nested functions # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "oct2" string => '20'; "oct4" slist => { '11', '12' }; "separator" string => ","; "prefix" string => "10.${oct2}.20"; "temp_namelist" slist => { " ", @(oct4) }; "foo" slist => splitstring ( join("${separator}${prefix}", "temp_namelist"), "$(separator)", "999999999" ); "nameserv" slist => grep ("^[^\s]+$", join(escape("${separator}${prefix}"), "temp_namelist") ); } ####################################################### bundle agent check { classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/106.cf0000644000175100017510000000165512243421446021731 0ustar00a10038a1003800000000000000####################################################### # # Test arrays with list-specified indices (issue 692) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "useshell"); } ####################################################### bundle agent check { classes: "ok" not => regcmp(".*Redefinition.*", "$(test.subout)"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/007.x.cf0000644000175100017510000000140012243421446022163 0ustar00a10038a1003800000000000000####################################################### # # Test simple variables failures # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "ten" real => "e2"; # Not a float } ####################################################### bundle agent check { reports: DEBUG:: "The real variable assignment should fail"; cfengine_3:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/012.cf0000644000175100017510000000161212243421446021716 0ustar00a10038a1003800000000000000####################################################### # # Compilation test of strings that end with a \ - issue 690 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "foo" string => "simple"; "baz" string => "s\imple"; "gar" string => "s\\imple"; "goo" string => "s\\"; "boo" string => "\\e"; "zoo" string => "\\"; } bundle agent check { classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/empty-splice-does-not-segfault.cf0000644000175100017510000000044212243421446027365 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { reports: "empty @{}"; } bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/01_vars/01_basic/107.cf.sub0000644000175100017510000000037312236160673022522 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "main" }; } bundle agent main { methods: "TEST" usebundle => test("any"); } bundle common test(var) { vars: "something" string => and("any", "any"), ifvarclass => canonify("${var}"); } cfengine-3.6.2/tests/acceptance/xml-c14nize.c0000644000175100017510000000205412243421446020466 0ustar00a10038a1003800000000000000#include #include #include #include static bool xmlC14nizeFile(const char *filename) { xmlDocPtr doc = xmlParseFile(filename); if (doc == NULL) { fprintf(stderr, "Unable to open %s for canonicalization\n", filename); return false; } xmlOutputBufferPtr out = xmlOutputBufferCreateFile(stdout, NULL); if (out == NULL) { fprintf(stderr, "Unable to set up writer for stdout\n"); return false; } if (xmlC14NDocSaveTo(doc, NULL, XML_C14N_1_0, 0, true, out) < 0) { fprintf(stderr, "Unable to c14nize XML document\n"); return false; } if (xmlOutputBufferClose(out) < 0) { fprintf(stderr, "Unable to close writer for stdout\n"); return false; } xmlFreeDoc(doc); return true; } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: xml-c14nize \n"); return 2; } return xmlC14nizeFile(argv[1]) ? 0 : 1; } cfengine-3.6.2/tests/acceptance/17_users/0000755000175100017510000000000012243421446017716 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/17_users/unsafe/0000755000175100017510000000000012412512360021171 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_with_many_attributes.cf0000644000175100017510000001000012400110676030345 0ustar00a10038a1003800000000000000####################################################### # # Test modifying a user with many attributes. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Start out with other attributes. users: "johndoe" policy => "present", password => init_password, uid => "8765", group_primary => "$(user_tests.gid2)", groups_secondary => { "$(user_tests.group1)" }, home_dir => "/home/johndoe", shell => "/bin/bash", description => "Wrong!"; } body password init_password { format => "plaintext"; data => "Wrong0P4SSW0RD"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; "desc_string" string => "This description should make the CFEngine test pass"; users: "johndoe" policy => "present", password => test_password, uid => "9876", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, home_dir => "/home/user-johndoe", shell => "/bin/csh", description => "$(desc_string)"; } body password test_password { !windows:: format => "hash"; data => "$(test.hash)"; windows:: format => "plaintext"; data => "New0P4SSW0RD"; } ####################################################### bundle agent check { methods: "any" usebundle => remove_stale_groups; methods: "any" usebundle => user_has_uid("johndoe", "9876", "uid_success", "uid_failure"), classes => always("uid_methods_run"); "any" usebundle => user_is_in_primary_group("johndoe", "$(user_tests.group1)", "pgroup_success", "pgroup_failure"), classes => always("pgroup_methods_run"); "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group2)", "sgroup_success", "sgroup_failure"), classes => always("sgroup_methods_run"); "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group1)", "not_sgroup_failure", "not_sgroup_success"), classes => always("not_sgroup_methods_run"); "any" usebundle => user_has_home_dir("johndoe", "/home/user-johndoe", "home_success", "home_failure"), classes => always("home_methods_run"); "any" usebundle => user_has_shell("johndoe", "/bin/csh", "shell_success", "shell_failure"), classes => always("shell_methods_run"); "any" usebundle => user_has_description("johndoe", "$(test.desc_string)", "desc_success", "desc_failure"), classes => always("desc_methods_run"); !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(test.hash)", "hash_success", "hash_failure"), classes => always("hash_methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "New0P4SSW0RD", "hash_success", "hash_failure"), classes => always("hash_methods_run"); classes: "ready" and => { "uid_methods_run", "pgroup_methods_run", "sgroup_methods_run", "not_sgroup_methods_run", "home_methods_run", "shell_methods_run", "desc_methods_run", "hash_methods_run" }; !windows:: # Note the secondary group classes here. Windows treats primary and secondary groups the same, # and hence that test is invalid there. "unix_ok" and => { "uid_success", "!uid_failure", "shell_success", "!shell_failure", "not_sgroup_success", "!not_sgroup_failure", }; windows:: "unix_ok" expression => "any"; any:: "ok" and => { "pgroup_success", "!pgroup_failure", "sgroup_success", "!sgroup_failure", "hash_success", "!hash_failure", "home_success", "!home_failure", "desc_success", "!desc_failure", "unix_ok" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_lock_warn.cf0000644000175100017510000000207212332665147026105 0ustar00a10038a1003800000000000000####################################################### # # Test warning about locking a user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { users: "johndoe" action => test_action, policy => "locked"; } body action test_action { action_policy => "warn"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_unlocked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user.cf0000644000175100017510000000200412332665147023302 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { users: "johndoe" policy => "present"; } ####################################################### bundle agent check { methods: "any" usebundle => user_exists("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/aix_get_shadow_field.pl0000755000175100017510000000107312400110676025663 0ustar00a10038a1003800000000000000#!/usr/bin/perl -w # Takes two arguments, the field to get, and the user to get it from. open(PASSWD, "< /etc/security/passwd") or die("Could not open password file"); my $in_user_section = 0; my $hash = ""; while () { if (!$in_user_section) { if (/^$ARGV[1]:/) { $in_user_section = 1; } } else { if (/^\S/) { $in_user_section = 0; } elsif (/$ARGV[0] *= *(\S+)/) { $hash = $1; } } } print("$hash\n") if ($hash); close(PASSWD); cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_with_password.cf0000644000175100017510000000331012412221023026773 0ustar00a10038a1003800000000000000####################################################### # # Test modifying a user with a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => init_password; } body password init_password { data => "$(init.hash)"; !windows:: format => "hash"; windows:: format => "plaintext"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", password => test_password; } body password test_password { format => "plaintext"; data => "New0P4SSW0RD"; } ####################################################### bundle agent check { methods: !windows:: # Make sure it is *not* the same as before. "any" usebundle => user_has_password_hash("johndoe", "$(init.hash)", "failure", "success"), classes => always("methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "New0P4SSW0RD", "success", "failure"), classes => always("methods_run"); any:: "any" usebundle => user_does_not_need_password_update("johndoe", "no_pw_update_ok", "no_pw_update_fail"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure", "no_pw_update_ok", "!no_pw_update_fail" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_primary_group.cf0000644000175100017510000000377612352022221027313 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a primary group. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub", "disable_sudo_tty_requirement.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; files: "$(G.testfile)" delete => init_delete; methods: "any" usebundle => disable_sudo_tty_requirement; } body delete init_delete { rmdirs => "false"; } ####################################################### body contain test_contain_body { useshell => "useshell"; } bundle agent test { users: "johndoe" policy => "present", group_primary => "$(user_tests.group1)"; commands: !windows:: "sudo -u johndoe $(G.touch) $(G.testfile)" contain => test_contain_body; } ####################################################### body perms check_perms_body { groups => { "$(user_tests.group1)" }; } body classes check_classes_body { promise_repaired => { "perms_not_ok" }; promise_kept => { "perms_ok" }; } bundle agent check { methods: "any" usebundle => remove_stale_groups; methods: "any" usebundle => user_is_in_primary_group("johndoe", "$(user_tests.group1)", "success", "failure"), classes => always("methods_run"); files: !windows:: "$(G.testfile)" perms => check_perms_body, classes => check_classes_body; classes: "ready" expression => "methods_run"; !windows:: "ok" and => { "success", "!failure", "perms_ok", "!perms_not_ok" }; windows:: "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_secondary_gid.cf0000644000175100017510000000321012400110676027213 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a secondary gid. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub", "disable_sudo_tty_requirement.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### body perms init_perms_body { groups => { "$(user_tests.gid1)" }; mode => "664"; } bundle agent init { # AIX useradd/usermod commands do not support numerical group arguments. meta: "test_suppress_fail" string => "aix", meta => { "redmine6285" }; # Remove him first, should he already be present. users: "johndoe" policy => "absent"; files: "$(G.testfile)" create => "true", perms => init_perms_body; methods: "any" usebundle => disable_sudo_tty_requirement; } ####################################################### body contain test_contain_body { useshell => "useshell"; } bundle agent test { users: "johndoe" policy => "present", groups_secondary => { "$(user_tests.gid1)" }; commands: !windows:: "sudo -u johndoe /bin/sh -c '$(G.echo) Succeeded > $(G.testfile)'" contain => test_contain_body; } ####################################################### bundle agent check { classes: "ok" not => strcmp("0", countlinesmatching("Succeeded", "$(G.testfile)")); reports: ok|windows:: "$(this.promise_filename) Pass"; !ok.!windows:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_lock_with_password.cf0000644000175100017510000000221312400110676030014 0ustar00a10038a1003800000000000000####################################################### # # Test locking a user and setting a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "locked", password => test_password; } body password test_password { format => "hash"; data => "$(test.hash)"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_locked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_with_many_attributes_warn.cf0000644000175100017510000001015312400110676031405 0ustar00a10038a1003800000000000000####################################################### # # Test warning about modifying a user with many attributes. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: "hash" string => "dTloMVpjYt1w2"; # Start out with other attributes. users: "johndoe" policy => "present", password => init_password, uid => "8765", group_primary => "$(user_tests.group2)", groups_secondary => { "$(user_tests.group1)" }, home_dir => "/johns_old_home_dir", shell => "/bin/csh", description => "Good user"; } body password init_password { !windows:: format => "hash"; data => "$(init.hash)"; windows:: format => "plaintext"; data => "Old0P4SSW0RD"; } ####################################################### bundle agent test { vars: "desc_string" string => "This description should make the CFEngine test fail"; users: "johndoe" action => test_action, policy => "present", password => test_password, uid => "9876", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, home_dir => "/johns_home_dir", shell => "/bin/sh", description => "$(desc_string)"; } body action test_action { action_policy => "warn"; } body password test_password { format => "plaintext"; data => "Wrong0P4SSW0RD"; } ####################################################### bundle agent check { methods: "any" usebundle => remove_stale_groups; methods: "any" usebundle => user_has_uid("johndoe", "8765", "uid_success", "uid_failure"), classes => always("uid_methods_run"); "any" usebundle => user_is_in_primary_group("johndoe", "$(user_tests.group2)", "pgroup_success", "pgroup_failure"), classes => always("pgroup_methods_run"); "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group1)", "sgroup_success", "sgroup_failure"), classes => always("sgroup_methods_run"); "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group2)", "not_sgroup_failure", "not_sgroup_success"), classes => always("not_sgroup_methods_run"); "any" usebundle => user_has_home_dir("johndoe", "/johns_old_home_dir", "home_success", "home_failure"), classes => always("home_methods_run"); "any" usebundle => user_has_shell("johndoe", "/bin/csh", "shell_success", "shell_failure"), classes => always("shell_methods_run"); "any" usebundle => user_has_description("johndoe", "Good user", "desc_success", "desc_failure"), classes => always("desc_methods_run"); !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(init.hash)", "hash_success", "hash_failure"), classes => always("hash_methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "Wrong0P4SSW0RD", "hash_failure", "hash_success"), classes => always("hash_methods_run"); classes: "ready" and => { "uid_methods_run", "pgroup_methods_run", "sgroup_methods_run", "not_sgroup_methods_run", "home_methods_run", "shell_methods_run", "desc_methods_run", "hash_methods_run" }; !windows:: # Note the secondary group classes here. Windows treats primary and secondary groups the same, # and hence that test is invalid there. "unix_ok" and => { "uid_success", "!uid_failure", "shell_success", "!shell_failure", "not_sgroup_success", "!not_sgroup_failure", }; windows:: "unix_ok" expression => "any"; any:: "ok" and => { "pgroup_success", "!pgroup_failure", "sgroup_success", "!sgroup_failure", "hash_success", "!hash_failure", "home_success", "!home_failure", "desc_success", "!desc_failure", "unix_ok" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_uid.cf0000644000175100017510000000255112243421446025176 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a specific uid. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; files: "$(G.testfile)" delete => init_delete; } body delete init_delete { rmdirs => "false"; } ####################################################### body perms test_perms_body { owners => { "johndoe" }; } bundle agent test { users: "johndoe" policy => "present", uid => "9999"; files: "$(G.testfile)" create => "true", perms => test_perms_body; } ####################################################### body perms check_perms_body { owners => { "9999" }; } body classes check_classes_body { promise_repaired => { "not_ok" }; promise_kept => { "ok" }; } bundle agent check { files: "$(G.testfile)" perms => check_perms_body, classes => check_classes_body; reports: (ok.!not_ok)|windows:: "$(this.promise_filename) Pass"; (!ok|not_ok).!windows:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_many_attributes.cf0000644000175100017510000000544012400110676027622 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with many attributes. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { vars: "desc_string" string => "This description should make the CFEngine test pass"; aix:: # AIX only allows certain shells. "shell" string => "/bin/csh"; !aix:: "shell" string => "$(G.echo)"; users: "johndoe" policy => "present", uid => "9876", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, home_dir => "/home/user-johndoe", shell => "$(shell)", description => "$(desc_string)"; } ####################################################### bundle agent check { methods: "any" usebundle => remove_stale_groups; methods: "any" usebundle => user_has_uid("johndoe", "9876", "uid_success", "uid_failure"), classes => always("uid_methods_run"); "any" usebundle => user_is_in_primary_group("johndoe", "$(user_tests.group1)", "pgroup_success", "pgroup_failure"), classes => always("pgroup_methods_run"); "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group2)", "sgroup_success", "sgroup_failure"), classes => always("sgroup_methods_run"); "any" usebundle => user_has_home_dir("johndoe", "/home/user-johndoe", "home_success", "home_failure"), classes => always("home_methods_run"); "any" usebundle => user_has_shell("johndoe", "$(test.shell)", "shell_success", "shell_failure"), classes => always("shell_methods_run"); "any" usebundle => user_has_description("johndoe", "$(test.desc_string)", "desc_success", "desc_failure"), classes => always("desc_methods_run"); classes: "ready" and => { "uid_methods_run", "pgroup_methods_run", "sgroup_methods_run", "home_methods_run", "shell_methods_run", "desc_methods_run" }; !windows:: "unix_ok" and => { "uid_success", "!uid_failure", "shell_success", "!shell_failure", }; windows:: "unix_ok" expression => "any"; any:: "ok" and => { "pgroup_success", "!pgroup_failure", "sgroup_success", "!sgroup_failure", "home_success", "!home_failure", "desc_success", "!desc_failure", "unix_ok" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/home_bundle_with_new_user_and_no_inherit.cf0000644000175100017510000000254212243421446031777 0ustar00a10038a1003800000000000000####################################################### # # Test home_bundle when adding a new user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { classes: "should_not_prevent_edits" expression => "any"; users: "johndoe" policy => "present", home_bundle => home_bundle("/home/johndoe"), home_bundle_inherit => "false"; } bundle agent home_bundle(x) { files: # Class selector should have no effect since we're not supposed to inherit classes. !should_not_prevent_edits:: "$(G.testfile)" create => "true", edit_line => home_edit("$(x)"); } bundle edit_line home_edit(x) { insert_lines: "$(x)"; } ####################################################### bundle agent check { classes: "ok" not => strcmp("0", countlinesmatching("/home/johndoe", "$(G.testfile)")); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/password_with_no_format.cf0000644000175100017510000000304712400110676026451 0ustar00a10038a1003800000000000000####################################################### # # Test missing password format # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: # "j0hnd0e" "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => init_password; } body password init_password { !windows:: format => "hash"; data => "$(init.hash)"; windows:: format => "plaintext"; data => "Old0P4SSW0RD"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", password => test_password; } body password test_password { data => "New0P4SSW0RD"; } ####################################################### bundle agent check { methods: # Make sure it is the same as before. !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(init.hash)", "success", "failure"), classes => always("methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "Old0P4SSW0RD", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/promise_outcomes.cf0000644000175100017510000001523012412512360025100 0ustar00a10038a1003800000000000000####################################################### # # Test that promise outcomes are set correctly. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { meta: # Something in the Solaris 10/11 chroot test environment makes it impossible # to test matching passwords, the pam module always returns error. # This should not happen in a production system though. # Since the error is not on our part, and likely unsolvable, we set # Redmine to zero. However, it would be nice to know if the problem ever # goes away, so using soft_fail. "test_soft_fail" string => "sunos_5_10|sunos_5_11", meta => { "redmine0" }; # AIX doesn't like long names (> 8 chars), so keep them short. # a = absent # p = present # t = attributes # w = password # l = locked # r = repair users: "akeep" policy => "absent"; "arepair" policy => "present"; "pkeep" policy => "present"; "prepair" policy => "absent"; "tkeep" policy => "present", uid => "9878", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, shell => "/bin/csh", description => "Description"; "trepair" policy => "present", uid => "9877", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, shell => "/bin/csh", description => "Description"; "wkeep" policy => "present", password => init_password; "wrepair" policy => "present", password => init_password; "lkeep" policy => "locked"; "lr_byadd" policy => "absent"; "lr_bymod" policy => "present"; } body password init_password { format => "plaintext"; data => "Init0P4SSW0RD"; } ####################################################### bundle agent test { users: !ok:: "akeep" classes => set_classes_kept_repaired("absent_keep", "not_absent_keep"), policy => "absent"; "arepair" classes => set_classes_kept_repaired("not_absent_repair", "absent_repair"), policy => "absent"; "pkeep" classes => set_classes_kept_repaired("present_keep", "not_present_keep"), policy => "present"; "prepair" classes => set_classes_kept_repaired("not_present_repair", "present_repair"), policy => "present"; "tkeep" classes => set_classes_kept_repaired("attributes_keep", "not_attributes_keep"), policy => "present", uid => "9878", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, shell => "/bin/csh", description => "Description"; "trepair" classes => set_classes_kept_repaired("not_attributes_repair", "attributes_repair"), policy => "present", uid => "9877", group_primary => "$(user_tests.group1)", groups_secondary => { }, shell => "/bin/ksh", description => "Description"; "wkeep" classes => set_classes_kept_repaired("password_keep", "not_password_keep"), policy => "present", password => init_password; "wrepair" classes => set_classes_kept_repaired("not_password_repair", "password_repair"), policy => "present", password => test_password; "lkeep" classes => set_classes_kept_repaired("locked_keep", "not_locked_keep"), policy => "locked"; "lr_byadd" classes => set_classes_kept_repaired("not_locked_repair_by_add", "locked_repair_by_add"), policy => "locked"; "lr_bymod" classes => set_classes_kept_repaired("not_locked_repair_by_mod", "locked_repair_by_mod"), policy => "locked"; classes: "and_ok" and => { "absent_keep", "absent_repair", "present_keep", "present_repair", "attributes_keep", "attributes_repair", "password_keep", "password_repair", "locked_keep", "locked_repair_by_add", "locked_repair_by_mod" }; "not_ok" or => { "not_absent_keep", "not_absent_repair", "not_present_keep", "not_present_repair", "not_attributes_keep", "not_attributes_repair", "not_password_keep", "not_password_repair", "not_locked_keep", "not_locked_repair_by_add", "not_locked_repair_by_mod" }; "ok" and => { "and_ok", "!not_ok" }; "fail" or => { "!and_ok", "not_ok" }; reports: !absent_keep.DEBUG:: "absent_keep is NOT set, but should be"; !absent_repair.DEBUG:: "absent_repair is NOT set, but should be"; !present_keep.DEBUG:: "present_keep is NOT set, but should be"; !present_repair.DEBUG:: "present_repair is NOT set, but should be"; !attributes_keep.DEBUG:: "attributes_keep is NOT set, but should be"; !attributes_repair.DEBUG:: "attributes_repair is NOT set, but should be"; !password_keep.DEBUG:: "password_keep is NOT set, but should be"; !password_repair.DEBUG:: "password_repair is NOT set, but should be"; !locked_keep.DEBUG:: "locked_keep is NOT set, but should be"; !locked_repair_by_add.DEBUG:: "locked_repair_by_add is NOT set, but should be"; !locked_repair_by_mod.DEBUG:: "locked_repair_by_mod is NOT set, but should be"; not_absent_keep.DEBUG:: "not_absent_keep is SET, but shouldn't be"; not_absent_repair.DEBUG:: "not_absent_repair is SET, but shouldn't be"; not_present_keep.DEBUG:: "not_present_keep is SET, but shouldn't be"; not_present_repair.DEBUG:: "not_present_repair is SET, but shouldn't be"; not_attributes_keep.DEBUG:: "not_attributes_keep is SET, but shouldn't be"; not_attributes_repair.DEBUG:: "not_attributes_repair is SET, but shouldn't be"; not_password_keep.DEBUG:: "not_password_keep is SET, but shouldn't be"; not_password_repair.DEBUG:: "not_password_repair is SET, but shouldn't be"; not_locked_keep.DEBUG:: "not_locked_keep is SET, but shouldn't be"; not_locked_repair_by_add.DEBUG:: "not_locked_repair_by_add is SET, but shouldn't be"; not_locked_repair_by_mod.DEBUG:: "not_locked_repair_by_mod is SET, but shouldn't be"; ok:: "$(this.promise_filename) Pass"; fail|!ok:: "$(this.promise_filename) FAIL"; } body password test_password { format => "plaintext"; data => "Test0P4SSW0RD"; } body classes set_classes_kept_repaired(x, y) { promise_kept => { "$(x)" }; promise_repaired => { "$(y)" }; } ####################################################### bundle agent check { } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_shell.cf0000644000175100017510000000324612400110676025521 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a specific shell. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub", "disable_sudo_tty_requirement.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; cache_system_functions => "no"; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; methods: "any" usebundle => disable_sudo_tty_requirement; } ####################################################### bundle agent test { vars: aix:: # AIX only allows certain shells. "shell" string => "/bin/csh"; !aix:: "shell" string => "$(G.cat)"; users: "johndoe" policy => "present", shell => "$(shell)"; } ####################################################### bundle agent check { vars: "currentdir" string => dirname("$(this.promise_filename)"); classes: !windows.!aix:: "ok" expression => regcmp(".*Succeeded.*", execresult("sudo su johndoe $(currentdir)$(const.dirsep)add_user_with_shell.txt", "useshell")); methods: aix:: "any" usebundle => user_has_shell("johndoe", "$(test.shell)", "shell_success", "shell_failure"), classes => always("shell_methods_run"); classes: aix:: "ok" and => { "shell_success", "!shell_failure" }; reports: ok|windows:: "$(this.promise_filename) Pass"; !ok.!windows:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_hashed_password.cf0000644000175100017510000000242012400110676027561 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => test_password; } body password test_password { format => "hash"; data => "$(test.hash)"; } ####################################################### bundle agent check { methods: "any" usebundle => user_has_password_hash("johndoe", "$(test.hash)", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: # Password hash unsupported on Windows. (ok.ready)|windows:: "$(this.promise_filename) Pass"; (!ok.ready).!windows:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_password.cf0000644000175100017510000000323412400110676026251 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", password => test_password; } body password test_password { format => "plaintext"; data => "J0hnd0eX"; } ####################################################### bundle agent check { methods: !windows:: "any" usebundle => user_get_password_hash("johndoe"), classes => always("methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "J0hnd0eX", "pw_ok", "pw_fail"), classes => always("methods_run"); any:: "any" usebundle => user_does_not_need_password_update("johndoe", "no_pw_update_ok", "no_pw_update_fail"); classes: "ready" expression => "methods_run"; !windows:: # Make sure the password field has grown to more than a few characters. "pw_ok" expression => regcmp("^[^:][^:][^:][^:][^:][^:][^:][^:][^:][^:].*", "$(user_get_password_hash.hash)"); any:: "ok" and => { "pw_ok", "!pw_fail", "no_pw_update_ok", "!no_pw_update_fail" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_many_empty_attributes.cf0000644000175100017510000000331612400110676031040 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with many empty attributes. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", group_primary => "", groups_secondary => { }, description => "", classes => if_ok("promise_ok"); } ####################################################### bundle agent check { methods: aix:: # AIX forcibly puts a user in the staff group, even if no group is specified. "any" usebundle => user_is_in_secondary_group("johndoe", "staff", "sgroup_success", "sgroup_failure"), classes => always("sgroup_methods_run"); !aix:: "any" usebundle => user_is_in_any_secondary_group("johndoe", "sgroup_failure", "sgroup_success"), classes => always("sgroup_methods_run"); any:: "any" usebundle => user_has_description("johndoe", "", "desc_success", "desc_failure"), classes => always("desc_methods_run"); classes: "ready" and => { "sgroup_methods_run", "desc_methods_run" }; "ok" and => { "sgroup_success", "!sgroup_failure", "desc_success", "!desc_failure", "promise_ok" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_several_secondary_groups.cf0000644000175100017510000000515612352022221031515 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with several secondary groups. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub", "disable_sudo_tty_requirement.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### body perms init_perms_body_bin { groups => { "$(user_tests.group1)" }; mode => "664"; } body perms init_perms_body_sys { groups => { "$(user_tests.group2)" }; mode => "664"; } bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; files: "$(G.testfile)" create => "true", perms => init_perms_body_bin; "$(G.testfile).2" create => "true", perms => init_perms_body_sys; methods: "any" usebundle => disable_sudo_tty_requirement; } ####################################################### body contain test_contain_body { useshell => "useshell"; } bundle agent test { users: "johndoe" policy => "present", groups_secondary => { "$(user_tests.group1)", "$(user_tests.group2)" }; commands: !windows:: "sudo -u johndoe /bin/sh -c '$(G.echo) Succeeded > $(G.testfile)'" contain => test_contain_body; "sudo -u johndoe /bin/sh -c '$(G.echo) Succeeded > $(G.testfile).2'" contain => test_contain_body; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; methods: "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group1)", "bin_success", "bin_failure"), classes => always("bin_methods_run"); "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group2)", "sys_success", "sys_failure"), classes => always("sys_methods_run"); classes: !windows:: "1_ok" not => strcmp("0", countlinesmatching("Succeeded", "$(G.testfile)")); "2_ok" not => strcmp("0", countlinesmatching("Succeeded", "$(G.testfile).2")); classes: "ready" and => { "bin_methods_run", "sys_methods_run" }; !windows:: "ok" and => { "bin_success", "!bin_failure", "sys_success", "!sys_failure", "1_ok", "2_ok" }; windows:: "ok" and => { "bin_success", "!bin_failure", "sys_success", "!sys_failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_shell.txt0000644000175100017510000000003312243421446025744 0ustar00a10038a1003800000000000000#!/bin/sh exit 0 Succeeded cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_locked.cf0000644000175100017510000000202212332665147024623 0ustar00a10038a1003800000000000000####################################################### # # Test adding a which is locked. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { users: "johndoe" policy => "locked"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_locked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/home_bundle_with_existing_user.cf0000644000175100017510000000213312243421446027774 0ustar00a10038a1003800000000000000####################################################### # # Test home_bundle when modifying an existing user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", home_bundle => home_bundle("/home/johndoe"); } bundle agent home_bundle(x) { files: "$(G.testfile)" create => "true", edit_line => home_edit("$(x)"); } bundle edit_line home_edit(x) { insert_lines: "$(x)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("0", countlinesmatching("/home/johndoe", "$(G.testfile)")); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/remove_user_warn.cf0000644000175100017510000000206512332665147025105 0ustar00a10038a1003800000000000000####################################################### # # Test warning about removing a user # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { users: "johndoe" action => test_action, policy => "absent"; } body action test_action { action_policy => "warn"; } ####################################################### bundle agent check { methods: "any" usebundle => user_exists("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/home_bundle_with_new_user_and_default_inherit.cf0000644000175100017510000000247412243421446033013 0ustar00a10038a1003800000000000000####################################################### # # Test home_bundle when adding a new user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { classes: "should_not_prevent_edits" expression => "any"; users: "johndoe" policy => "present", home_bundle => home_bundle("/home/johndoe"); } bundle agent home_bundle(x) { files: # Class selector should have no effect since we're not supposed to inherit classes. !should_not_prevent_edits:: "$(G.testfile)" create => "true", edit_line => home_edit("$(x)"); } bundle edit_line home_edit(x) { insert_lines: "$(x)"; } ####################################################### bundle agent check { classes: "ok" not => strcmp("0", countlinesmatching("/home/johndoe", "$(G.testfile)")); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/home_bundle_with_new_user_and_inherit.cf0000644000175100017510000000253312243421446031303 0ustar00a10038a1003800000000000000####################################################### # # Test home_bundle when adding a new user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { classes: "should_prevent_edits" expression => "any"; users: "johndoe" policy => "present", home_bundle => home_bundle("/home/johndoe"), home_bundle_inherit => "true"; } bundle agent home_bundle(x) { files: # Class selector should prevent edits since we're supposed to inherit classes. !should_prevent_edits:: "$(G.testfile)" create => "true", edit_line => home_edit("$(x)"); } bundle edit_line home_edit(x) { insert_lines: "$(x)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("0", countlinesmatching("/home/johndoe", "$(G.testfile)")); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_unlock_with_password.cf0000644000175100017510000000322712400110676030365 0ustar00a10038a1003800000000000000####################################################### # # Test unlocking a user and setting a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "locked"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => test_password; } body password test_password { !windows:: format => "hash"; data => "$(test.hash)"; windows:: format => "plaintext"; data => "Unlocked0P4SSW0RD"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_unlocked("johndoe", "unlock_success", "unlock_failure"), classes => always("unlock_methods_run"); !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(test.hash)", "hash_success", "hash_failure"), classes => always("hash_methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "Unlocked0P4SSW0RD", "hash_success", "hash_failure"), classes => always("hash_methods_run"); classes: "ready" and => { "unlock_methods_run", "hash_methods_run" }; "ok" and => { "unlock_success", "!unlock_failure", "hash_success", "!hash_failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/missing_policy.cf0000644000175100017510000000172312332665147024553 0ustar00a10038a1003800000000000000####################################################### # # Test a user promise without a policy attribute. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { users: "johndoe"; } ####################################################### bundle agent check { methods: "any" usebundle => user_exists("johndoe", "failure", "success"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/disable_sudo_tty_requirement.cf.sub0000644000175100017510000000057312352022221030250 0ustar00a10038a1003800000000000000# Disable the requiretty setting in /etc/sudoers. body file control { inputs => { "../../plucked.cf.sub" }; } bundle agent disable_sudo_tty_requirement { files: "/etc/sudoers" edit_line => comment_requiretty; } bundle edit_line comment_requiretty { replace_patterns: "^Defaults *requiretty" replace_with => value("#Defaults requiretty"); } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_with_many_empty_attributes.cf0000644000175100017510000000452512400110676031602 0ustar00a10038a1003800000000000000####################################################### # # Test modifying a user with many empty attributes. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "present", group_primary => "$(user_tests.group1)", groups_secondary => { "$(user_tests.group2)" }, description => "Description"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", group_primary => "", groups_secondary => { }, description => ""; } ####################################################### bundle agent check { methods: "any" usebundle => remove_stale_groups; methods: windows:: "any" usebundle => user_is_in_primary_group("johndoe", "$(user_tests.group1)", "pgroup_failure", "pgroup_success"), classes => always("pgroup_methods_run"); # Unix hosts cannot remove the primary group. !windows:: "any" usebundle => user_is_in_primary_group("johndoe", "$(user_tests.group1)", "pgroup_success", "pgroup_failure"), classes => always("pgroup_methods_run"); aix:: # AIX forcibly puts a user in the primary group, even if no group is specified. "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group1)", "sgroup_success", "sgroup_failure"), classes => always("sgroup_methods_run"); !aix:: "any" usebundle => user_is_in_any_secondary_group("johndoe", "sgroup_failure", "sgroup_success"), classes => always("sgroup_methods_run"); any:: "any" usebundle => user_has_description("johndoe", "", "desc_success", "desc_failure"), classes => always("desc_methods_run"); classes: "ready" and => { "pgroup_methods_run", "sgroup_methods_run", "desc_methods_run" }; "ok" and => { "pgroup_success", "!pgroup_failure", "sgroup_success", "!sgroup_failure", "desc_success", "!desc_failure", }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_description.cf0000644000175100017510000000227312332665147026750 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a description. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { vars: "desc_string" string => "This description should make the CFEngine test pass"; users: "johndoe" policy => "present", description => "$(desc_string)"; } ####################################################### bundle agent check { methods: "any" usebundle => user_has_description("johndoe", "$(test.desc_string)", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/user_queries.cf.sub0000644000175100017510000002341512412512360025013 0ustar00a10038a1003800000000000000bundle common user_tests { vars: !windows:: "group1" string => "bin"; "group2" string => "sys"; "gid1" string => "2"; "gid2" string => "3"; windows:: "group1" string => "Users"; "group2" string => "Administrators"; } bundle agent remove_stale_groups { # When we create a user and change its primary GID afterwards, its original # group may linger and cause problems later. commands: aix:: "rmgroup johndoe" contain => in_shell; !aix:: "groupdel johndoe" contain => in_shell; } bundle agent user_exists(user, true_class, false_class) { commands: !windows:: "$(G.grep) '^$(user):' /etc/passwd" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); "reg" string => escape("$(user)"); classes: windows:: "$(true_class)" expression => regcmp(".*$(reg).*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*$(reg).*", "$(output)"), scope => "namespace"; } bundle agent user_has_uid(user, uid, true_class, false_class) { commands: !windows:: "$(G.grep) '^$(user):[^:]*:$(uid):' /etc/passwd" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); reports: windows:: "Cannot check uid on Windows!"; } bundle agent user_is_in_primary_group(user, group, true_class, false_class) { vars: !windows:: "no" int => getfields("$(group):.*", "/etc/group", ":", "gid_number"); commands: !windows:: "$(G.grep) '^$(user):[^:]*:[^:]*:$(gid_number[3]):' /etc/passwd" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); methods: windows:: "redirect" usebundle => user_is_in_secondary_group("$(user)", "$(group)", "$(true_class)", "$(false_class)"); } bundle agent user_is_in_secondary_group(user, group, true_class, false_class) { commands: !windows:: "$(G.egrep) '^$(group):[^:]*:[^:]*:[^:]*,?$(user)(,|$)' /etc/group" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); "reg" string => escape("$(group)"); classes: windows:: "$(true_class)" expression => regcmp(".*Local Group Memberships *(\*[a-zA-Z0-9]* *)* *$(reg).*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*Local Group Memberships *(\*[a-zA-Z0-9]* *)* *$(reg).*", "$(output)"), scope => "namespace"; } bundle agent user_is_in_any_secondary_group(user, true_class, false_class) { commands: !windows:: "$(G.egrep) '^[^:]*:[^:]*:[^:]*:[^:]*,?$(user)(,|$)' /etc/group" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); classes: windows:: "$(true_class)" expression => regcmp(".*Local Group Memberships *\*None.*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*Local Group Memberships *\*None.*", "$(output)"), scope => "namespace"; } bundle agent user_has_home_dir(user, home_dir, true_class, false_class) { commands: !windows:: "$(G.grep) '^$(user):[^:]*:[^:]*:[^:]*:[^:]*:$(home_dir):' /etc/passwd" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); "reg" string => escape("$(home_dir)"); classes: windows:: "$(true_class)" expression => regcmp(".*Home directory *$(reg).*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*Home directory *$(reg).*", "$(output)"), scope => "namespace"; } bundle agent user_has_shell(user, shell, true_class, false_class) { commands: !windows:: "$(G.grep) '^$(user):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:$(shell)$' /etc/passwd" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); reports: windows:: "Cannot check shell on Windows!"; } bundle agent user_has_description(user, description, true_class, false_class) { commands: !windows:: "$(G.grep) '^$(user):[^:]*:[^:]*:[^:]*:$(description):' /etc/passwd" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); classes: windows:: "$(true_class)" expression => regcmp(".*Full Name *$(description).*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*Full Name *$(description).*", "$(output)"), scope => "namespace"; } bundle agent user_has_password(user, password, true_class, false_class) { reports: !windows:: "Cannot test password on Unix!"; classes: windows.has_psexec:: "$(true_class)" expression => returnszero("$(G.psexec) -u $(user) -p $(password) $(sys.cf_agent) -h", "noshell"), scope => "namespace"; "$(false_class)" not => returnszero("$(G.psexec) -u $(user) -p $(password) $(sys.cf_agent) -h", "noshell"), scope => "namespace"; reports: windows.!has_psexec:: "Need PsExec.exe tool from PSTools to test password!"; } bundle agent user_has_password_hash(user, hash, true_class, false_class) { vars: !aix:: "escaped_hash" string => escape("$(hash)"); aix:: "user_hash" string => execresult("$(this.promise_dirname)/aix_get_shadow_field.pl password $(user)", "useshell"); classes: aix:: "$(true_class)" expression => strcmp($(hash), $(user_hash)), scope => "namespace"; "$(false_class)" not => strcmp($(hash), $(user_hash)), scope => "namespace"; commands: !windows.!aix:: "$(G.grep) '^$(user):$(escaped_hash):' /etc/shadow" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); reports: windows:: "Cannot test password hash on Windows!"; } bundle agent user_get_password_hash(user) { vars: !windows.!aix:: "hash" string => execresult("$(G.grep) '^$(user):' /etc/shadow | $(G.sed) -e 's/[^:]*:\([^:]*\):.*/\1/'", "useshell"); aix:: "hash" string => execresult("$(this.promise_dirname)/aix_get_shadow_field.pl password $(user)", "useshell"); reports: windows:: "Cannot get password hash on Windows!"; } bundle agent user_is_locked(user, true_class, false_class) { vars: solaris:: # Solaris doesn't support expiry date properly (see users promise code). "expiry_date" string => ""; !solaris:: # Expiry date should be something non-empty. "expiry_date" string => "[^:]"; aix:: "user_hash" string => execresult("$(this.promise_dirname)/aix_get_shadow_field.pl password $(user)", "useshell"); classes: aix:: "$(true_class)" expression => regcmp("!.*", $(user_hash)), scope => "namespace"; "$(false_class)" not => regcmp("!.*", $(user_hash)), scope => "namespace"; commands: !windows.!aix:: # Notice the [^:] without * at the end. That field (expiry) should be *something*. "$(G.grep) '^$(user):![^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:$(expiry_date)[^:]*:' /etc/shadow" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); classes: windows:: "$(true_class)" expression => regcmp(".*Account active *No.*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*Account active *No.*", "$(output)"), scope => "namespace"; } bundle agent user_is_unlocked(user, true_class, false_class) { vars: aix:: "user_hash" string => execresult("$(this.promise_dirname)/aix_get_shadow_field.pl password $(user)", "useshell"); classes: aix:: "$(true_class)" not => regcmp("!.*", $(user_hash)), scope => "namespace"; "$(false_class)" expression => regcmp("!.*", $(user_hash)), scope => "namespace"; commands: !windows.!aix:: # Notice the field at the end. That field (expiry) should be gone or zero. "$(G.egrep) '^$(user):[^:!]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:(:|0:)' /etc/shadow" contain => no_output_shell, classes => on_success("$(true_class)", "$(false_class)"); vars: windows:: "output" string => execresult("net user $(user)", "useshell"); classes: windows:: "$(true_class)" expression => regcmp(".*Account active *Yes.*", "$(output)"), scope => "namespace"; "$(false_class)" not => regcmp(".*Account active *Yes.*", "$(output)"), scope => "namespace"; } # Some platforms add a flag that forces the user to change the password. bundle agent user_does_not_need_password_update(user, true_class, false_class) { vars: aix:: "flags" string => execresult("$(this.promise_dirname)/aix_get_shadow_field.pl flags $(user)", "useshell"); classes: aix:: "$(true_class)" not => regcmp(".*ADMCHG.*", "$(flags)"), scope => "namespace"; "$(false_class)" expression => regcmp(".*ADMCHG.*", "$(flags)"), scope => "namespace"; !aix:: "$(true_class)" expression => "any", scope => "namespace"; } body classes on_success(true_class, false_class) { promise_repaired => { "$(true_class)" }; repair_failed => { "$(false_class)" }; cancel_notkept => { "$(true_class)" }; cancel_repaired => { "$(false_class)" }; } body contain no_output_shell { no_output => "true"; useshell => "useshell"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_unlock_warn.cf0000644000175100017510000000207212332665147026450 0ustar00a10038a1003800000000000000####################################################### # # Test warning about unlocking a user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "locked"; } ####################################################### bundle agent test { users: "johndoe" action => test_action, policy => "present"; } body action test_action { action_policy => "warn"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_locked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/password_with_no_data.cf0000644000175100017510000000304412400110676026067 0ustar00a10038a1003800000000000000####################################################### # # Test missing password data # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: # "j0hnd0e" "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => init_password; } body password init_password { !windows:: format => "hash"; data => "$(init.hash)"; windows:: format => "plaintext"; data => "Old0P4SSW0RD"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", password => test_password; } body password test_password { format => "plaintext"; } ####################################################### bundle agent check { methods: # Make sure it is the same as before. !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(init.hash)", "success", "failure"), classes => always("methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "Old0P4SSW0RD", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/newly_created_account_should_not_count_as_locked.cf0000644000175100017510000000275712400110676033532 0ustar00a10038a1003800000000000000####################################################### # # Test that a newly created account does not confuse # our locking detection. This may happen because # "useradd" initially sets the password to '!'. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Delete user, then create. vars: "users[n1]" string => "johndoe"; "users[n2]" string => "johndoe"; "policies[n1]" string => "absent"; "policies[n2]" string => "present"; "iter" slist => { "n1", "n2" }; users: "$(users[$(iter)])" policy => "$(policies[$(iter)])"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "locked", password => test_password; } body password test_password { format => "hash"; data => "$(test.hash)"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_locked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/home_bundle_when_removing_user.cf0000644000175100017510000000211712243421446027760 0ustar00a10038a1003800000000000000####################################################### # # Test home_bundle when removing a user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { users: "johndoe" policy => "absent", home_bundle => home_bundle("/home/johndoe"); } bundle agent home_bundle(x) { files: "$(G.testfile)" create => "true", edit_line => home_edit("$(x)"); } bundle edit_line home_edit(x) { insert_lines: "$(x)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("0", countlinesmatching("/home/johndoe", "$(G.testfile)")); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_primary_gid.cf0000644000175100017510000000320612352022221026706 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a primary gid. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub", "disable_sudo_tty_requirement.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; files: "$(G.testfile)" delete => init_delete; methods: "any" usebundle => disable_sudo_tty_requirement; } body delete init_delete { rmdirs => "false"; } ####################################################### body contain test_contain_body { useshell => "useshell"; } bundle agent test { users: "johndoe" policy => "present", group_primary => "$(user_tests.gid1)"; commands: !windows:: "sudo -u johndoe $(G.touch) $(G.testfile)" contain => test_contain_body; } ####################################################### body perms check_perms_body { groups => { "$(user_tests.gid1)" }; } body classes check_classes_body { promise_repaired => { "not_ok" }; promise_kept => { "ok" }; } bundle agent check { methods: "any" usebundle => remove_stale_groups; files: "$(G.testfile)" perms => check_perms_body, classes => check_classes_body; reports: (ok.!not_ok)|windows:: "$(this.promise_filename) Pass"; (!ok|not_ok).!windows:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_lock.cf0000644000175100017510000000172512332665147025062 0ustar00a10038a1003800000000000000####################################################### # # Test locking a user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { users: "johndoe" policy => "locked"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_locked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_warn.cf0000644000175100017510000000214712332665147024341 0ustar00a10038a1003800000000000000####################################################### # # Test warning about adding a user # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { users: "johndoe" action => test_action, policy => "present"; } body action test_action { action_policy => "warn"; } ####################################################### bundle agent check { methods: "any" usebundle => user_exists("johndoe", "failure", "success"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_secondary_group.cf0000644000175100017510000000353312352022221027606 0ustar00a10038a1003800000000000000####################################################### # # Test adding a user with a secondary group. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub", "disable_sudo_tty_requirement.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### body perms init_perms_body { groups => { "$(user_tests.group1)" }; mode => "664"; } bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; files: "$(G.testfile)" create => "true", perms => init_perms_body; methods: "any" usebundle => disable_sudo_tty_requirement; } ####################################################### body contain test_contain_body { useshell => "useshell"; } bundle agent test { users: "johndoe" policy => "present", groups_secondary => { "$(user_tests.group1)" }; commands: !windows:: "sudo -u johndoe /bin/sh -c '$(G.echo) Succeeded > $(G.testfile)'" contain => test_contain_body; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_in_secondary_group("johndoe", "$(user_tests.group1)", "success", "failure"), classes => always("methods_run"); classes: !windows:: "content_ok" not => strcmp("0", countlinesmatching("Succeeded", "$(G.testfile)")); classes: "ready" expression => "methods_run"; !windows:: "ok" and => { "success", "!failure", "content_ok" }; windows:: "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_with_same_password.cf0000644000175100017510000000425212412512360030015 0ustar00a10038a1003800000000000000####################################################### # # Test modifying a user with a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { meta: # Something in the Solaris 10/11 chroot test environment makes it impossible # to test matching passwords, the pam module always returns error. # This should not happen in a production system though. # Since the error is not on our part, and likely unsolvable, we set # Redmine to zero. However, it would be nice to know if the problem ever # goes away, so using soft_fail. "test_soft_fail" string => "sunos_5_10|sunos_5_11", meta => { "redmine0" }; vars: # This is the same password as the plaintext one further down. "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => init_password; } body password init_password { !windows:: format => "hash"; data => "$(init.hash)"; windows:: format => "plaintext"; data => "J0hnd0eX"; } ####################################################### bundle agent test { users: "johndoe" policy => "present", password => test_password, classes => if_repaired("kept_failed"); } body password test_password { format => "plaintext"; data => "J0hnd0eX"; } ####################################################### bundle agent check { methods: # Make sure it is the same as before. !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(init.hash)", "success", "failure"), classes => always("methods_run"); windows:: "any" usebundle => user_has_password("johndoe", "J0hnd0eX", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure", "!kept_failed" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/remove_user.cf0000644000175100017510000000172212332665147024055 0ustar00a10038a1003800000000000000####################################################### # # Test removing a user # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present"; } ####################################################### bundle agent test { users: "johndoe" policy => "absent"; } ####################################################### bundle agent check { methods: "any" usebundle => user_exists("johndoe", "failure", "success"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_unlock.cf0000644000175100017510000000173112332665147025422 0ustar00a10038a1003800000000000000####################################################### # # Test unlocking a user. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "locked"; } ####################################################### bundle agent test { users: "johndoe" policy => "present"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_unlocked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_with_many_attributes_warn.cf0000644000175100017510000000300412400110676030643 0ustar00a10038a1003800000000000000####################################################### # # Test warning about adding a user with many attributes. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { # Remove him first, should he already be present. users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { vars: "desc_string" string => "This description should make the CFEngine test pass"; users: "johndoe" action => test_action, policy => "present", uid => "9876", group_primary => "$(user_tests.gid1)", groups_secondary => { "$(user_tests.group2)" }, password => test_password, shell => "/bin/csh", description => "$(desc_string)"; } body action test_action { action_policy => "warn"; } body password test_password { format => "hash"; data => "dTloMVpjYt1w2"; } ####################################################### bundle agent check { methods: "any" usebundle => user_exists("johndoe", "failure", "success"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/modify_user_with_hashed_password.cf0000644000175100017510000000300712400110676030322 0ustar00a10038a1003800000000000000####################################################### # # Test modifying a user with a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "present", password => init_password; } body password init_password { format => "plaintext"; data => "Bad0P4SSW0RD"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "present", password => test_password; } body password test_password { format => "hash"; data => "$(test.hash)"; } ####################################################### bundle agent check { methods: !windows:: "any" usebundle => user_has_password_hash("johndoe", "$(test.hash)", "success", "failure"), classes => always("methods_run"); windows:: # Hash not supported on Windows. Make sure it is the same as before. "any" usebundle => user_has_password("johndoe", "Bad0P4SSW0RD", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/17_users/unsafe/add_user_locked_with_password.cf0000644000175100017510000000222212400110676027566 0ustar00a10038a1003800000000000000####################################################### # # Test adding a locked a user and setting a password. # ####################################################### body common control { inputs => { "../../default.cf.sub", "user_queries.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { users: "johndoe" policy => "absent"; } ####################################################### bundle agent test { vars: "hash" string => "dTloMVpjYt1w2"; users: "johndoe" policy => "locked", password => test_password; } body password test_password { format => "hash"; data => "$(test.hash)"; } ####################################################### bundle agent check { methods: "any" usebundle => user_is_locked("johndoe", "success", "failure"), classes => always("methods_run"); classes: "ready" expression => "methods_run"; "ok" and => { "success", "!failure" }; reports: ok.ready:: "$(this.promise_filename) Pass"; !ok.ready:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/11_databases/0000755000175100017510000000000012236160673020502 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/11_databases/00_syntax/0000755000175100017510000000000012243421446022323 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/11_databases/00_syntax/missing_database_operation.cf0000644000175100017510000000140112243421446030206 0ustar00a10038a1003800000000000000# Test that missing database_operation does not segfault (Mantis #1046) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { databases: "foobar" database_type => "sql", database_server => myserver; } body database_server myserver { db_server_owner => "owner"; db_server_password => "password"; db_server_host => "localhost"; db_server_type => "postgres"; db_server_connection_db => "postgres"; } bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } ### PROJECT_ID: core ### CATEGORY_ID: 33 cfengine-3.6.2/tests/acceptance/14_reports/0000755000175100017510000000000012236160673020254 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/14_reports/00_output/0000755000175100017510000000000012412221023022072 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/14_reports/00_output/001.cf.sub.in0000644000175100017510000000002512236160673024117 0ustar00a10038a1003800000000000000firstline secondline cfengine-3.6.2/tests/acceptance/14_reports/00_output/report_array.cf0000644000175100017510000000170212316547775025151 0ustar00a10038a1003800000000000000# Check that reports are printed just once (Redmine#3446 https://cfengine.com/dev/issues/3446) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "noshell"); } bundle agent check { classes: "ok1" expression => regcmp(".*9b70d955f7e126bc082e4a99eb2b3d08e4ebc29a.*", "$(test.subout)"); "ok2" expression => regcmp(".*18a307169ff8a691607846c8a19c361a37695773.*", "$(test.subout)"); "ok3" expression => regcmp(".*79815eefd0b619c6b875edf68adc7ef0e00c1ad3.*", "$(test.subout)"); "ok" and => { "ok1", "ok2", "ok3" }; reports: DEBUG:: "Output from subtest: $(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 2 cfengine-3.6.2/tests/acceptance/14_reports/00_output/002.cf.sub0000644000175100017510000000061412243421446023513 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #2936: Check that list variables under reserved scope expand # as they should in reports promises. # ############################################################################## body common control { bundlesequence => {"example"}; } bundle agent example { reports: "$(sys.hardware_addresses)"; } cfengine-3.6.2/tests/acceptance/14_reports/00_output/report_array.cf.sub0000644000175100017510000000066212316547775025745 0ustar00a10038a1003800000000000000body common control { bundlesequence => { set, run }; } bundle agent set { vars: "array[key_scalar]" string => "9b70d955f7e126bc082e4a99eb2b3d08e4ebc29a"; "array[key_slist]" slist => { "18a307169ff8a691607846c8a19c361a37695773", "79815eefd0b619c6b875edf68adc7ef0e00c1ad3" }; "keys" slist => getindices(array); } bundle agent run { reports: "key = $(set.keys), value = $(set.array[$(set.keys)])"; } cfengine-3.6.2/tests/acceptance/14_reports/00_output/002.cf0000644000175100017510000000206512412221023022710 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #2936: Check that list variables under reserved scope expand # as they should in reports promises. # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { meta: "test_suppress_fail" string => "hpux|windows|sunos_5_11", meta => { "redmine4745", "redmine4963" }; vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "noshell"); } bundle agent check { # If the output contains the string "$(sys.hardware_addresses)" then we # failed to expand the variable! classes: "ok" not => regcmp(".*hardware_addresses.*", "$(test.subout)"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 2 cfengine-3.6.2/tests/acceptance/14_reports/00_output/staging/0000755000175100017510000000000012316547775023562 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/14_reports/00_output/staging/report_in_common_bundle.cf0000644000175100017510000000136312316547775031001 0ustar00a10038a1003800000000000000# Check that reports are printed from common bundles (Redmine#3848 https://cfengine.com/dev/issues/3848) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -b runme -Kf $(this.promise_filename).sub", "noshell"); } bundle agent check { classes: "ok" expression => regcmp(".*rhino_9d85a7796746fb3e2e2ac95f74e4b981564803de.*", "$(test.subout)"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 2 cfengine-3.6.2/tests/acceptance/14_reports/00_output/staging/report_in_common_bundle.cf.sub0000644000175100017510000000020412316547775031562 0ustar00a10038a1003800000000000000bundle agent runme { } bundle common report { reports: "$(this.bundle): rhino_9d85a7796746fb3e2e2ac95f74e4b981564803de"; } cfengine-3.6.2/tests/acceptance/14_reports/00_output/001.cf0000644000175100017510000000206112243421446022720 0ustar00a10038a1003800000000000000####################################################### # # Test that printfile honors number_of_lines constraint (Issue 686) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "noshell"); } ####################################################### bundle agent check { classes: "firstline" expression => regcmp(".*firstline.*", "$(test.subout)"); "nosecondline" not => regcmp(".*secondline.*", "$(test.subout)"); "ok" and => { "firstline", "nosecondline" }; reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 2 cfengine-3.6.2/tests/acceptance/14_reports/00_output/001.cf.sub0000644000175100017510000000045412316547775023533 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "test" }; version => "1.0"; } bundle agent test { reports: cfengine_3:: "doesnotmatter" printfile => p; } body printfile p { file_to_print => "$(this.promise_filename).in"; number_of_lines => "1"; } cfengine-3.6.2/tests/acceptance/14_reports/00_output/report_once.cf0000644000175100017510000000131512243421446024740 0ustar00a10038a1003800000000000000# Check that reports are printed just once (Redmine#3446 https://cfengine.com/dev/issues/3446) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "noshell"); } bundle agent check { # If the output contains the string "ONCE" twice then we fail classes: "ok" not => regcmp(".*ONCE.*ONCE.*", "$(test.subout)"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 2 cfengine-3.6.2/tests/acceptance/14_reports/00_output/report_once.cf.sub0000644000175100017510000000024412243421446025530 0ustar00a10038a1003800000000000000body common control { bundlesequence => { run }; } bundle agent run { reports: "should be printed just ONCE"; "should be printed just ONCE"; } cfengine-3.6.2/tests/acceptance/Makefile.in0000644000175100017510000011712212412324464020317 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) @BUILTIN_EXTENSIONS_FALSE@am__append_1 = mock_package_manager @HAVE_LIBXML2_TRUE@am__append_2 = xml-c14nize @HAVE_LIBXML2_FALSE@am__append_3 = LIBXML2_TESTS=0 subdir = tests/acceptance DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libmock_package_manager_la_DEPENDENCIES = \ ../../libpromises/libpromises.la am_libmock_package_manager_la_OBJECTS = mock_package_manager.lo libmock_package_manager_la_OBJECTS = \ $(am_libmock_package_manager_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = @BUILTIN_EXTENSIONS_FALSE@am__EXEEXT_1 = \ @BUILTIN_EXTENSIONS_FALSE@ mock_package_manager$(EXEEXT) @HAVE_LIBXML2_TRUE@am__EXEEXT_2 = xml-c14nize$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_mock_package_manager_OBJECTS = mock_package_manager_OBJECTS = $(am_mock_package_manager_OBJECTS) @BUILTIN_EXTENSIONS_FALSE@mock_package_manager_DEPENDENCIES = \ @BUILTIN_EXTENSIONS_FALSE@ libmock_package_manager.la xml_c14nize_SOURCES = xml-c14nize.c xml_c14nize_OBJECTS = xml_c14nize-xml-c14nize.$(OBJEXT) am__DEPENDENCIES_1 = @HAVE_LIBXML2_TRUE@xml_c14nize_DEPENDENCIES = \ @HAVE_LIBXML2_TRUE@ ../../libutils/libutils.la \ @HAVE_LIBXML2_TRUE@ $(am__DEPENDENCIES_1) xml_c14nize_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(xml_c14nize_CFLAGS) \ $(CFLAGS) $(xml_c14nize_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libmock_package_manager_la_SOURCES) \ $(mock_package_manager_SOURCES) xml-c14nize.c DIST_SOURCES = $(libmock_package_manager_la_SOURCES) \ $(mock_package_manager_SOURCES) xml-c14nize.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ AM_CPPFLAGS = $(ENTERPRISE_CFLAGS) \ -I$(top_srcdir)/libpromises \ -I$(top_srcdir)/libutils \ -I$(top_srcdir)/libcfnet \ $(OPENSSL_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) noinst_LTLIBRARIES = libmock_package_manager.la libmock_package_manager_la_SOURCES = mock_package_manager.c libmock_package_manager_la_LIBADD = ../../libpromises/libpromises.la @BUILTIN_EXTENSIONS_FALSE@mock_package_manager_SOURCES = @BUILTIN_EXTENSIONS_FALSE@mock_package_manager_LDADD = libmock_package_manager.la @HAVE_LIBXML2_TRUE@xml_c14nize_CPPFLAGS = \ @HAVE_LIBXML2_TRUE@ -I$(top_srcdir)/libpromises \ @HAVE_LIBXML2_TRUE@ -I$(srcdir)/../../libutils \ @HAVE_LIBXML2_TRUE@ $(LIBXML2_CPPFLAGS) @HAVE_LIBXML2_TRUE@xml_c14nize_CFLAGS = $(LIBXML2_CFLAGS) @HAVE_LIBXML2_TRUE@xml_c14nize_LDFLAGS = $(LIBXML2_LDFLAGS) @HAVE_LIBXML2_TRUE@xml_c14nize_LDADD = ../../libutils/libutils.la \ @HAVE_LIBXML2_TRUE@ $(LIBXML2_LIBS) EXTRA_DIST = default.cf.sub dcs.cf.sub plucked.cf.sub testall dummy_etc TESTS = testall TESTS_ENVIRONMENT = env AGENT=`pwd`/../../cf-agent/cf-agent \ CF_PROMISES=`pwd`/../../cf-promises/cf-promises \ CF_SERVERD=`pwd`/../../cf-serverd/cf-serverd \ CF_KEY=`pwd`/../../cf-key/cf-key \ MOCK_PACKAGE_MANAGER=`pwd`/mock_package_manager \ $(am__append_3) CLEANFILES = *.gcno *.gcda all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(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) --foreign tests/acceptance/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/acceptance/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libmock_package_manager.la: $(libmock_package_manager_la_OBJECTS) $(libmock_package_manager_la_DEPENDENCIES) $(EXTRA_libmock_package_manager_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libmock_package_manager_la_OBJECTS) $(libmock_package_manager_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list mock_package_manager$(EXEEXT): $(mock_package_manager_OBJECTS) $(mock_package_manager_DEPENDENCIES) $(EXTRA_mock_package_manager_DEPENDENCIES) @rm -f mock_package_manager$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mock_package_manager_OBJECTS) $(mock_package_manager_LDADD) $(LIBS) xml-c14nize$(EXEEXT): $(xml_c14nize_OBJECTS) $(xml_c14nize_DEPENDENCIES) $(EXTRA_xml_c14nize_DEPENDENCIES) @rm -f xml-c14nize$(EXEEXT) $(AM_V_CCLD)$(xml_c14nize_LINK) $(xml_c14nize_OBJECTS) $(xml_c14nize_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mock_package_manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_c14nize-xml-c14nize.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< xml_c14nize-xml-c14nize.o: xml-c14nize.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_c14nize_CPPFLAGS) $(CPPFLAGS) $(xml_c14nize_CFLAGS) $(CFLAGS) -MT xml_c14nize-xml-c14nize.o -MD -MP -MF $(DEPDIR)/xml_c14nize-xml-c14nize.Tpo -c -o xml_c14nize-xml-c14nize.o `test -f 'xml-c14nize.c' || echo '$(srcdir)/'`xml-c14nize.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_c14nize-xml-c14nize.Tpo $(DEPDIR)/xml_c14nize-xml-c14nize.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xml-c14nize.c' object='xml_c14nize-xml-c14nize.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_c14nize_CPPFLAGS) $(CPPFLAGS) $(xml_c14nize_CFLAGS) $(CFLAGS) -c -o xml_c14nize-xml-c14nize.o `test -f 'xml-c14nize.c' || echo '$(srcdir)/'`xml-c14nize.c xml_c14nize-xml-c14nize.obj: xml-c14nize.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_c14nize_CPPFLAGS) $(CPPFLAGS) $(xml_c14nize_CFLAGS) $(CFLAGS) -MT xml_c14nize-xml-c14nize.obj -MD -MP -MF $(DEPDIR)/xml_c14nize-xml-c14nize.Tpo -c -o xml_c14nize-xml-c14nize.obj `if test -f 'xml-c14nize.c'; then $(CYGPATH_W) 'xml-c14nize.c'; else $(CYGPATH_W) '$(srcdir)/xml-c14nize.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/xml_c14nize-xml-c14nize.Tpo $(DEPDIR)/xml_c14nize-xml-c14nize.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xml-c14nize.c' object='xml_c14nize-xml-c14nize.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(xml_c14nize_CPPFLAGS) $(CPPFLAGS) $(xml_c14nize_CFLAGS) $(CFLAGS) -c -o xml_c14nize-xml-c14nize.obj `if test -f 'xml-c14nize.c'; then $(CYGPATH_W) 'xml-c14nize.c'; else $(CYGPATH_W) '$(srcdir)/xml-c14nize.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? testall.log: testall @p='testall'; \ b='testall'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) 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 $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-noinstPROGRAMS 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: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am dist-hook \ 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 \ recheck tags tags-am uninstall uninstall-am dist-hook: cd $(srcdir); tar -c -f - [0-9]* | tar -x -C $(abspath $(distdir)) -f - chmod -R go-w $(distdir) pluck: echo '### This is an auto-generated file, see Makefile.am and `make pluck` ###' > plucked.cf.sub ../../contrib/cf-locate/cf-locate -f -p '( if_|warn_only|INI_section|kept_successful_command|edit_line|set_user_field|set_variable_values\(|edit_field|set_line_based|location|replace_with|_cp|_dcp|empty|shell|immediate|perms| m\b|recurse|tidy| all|classes_generic| start|always|^value|edit_field line|insert_lines|(link|copy)from| file_mustache| (file|dir)_(copy|tidy|sync|make|empty|link|hardlink))' ../../../masterfiles/lib/3.6 >> plucked.cf.sub # 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: cfengine-3.6.2/tests/acceptance/21_methods/0000755000175100017510000000000012400110676020206 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/21_methods/reporting/0000755000175100017510000000000012316547775022243 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/21_methods/reporting/kept.cf0000644000175100017510000000220512316547775023517 0ustar00a10038a1003800000000000000####################################################### # # Redmine#4852: test kept methods reporting # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { methods: "create" usebundle => test_create_hello; } ####################################################### bundle agent test { methods: "verify" usebundle => test_create_hello, classes => test_verify_method; reports: OK:: "OK"; FAIL:: "FAIL"; } bundle agent test_create_hello { files: "$(G.testfile)" create => "true", perms => test_m("000"), action => test_immediate; } body perms test_m(mode) { mode => $(mode); } body action test_immediate { ifelapsed => 0; } body classes test_verify_method { promise_kept => {"ok"}; } bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/21_methods/warn_only.cf0000644000175100017510000000174212400110676022534 0ustar00a10038a1003800000000000000####################################################### # # Redmine#4852: test kept methods reporting # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### body action warnonly { action_policy => "warn"; } ####################################################### bundle agent test { methods: "verify" usebundle => test_method, action => warnonly, classes => if_else("method_kept", "method_notkept"); } bundle agent test_method { reports: "unwanted sideeffect!" classes => if_else("report_kept", "report_notkept"); } bundle agent check { classes: "ok" expression => "method_notkept.!report_kept.!report_notkept"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/07_packages/0000755000175100017510000000000012352022221020317 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/800.cf0000644000175100017510000000260212243421446021153 0ustar00a10038a1003800000000000000####################################################### # Test that classes are set on individual installation (Mantis #829) ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock, classes => ok("a"); "d:e:f" package_policy => "add", package_method => mock, classes => ok("d"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes ok(classname) { promise_repaired => { "$(classname)" }; promise_kept => { "$(classname)" }; } bundle agent check { reports: a.d:: "$(this.promise_filename) Pass"; !a|!d:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/907.cf0000644000175100017510000000240312332667376021177 0ustar00a10038a1003800000000000000####################################################### # # Test no-op with with "package_repositories" works # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock; } body package_method mock { package_changes => "individual"; package_file_repositories => { "/tmp" }; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } ####################################################### bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/908.cf0000644000175100017510000000300512243421446021162 0ustar00a10038a1003800000000000000####################################################### # # Test broken list_command # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_list_command => "/nonexisting"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/test_repository/0000755000175100017510000000000012352022221023575 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repository/installed.txt0000644000175100017510000000402112352022221026312 0ustar00a10038a1003800000000000000i update-to-exact-version 1.4.3 i386 i update-to-lessorequal-version 1.4.3 i386 i update-to-lessthan-version 1.4.3 i386 i update-to-greaterorequal-version 1.4.3 i386 i update-to-greaterthan-version 1.4.3 i386 i update-to-greaterorequal-version-already-greater-installed 2.2.2 i386 i update-to-greaterthan-version-already-greater-installed 2.2.2 i386 i mismatch-update-to-exact-version 1.4.3 i386 i mismatch-update-to-lessorequal-version 1.4.3 i386 i mismatch-update-to-lessthan-version 1.4.3 i386 i mismatch-update-to-greaterorequal-version 1.4.3 i386 i mismatch-update-to-greaterthan-version 1.4.3 i386 i missing-update-to-exact-version 1.4.3 i386 i missing-update-to-lessorequal-version 1.4.3 i386 i missing-update-to-lessthan-version 1.4.3 i386 i missing-update-to-greaterorequal-version 1.4.3 i386 i missing-update-to-greaterthan-version 1.4.3 i386 i delete-exact-version 2.2.3 i386 i mismatch-delete-exact-version 2.2.3 i386 a install-exact-version-2.2.3.i386.rpm a install-greaterorequal-version-2.2.3.i386.rpm a install-greaterthan-version-2.2.3.i386.rpm a install-lessorequal-version-2.2.3.i386.rpm a install-lessthan-version-2.2.3.i386.rpm a mismatch-install-exact-version-2.2.3.i386.rpm a mismatch-install-greaterorequal-version-2.2.3.i386.rpm a mismatch-install-greaterthan-version-2.2.3.i386.rpm a mismatch-install-lessorequal-version-2.2.3.i386.rpm a mismatch-install-lessthan-version-2.2.3.i386.rpm a mismatch-update-to-exact-version-2.2.3.i386.rpm a mismatch-update-to-greaterorequal-version-2.2.3.i386.rpm a mismatch-update-to-greaterthan-version-2.2.3.i386.rpm a mismatch-update-to-lessorequal-version-2.2.3.i386.rpm a mismatch-update-to-lessthan-version-2.2.3.i386.rpm a update-to-exact-version-2.2.3.i386.rpm a update-to-greaterorequal-version-2.2.3.i386.rpm a update-to-greaterorequal-version-already-greater-installed-2.2.3.i386.rpm a update-to-greaterthan-version-2.2.3.i386.rpm a update-to-greaterthan-version-already-greater-installed-2.2.3.i386.rpm a update-to-lessorequal-version-2.2.3.i386.rpm a update-to-lessthan-version-2.2.3.i386.rpm install-greaterthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033022 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-update-to-lessorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446035114 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryupdate-to-greaterthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033256 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-install-greaterthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446034625 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-install-lessthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446034142 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryupdate-to-greaterorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033774 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorycfengine-3.6.2/tests/acceptance/07_packages/test_repository/install-exact-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446031701 0ustar00a10038a1003800000000000000install-greaterorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033540 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryinstall-lessorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033055 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-install-exact-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033425 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-update-to-lessthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446034376 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorycfengine-3.6.2/tests/acceptance/07_packages/test_repository/install-lessthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446032416 0ustar00a10038a1003800000000000000mismatch-update-to-greaterorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446035577 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryupdate-to-lessorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033311 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-update-to-exact-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446033661 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryupdate-to-greaterorequal-version-already-greater-installed-2.2.3.i386.rpm0000644000175100017510000000000012243421446041017 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryupdate-to-greaterthan-version-already-greater-installed-2.2.3.i386.rpm0000644000175100017510000000000012243421446040301 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositoryupdate-to-lessthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446032573 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-install-lessorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446034660 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-install-greaterorequal-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446035343 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorymismatch-update-to-greaterthan-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446035061 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/test_repositorycfengine-3.6.2/tests/acceptance/07_packages/test_repository/update-to-exact-version-2.2.3.i386.rpm0000644000175100017510000000000012243421446032135 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/07_packages/warn-package-delete.cf.sub0000644000175100017510000000203012236160673025233 0ustar00a10038a1003800000000000000####################################################### # # Test delete a package # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "test_warn_delete_pkg" }; version => "1.0"; } ####################################################### bundle agent test_warn_delete_pkg { packages: "bash" package_policy => "delete", package_method => mock_warn_delete_pkg, package_select => ">=", package_version => "4.2.8", package_architectures => {"x86_64"}; } body package_method mock_warn_delete_pkg { package_changes => "individual"; package_list_command => "$(G.printf) 'bash-4.2.8-x86_64'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.false)"; } cfengine-3.6.2/tests/acceptance/07_packages/900.cf0000644000175100017510000000233612243421446021160 0ustar00a10038a1003800000000000000####################################################### # # Test no-op works # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock; } body package_method mock { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } ####################################################### bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dry-run-install.cf.sub0000644000175100017510000000170712236160673024511 0ustar00a10038a1003800000000000000# Test that if the action => 'warn' is specified, no packages are installed. body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "test" }; version => "1.0"; } bundle agent test { packages: "bash" package_policy => "add", package_method => mock_do_not_install_pkg, package_select => ">=", package_version => "1.0", action => dryrun; } body action dryrun { action_policy => "warn"; } body package_method mock_do_not_install_pkg { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_installed_regex => ".*"; package_add_command => "/bin/should-not-be-called"; package_update_command => "/bin/should-not-be-called"; package_delete_command => "/bin/should-not-be-called"; package_verify_command => "/bin/should-not-be-called"; } cfengine-3.6.2/tests/acceptance/07_packages/custom-version-compare.cf0000644000175100017510000000632112352022221025254 0ustar00a10038a1003800000000000000####################################################### # Test custom version comparator ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_needs_work" string => "windows"; packages: # Test that overriding 'equal' works. Installed is 01, requested is 1. Overridden eq compares numeric values. "bash-1-amd64" package_policy => "addupdate", package_method => mock_zeroone_installed, classes => test_set_class("custom_eq_succ", "custom_eq_fail"); "bash-2-amd64" package_policy => "addupdate", package_method => mock_zeroone_installed_can_install, classes => test_set_class("custom_eq_2_succ", "custom_eq_2_fail"); } body package_method mock_zeroone_installed { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-01-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_version_less_command => "test $(v1) -lt $(v2)"; package_version_equal_command => "test $(v1) -eq $(v2)"; } body package_method mock_zeroone_installed_can_install { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-01-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_version_less_command => "test $(v1) -lt $(v2)"; package_version_equal_command => "test $(v1) -eq $(v2)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "custom_eq_succ", "!custom_eq_fail", "custom_eq_2_succ", "!custom_eq_2_fail" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/warn-package-delete.cf0000644000175100017510000000172412243421446024450 0ustar00a10038a1003800000000000000####################################################### # # Test delete a package # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -KI -f $(this.promise_filename).sub --dry-run", "useshell"); } ####################################################### bundle agent check { classes: "ok" expression => regcmp(".*Deleting.*", "$(test.subout)"); reports: # DEBUG:: # "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/902.cf0000644000175100017510000000316212352022221021145 0ustar00a10038a1003800000000000000####################################################### # # Test missing name regex fails # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_unsupported" string => "windows"; packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/has-default-no-list-architectures.cf0000644000175100017510000000440012243421446027265 0ustar00a10038a1003800000000000000# # Test matching packages with explicit default architecture set and no # architecture in list of installed packages. Should work similar to the case # there are no architectures at all. # # List of installed packages contains a single package with no architecture # specified. # body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: # # Test that package is matched by a promise with no package_architectures # constraint, as it means "any architecture" # "foobar" package_version => "1", package_policy => "addupdate", package_method => mock, classes => kept("ok_1"); # # Test that specifying proper architecture explicitly matches the package. # "foobar" package_version => "1", package_architectures => { "setun" }, package_policy => "addupdate", package_method => mock, classes => kept("ok_2"); # # Test that specifying wrong architecture explicitly does not match the package. # "foobar" package_version => "1", package_architectures => { "aldan" }, package_policy => "addupdate", package_method => mock, classes => fail("ok_3"); } body package_method mock { package_changes => "individual"; package_default_arch_command => "$(G.printf) 'setun'"; package_list_command => "$(G.printf) 'foobar-1'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([\S+])"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes kept(classname) { promise_kept => { "$(classname)" }; } body classes fail(classname) { repair_failed => { "$(classname)" }; } bundle agent check { classes: "ok" and => { "ok_1", "ok_2", "ok_3" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/903.cf0000644000175100017510000000316712352022221021153 0ustar00a10038a1003800000000000000####################################################### # # Test missing package listing fails # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_unsupported" string => "windows"; packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dependency-checks-package_verify_command.cf0000644000175100017510000000642412243421446030701 0ustar00a10038a1003800000000000000####################################################### # Test for presence of "main" attribute, given the presence of "dependent" # attributes, which do not make sense without the "main" attribute. # # main attribute: package_verify_command # dependent attributes: # package_noverify_regex # package_noverify_returncode ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "bash-1.0-amd64" package_policy => "add", package_method => mock_no_verify_command_noverify_regex, classes => test_set_class("no_verify_command_noverify_regex_succ", "no_verify_command_noverify_regex_fail"); "bash-1.0-i386" package_policy => "add", package_method => mock_no_verify_command_noverify_returncode, classes => test_set_class("no_verify_command_noverify_returncode_succ", "no_verify_command_noverify_returncode_fail"); } body package_method mock_no_verify_command_noverify_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; # package_verify_command => "$(G.true)"; package_noverify_regex => "."; } body package_method mock_no_verify_command_noverify_returncode { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; # package_verify_command => "$(G.true)"; package_noverify_returncode => "-1"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "!no_verify_command_noverify_regex_succ", "no_verify_command_noverify_regex_fail", "!no_verify_command_noverify_returncode_succ", "no_verify_command_noverify_returncode_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/904.cf0000644000175100017510000000274312243421446021166 0ustar00a10038a1003800000000000000####################################################### # # Test missing basic package commands # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dependency-checks-package_patch_command.cf0000644000175100017510000001036012243421446030466 0ustar00a10038a1003800000000000000####################################################### # Test for presence of "main" attribute, given the presence of "dependent" # attributes, which do not make sense without the "main" attribute. # # main attribute: package_patch_command # dependent attributes: # package_patch_arch_regex # package_patch_name_regex # package_patch_version_regex ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: "bash-1.0-amd64" package_policy => "add", package_method => mock_no_patch_command_patch_arch_regex, classes => test_set_class("no_patch_command_patch_arch_regex_succ", "no_patch_command_patch_arch_regex_fail"); "bash-1.0-i386" package_policy => "add", package_method => mock_no_patch_command_patch_name_regex, classes => test_set_class("no_patch_command_patch_name_regex_succ", "no_patch_command_patch_name_regex_fail"); "bash-1.0-sparc" package_policy => "add", package_method => mock_no_patch_command_patch_version_regex, classes => test_set_class("no_patch_command_patch_version_regex_succ", "no_patch_command_patch_version_regex_fail"); } body package_method mock_no_patch_command_patch_arch_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_patch_arch_regex => ""; } body package_method mock_no_patch_command_patch_name_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_patch_name_regex => ""; } body package_method mock_no_patch_command_patch_version_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_patch_version_regex => ""; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "!no_patch_command_patch_arch_regex_succ", "no_patch_command_patch_arch_regex_fail", "!no_patch_command_patch_name_regex_succ", "no_patch_command_patch_name_regex_fail", "!no_patch_command_patch_version_regex_succ", "no_patch_command_patch_version_regex_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/no-architectures.cf0000644000175100017510000000352212243421446024125 0ustar00a10038a1003800000000000000# # Test matching packages with no explicit default architecture set and no # architectures in list of installed packages. # # List of installed packages contains a single package with no architecture # specified. # body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: # # Test that package is matched by a promise with no package_architectures # constraint. # "foobar" package_version => "1", package_policy => "addupdate", package_method => mock, classes => kept("ok_1"); # # Test that specifying architecture explicitly does not match the package with # default architecture. # "foobar" package_version => "1", package_architectures => { "aldan" }, package_policy => "addupdate", package_method => mock, classes => fail("ok_2"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.printf) 'foobar-1'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([\S+])"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes kept(classname) { promise_kept => { "$(classname)" }; } body classes fail(classname) { repair_failed => { "$(classname)" }; } bundle agent check { classes: "ok" and => { "ok_1", "ok_2" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/004.cf0000644000175100017510000000474512352022221021146 0ustar00a10038a1003800000000000000####################################################### # # Test adding *second* package # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } bundle common g { classes: "mpm_declared" not => strcmp(getenv("MOCK_PACKAGE_MANAGER", "65535"), ""); vars: mpm_declared:: "pm" string => getenv("MOCK_PACKAGE_MANAGER", "65535"); !mpm_declared:: "pm" string => "$(G.mock_package_manager)"; } ####################################################### bundle agent init { commands: "$(g.pm) --clear-installed"; "$(g.pm) --clear-available"; "$(g.pm) --populate-available imagisoft:1.0i:x666"; "$(g.pm) --populate-available bluesky:3.1:x666"; "$(g.pm) --add bluesky:*:*"; } ####################################################### bundle agent test { vars: "name" string => "imagisoft"; packages: "$(name)" package_policy => "add", package_method => mock, package_version => "1.0i", classes => test_set_class("pass","fail"); } body package_method mock { package_changes => "individual"; package_list_command => "$(g.pm) --list-installed"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_installed_regex => "^[^:]*"; package_add_command => "$(g.pm) --add "; package_update_command => "$(g.pm) --update "; package_delete_command => "$(g.pm) --delete "; package_verify_command => "$(g.pm) --verify "; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { vars: "pkgs" string => execresult("$(g.pm) --list-installed", "noshell"); classes: "has_pkg" expression => regcmp(".*imagisoft:1\.0i:x666.*", "$(pkgs)"); "ok" expression => "pass.!fail.has_pkg"; reports: DEBUG.pass:: "pass"; DEBUG.has_pkg:: "has_pkg"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes succesfully_executed(class) { kept_returncodes => { "0" }; promise_kept => { "$(class)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/warn-package-delete-non-existing.cf0000644000175100017510000000317612243421446027073 0ustar00a10038a1003800000000000000####################################################### # # Test delete a package that does not exist # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "nosuchpackageinstalled" package_method => mock_warn_delete_pkg, package_policy => "delete", classes => kept_repaired_notkept("kept", "repaired", "notkept"); } body package_method mock_warn_delete_pkg { package_changes => "individual"; package_list_command => "$(G.printf) 'bash-4.2.8-x86_64'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.false)"; } body classes kept_repaired_notkept(kept, repaired, notkept) { promise_kept => { "$(kept)" }; promise_repaired => { "$(repaired)" }; repair_failed => { "$(notkept)" }; } ####################################################### bundle agent check { reports: kept:: "$(this.promise_filename) Pass"; !kept:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/905.cf0000644000175100017510000000273512243421446021170 0ustar00a10038a1003800000000000000####################################################### # # Test missing "installed" regex # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/package_commands_useshell.cf0000644000175100017510000000744712352022221026025 0ustar00a10038a1003800000000000000####################################################### # # Test package_commands_useshell works # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_needs_work" string => "windows"; vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "bash-1.0-amd64" package_policy => "add", package_method => mock_useshell_true, classes => test_set_class("useshell_true_succ", "useshell_true_fail"); "bash-1.0-i386" package_policy => "add", package_method => mock_useshell_false, classes => test_set_class("useshell_false_succ", "useshell_false_fail"); "bash-1.0-spark" package_policy => "add", package_method => mock_useshell_unset, classes => test_set_class("useshell_unset_succ", "useshell_unset_fail"); } body package_method mock_useshell_true { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "if true; then true; else false; fi"; package_list_name_regex => ".*"; package_list_version_regex => ".*"; package_list_arch_regex => ".*"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; package_commands_useshell => "true"; } body package_method mock_useshell_false { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "if true; then true; else false; fi"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; package_commands_useshell => "false"; } body package_method mock_useshell_unset { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "echo 'a:b:c\n'"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "useshell_true_succ", "!useshell_true_fail", "!useshell_false_succ", "useshell_false_fail", "useshell_unset_succ", "!useshell_unset_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/default-list-architectures-same.cf0000644000175100017510000000451612243421446027035 0ustar00a10038a1003800000000000000# # Test matching packages with explicit default architecture set and the same # architecture in list of installed packages. Should work similar to the case # there are no architectures at all. # # List of installed packages contains a single package with the default # architecture specified. # body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: # # Test that package is matched by a promise with no package_architectures # constraint, as it means "any architecture" # "foobar" package_version => "1", package_policy => "addupdate", package_method => mock, classes => kept("ok_1"); # # Test that specifying proper architecture explicitly matches the package. # "foobar" package_version => "1", package_architectures => { "setun" }, package_policy => "addupdate", package_method => mock, classes => kept("ok_2"); # # Test that specifying wrong architecture explicitly does not match the package. # "foobar" package_version => "1", package_architectures => { "aldan" }, package_policy => "addupdate", package_method => mock, classes => fail("ok_3"); } body package_method mock { package_changes => "individual"; package_default_arch_command => "$(G.printf) 'setun'"; package_list_command => "$(G.printf) 'foobar-1-setun'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes kept(classname) { promise_kept => { "$(classname)" }; } body classes fail(classname) { repair_failed => { "$(classname)" }; } bundle agent check { classes: "ok" and => { "ok_1", "ok_2", "ok_3" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dependency-checks-package_list_command.cf0000644000175100017510000001336612352022221030340 0ustar00a10038a1003800000000000000####################################################### # Test for presence of "main" attribute, given the presence of "dependent" # attributes, which do not make sense without the "main" attribute. # # main attribute: package_list_command # dependent attributes: # package_installed_regex # package_list_arch_regex # package_list_name_regex # package_list_version_regex # package_multiline_start ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_unsupported" string => "windows"; packages: "bash-1.0-amd64" package_policy => "add", package_method => mock_no_list_command_package_installed_regex, classes => test_set_class("no_list_command_package_installed_regex_succ", "no_list_command_package_installed_regex_fail"); "bash-2.0-amd64" package_policy => "add", package_method => mock_no_list_command_package_arch_regex, classes => test_set_class("no_list_command_package_arch_regex_succ", "no_list_command_package_arch_regex_fail"); "bash-1.0-i386" package_policy => "add", package_method => mock_no_list_command_package_name_regex, classes => test_set_class("no_list_command_package_name_regex_succ", "no_list_command_package_name_regex_fail"); "bash-1.0-sparc" package_policy => "add", package_method => mock_no_list_command_package_version_regex, classes => test_set_class("no_list_command_package_version_regex_succ", "no_list_command_package_version_regex_fail"); } body package_method mock_no_list_command_package_version_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_file_repositories => { "/package/repos1", "package/repos2" }; # but no package_list_command! # package_installed_regex => ".*"; # package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; # package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; # package_multiline_start => package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock_no_list_command_package_name_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_file_repositories => { "/package/repos1", "package/repos2" }; # but no package_list_command! # package_installed_regex => ".*"; # package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_name_regex => "^([^-]+)"; # package_list_version_regex => "^[^-]+-([^-]+)"; # package_multiline_start => package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock_no_list_command_package_arch_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_file_repositories => { "/package/repos1", "package/repos2" }; # but no package_list_command! # package_installed_regex => ".*"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; # package_list_name_regex => "^([^-]+)"; # package_list_version_regex => "^[^-]+-([^-]+)"; # package_multiline_start => package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock_no_list_command_package_installed_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_file_repositories => { "/package/repos1", "package/repos2" }; # but no package_list_command! package_installed_regex => ".*"; # package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; # package_list_name_regex => "^([^-]+)"; # package_list_version_regex => "^[^-]+-([^-]+)"; # package_multiline_start => package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "!no_list_command_package_installed_regex_succ", "no_list_command_package_installed_regex_fail", "!no_list_command_package_arch_regex_succ", "no_list_command_package_arch_regex_fail", "!no_list_command_package_name_regex_succ", "no_list_command_package_name_regex_fail", "!no_list_command_package_version_regex_succ", "no_list_command_package_version_regex_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dependency-checks-package_delete_command.cf0000644000175100017510000000414112243421446030631 0ustar00a10038a1003800000000000000####################################################### # Test for presence of "main" attribute, given the presence of "dependent" # attributes, which do not make sense without the "main" attribute. # # main attribute: package_delete_command # dependent attributes: # package_delete_convention ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: "bash-1.0-amd64" package_policy => "add", package_method => mock_no_delete_command_delete_convention, classes => test_set_class("no_delete_command_delete_convention_succ", "no_delete_command_delete_convention_fail"); } body package_method mock_no_delete_command_delete_convention { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; # package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_delete_convention => "$(name)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "!no_delete_command_delete_convention_succ", "no_delete_command_delete_convention_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/list-architecture.cf0000644000175100017510000000430212243421446024276 0ustar00a10038a1003800000000000000# # Test matching packages with no explicit default architecture set, but with # architecture reported by the list of installed packages. # # List of installed packages contains a single package with explicit architecture set. # body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: # # Test that package with explicit architecture is matched by promise with no # package_architectures constraint, as no constraint means "any architecture". # "foobar" package_version => "1", package_policy => "addupdate", package_method => mock, classes => kept("ok_1"); # # Test that specifying architecture explicitly matches. # "foobar" package_version => "1", package_architectures => { "besm6" }, package_policy => "addupdate", package_method => mock, classes => kept("ok_2"); # # Test that specifying wrong architecture does not match. # "foobar" package_version => "1", package_architectures => { "aldan" }, package_policy => "addupdate", package_method => mock, classes => fail("ok_3"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.printf) 'foobar-1-besm6'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes kept(classname) { promise_kept => { "$(classname)" }; } body classes fail(classname) { repair_failed => { "$(classname)" }; } bundle agent check { classes: "ok" and => { "ok_1", "ok_2", "ok_3" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/003.cf0000644000175100017510000000465012352022221021140 0ustar00a10038a1003800000000000000####################################################### # # Test adding a package using separate package_version attribute # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } bundle common g { classes: "mpm_declared" not => strcmp(getenv("MOCK_PACKAGE_MANAGER", "65535"), ""); vars: mpm_declared:: "pm" string => getenv("MOCK_PACKAGE_MANAGER", "65535"); !mpm_declared:: "pm" string => "$(G.mock_package_manager)"; } ####################################################### bundle agent init { commands: "$(g.pm) --clear-installed"; "$(g.pm) --clear-available"; "$(g.pm) --populate-available imagisoft:1.0i:x666"; } ####################################################### bundle agent test { vars: "name" string => "imagisoft"; packages: "$(name)" package_policy => "add", package_method => mock, package_version => "1.0i", classes => test_set_class("pass","fail"); } body package_method mock { package_changes => "individual"; package_list_command => "$(g.pm) --list-installed"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_installed_regex => "^[^:]*"; package_add_command => "$(g.pm) --add "; package_update_command => "$(g.pm) --update "; package_delete_command => "$(g.pm) --delete "; package_verify_command => "$(g.pm) --verify "; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { vars: "pkgs" string => execresult("$(g.pm) --list-installed", "noshell"); classes: "has_pkg" expression => regcmp("imagisoft:1\.0i:x666", "$(pkgs)"); "ok" expression => "pass.!fail.has_pkg"; reports: DEBUG.pass:: "pass"; DEBUG.has_pkg:: "has_pkg"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes succesfully_executed(class) { kept_returncodes => { "0" }; promise_kept => { "$(class)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/upgrade-package.cf0000644000175100017510000000245212352022221023654 0ustar00a10038a1003800000000000000# Tests that package upgrade works properly body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_needs_work" string => "windows"; vars: "dummy" string => "dummy"; } body package_method yum_rpm { package_changes => "individual"; package_list_command => "$(G.printf) 'which 1 i386'"; package_list_name_regex => "^(\S+?)\s\S+?\s\S+$"; package_list_version_regex => "^\S+?\s(\S+?)\s\S+$"; package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.false)"; } bundle agent test { packages: "which" package_policy => "addupdate", package_select => "==", package_version => "2", package_method => yum_rpm, classes => if_repaired("whichrepaired"); } bundle agent check { reports: whichrepaired:: "$(this.promise_filename) Pass"; !whichrepaired:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/005.cf0000644000175100017510000000507412352022221021143 0ustar00a10038a1003800000000000000####################################################### # # Test trying to actually specify versions of packages # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } bundle common g { classes: "mpm_declared" not => strcmp(getenv("MOCK_PACKAGE_MANAGER", "65535"), ""); vars: mpm_declared:: "pm" string => getenv("MOCK_PACKAGE_MANAGER", "65535"); !mpm_declared:: "pm" string => "$(G.mock_package_manager)"; } ####################################################### bundle agent init { commands: "$(g.pm) --clear-installed"; "$(g.pm) --clear-available"; "$(g.pm) --populate-available imagisoft:1.0i:x666"; "$(g.pm) --populate-available bluesky:3.1:x666"; "$(g.pm) --add bluesky:*:*"; } ####################################################### bundle agent test { vars: "name" string => "imagisoft"; packages: "$(name)" package_policy => "add", package_method => mock, package_version => "1.0i", classes => test_set_class("pass","fail"); } body package_method mock { package_changes => "individual"; package_list_command => "$(g.pm) --list-installed"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_installed_regex => "^[^:]*"; package_add_command => "$(g.pm) --add "; package_update_command => "$(g.pm) --update "; package_delete_command => "$(g.pm) --delete "; package_verify_command => "$(g.pm) --verify "; package_name_convention => "$(name):$(version):$(arch)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { vars: "pkgs" string => execresult("$(g.pm) --list-installed", "noshell"); classes: "has_pkg" expression => regcmp(".*imagisoft:1\.0i:x666.*", "$(pkgs)"); "ok" expression => "pass.!fail.has_pkg"; reports: DEBUG.pass:: "pass"; DEBUG.has_pkg:: "has_pkg"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes succesfully_executed(class) { kept_returncodes => { "0" }; promise_kept => { "$(class)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/006.cf0000644000175100017510000000505512352022221021143 0ustar00a10038a1003800000000000000####################################################### # # Test trying to avoid parsing promiser # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } bundle common g { classes: "mpm_declared" not => strcmp(getenv("MOCK_PACKAGE_MANAGER", "65535"), ""); vars: mpm_declared:: "pm" string => getenv("MOCK_PACKAGE_MANAGER", "65535"); !mpm_declared:: "pm" string => "$(G.mock_package_manager)"; } ####################################################### bundle agent init { commands: "$(g.pm) --clear-installed"; "$(g.pm) --clear-available"; "$(g.pm) --populate-available imagisoft:1.0i:x666"; "$(g.pm) --populate-available bluesky:3.1:x666"; "$(g.pm) --add bluesky:*:*"; } ####################################################### bundle agent test { vars: "name" string => "imagisoft"; packages: "$(name)" package_policy => "add", package_method => mock, package_version => "1.0i", classes => test_set_class("pass","fail"); } body package_method mock { package_changes => "individual"; package_list_command => "$(g.pm) --list-installed"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_installed_regex => "^[^:]*"; package_add_command => "$(g.pm) --add "; package_update_command => "$(g.pm) --update "; package_delete_command => "$(g.pm) --delete "; package_verify_command => "$(g.pm) --verify "; package_name_convention => "$(name):$(version):$(arch)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { vars: "pkgs" string => execresult("$(g.pm) --list-installed", "noshell"); classes: "has_pkg" expression => regcmp(".*imagisoft:1\.0i:x666.*", "$(pkgs)"); "ok" expression => "pass.!fail.has_pkg"; reports: DEBUG.pass:: "pass"; DEBUG.has_pkg:: "has_pkg"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes succesfully_executed(class) { kept_returncodes => { "0" }; promise_kept => { "$(class)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/default-list-architectures-different.cf0000644000175100017510000000515512243421446030056 0ustar00a10038a1003800000000000000# # Test matching packages with explicit default architecture set and the same # architecture in list of installed packages. Should work similar to the case # there are no architectures at all. # # List of installed packages contains a single package with the default # architecture specified. # body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: # # Test that package is matched by a promise with no package_architectures # constraint, as it means "any architecture" # "foobar" package_version => "1", package_policy => "addupdate", package_method => mock, classes => kept("ok_1"); # # Test that specifying default architecture does not match the # "foobar" package_version => "1", package_architectures => { "setun" }, package_policy => "addupdate", package_method => mock, classes => fail("ok_2"); # # Test that specifying proper architecture explicitly matches the package. # "foobar" package_version => "1", package_architectures => { "besm6" }, package_policy => "addupdate", package_method => mock, classes => kept("ok_3"); # # Test that specifying wrong architecture explicitly does not match the package. # "foobar" package_version => "1", package_architectures => { "aldan" }, package_policy => "addupdate", package_method => mock, classes => fail("ok_4"); } body package_method mock { package_changes => "individual"; package_default_arch_command => "$(G.printf) 'setun'"; package_list_command => "$(G.printf) 'foobar-1-besm6'"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-([\S]+)"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes kept(classname) { promise_kept => { "$(classname)" }; } body classes fail(classname) { repair_failed => { "$(classname)" }; } bundle agent check { classes: "ok" and => { "ok_1", "ok_2", "ok_3", "ok_4"}; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/002.cf0000644000175100017510000000464712352022221021145 0ustar00a10038a1003800000000000000####################################################### # # Test add a package using a "default" architecture # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } bundle common g { classes: "mpm_declared" not => strcmp(getenv("MOCK_PACKAGE_MANAGER", "65535"), ""); vars: mpm_declared:: "pm" string => getenv("MOCK_PACKAGE_MANAGER", "65535"); !mpm_declared:: "pm" string => "$(G.mock_package_manager)"; } ####################################################### bundle agent init { commands: "$(g.pm) --clear-installed"; "$(g.pm) --clear-available"; "$(g.pm) --populate-available imagisoft:1.0i:x666"; } ####################################################### bundle agent test { vars: "name" string => "imagisoft"; "version" string => "1.0i"; packages: "$(name):$(version)" package_policy => "add", package_method => mock, classes => test_set_class("pass","fail"); } body package_method mock { package_changes => "individual"; package_list_command => "$(g.pm) --list-installed"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_installed_regex => "^[^:]*"; package_add_command => "$(g.pm) --add "; package_update_command => "$(g.pm) --update "; package_delete_command => "$(g.pm) --delete "; package_verify_command => "$(g.pm) --verify "; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { vars: "pkgs" string => execresult("$(g.pm) --list-installed", "noshell"); classes: "has_pkg" expression => regcmp("imagisoft:1\.0i:x666", "$(pkgs)"); "ok" expression => "pass.!fail.has_pkg"; reports: DEBUG.pass:: "pass"; DEBUG.has_pkg:: "has_pkg"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes succesfully_executed(class) { kept_returncodes => { "0" }; promise_kept => { "$(class)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/contradicting-bodies-and-promises.cf0000644000175100017510000001130412243421446027335 0ustar00a10038a1003800000000000000####################################################### # Test that specifying two incompatible ways to get package version is detected # and reported ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "bash-1.0-amd64" package_policy => "add", package_method => mock, package_version => "2.0", package_architectures => { "amd64" }, classes => test_set_class("overlapping_version_arch_regex_succ", "overlapping_version_arch_regex_fail"); "bash-1.0-i386" package_policy => "add", package_method => mock_no_name_regex_but_version_regex, classes => test_set_class("no_name_regex_version_succ", "no_name_regex_version_fail"); "bash-1.0-i386" package_policy => "add", package_method => mock_no_name_regex_but_arch_regex, classes => test_set_class("no_name_regex_arch_succ", "no_name_regex_arch_fail"); "bash-1.0-sparc" package_policy => "add", package_method => mock_overlapping_version_regex, package_version => "2.0", classes => test_set_class("overlapping_version_regex_succ", "overlapping_version_regex_fail"); } body package_method mock_overlapping_version_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.true) $(this.name)-$(this.version):$(this.arch)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body package_method mock_no_name_regex_but_arch_regex { package_changes => "individual"; package_arch_regex => ".*"; # but no package_name_regex! package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock_no_name_regex_but_version_regex { package_changes => "individual"; package_version_regex => ".*"; # but no package_name_regex! package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body package_method mock { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "!no_name_regex_version_succ", "no_name_regex_version_fail", "!no_name_regex_arch_succ", "no_name_regex_arch_fail", "!overlapping_version_arch_regex_succ", "overlapping_version_arch_regex_fail", "!overlapping_version_regex_succ", "overlapping_version_regex_fail"}; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/906.cf0000644000175100017510000000503012243421446021160 0ustar00a10038a1003800000000000000####################################################### # # Test too long repository directory # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_file_repositories => { "/tmp", "/fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu/" }; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/901.cf0000644000175100017510000000315212352022221021143 0ustar00a10038a1003800000000000000####################################################### # # Test missing version regex fails # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_unsupported" string => "windows"; packages: "a:b:c" package_policy => "add", package_method => mock, classes => test_set_class("fail","ok"); } body package_method mock { package_changes => "individual"; package_list_command => "$(G.true)"; package_list_name_regex => "^[^:]*"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(G.true)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.true)"; package_verify_command => "$(G.true)"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { reports: ok.!fail:: "$(this.promise_filename) Pass"; !ok|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/001.cf0000644000175100017510000000463612352022221021142 0ustar00a10038a1003800000000000000####################################################### # # Test add a package # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "G", "g", default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } bundle common g { classes: "mpm_declared" not => strcmp(getenv("MOCK_PACKAGE_MANAGER", "65535"), ""); vars: mpm_declared:: "pm" string => getenv("MOCK_PACKAGE_MANAGER", "65535"); !mpm_declared:: "pm" string => "$(G.mock_package_manager)"; } ####################################################### bundle agent init { commands: "$(g.pm) --clear-installed"; "$(g.pm) --clear-available"; "$(g.pm) --populate-available imagisoft:1.0i:teapot"; } ####################################################### bundle agent test { vars: "name" string => "imagisoft"; "version" string => "1.0i"; "arch" string => "teapot"; packages: "$(name):$(version):$(arch)" package_policy => "add", package_method => mock, classes => test_set_class("pass","fail"); } body package_method mock { package_changes => "individual"; package_list_command => "$(g.pm) --list-installed"; package_list_name_regex => "^[^:]*"; package_list_version_regex => ":(?<=:).*(?=:)"; package_list_arch_regex => "[^:]\w+$"; package_installed_regex => "^[^:]*"; package_add_command => "$(g.pm) --add "; package_update_command => "$(g.pm) --update "; package_delete_command => "$(g.pm) --delete "; package_verify_command => "$(g.pm) --verify "; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { vars: "pkgs" string => execresult("$(g.pm) --list-installed", "noshell"); classes: "has_pkg" expression => regcmp("imagisoft:1\.0i:teapot", "$(pkgs)"); "ok" expression => "pass.!fail.has_pkg"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes succesfully_executed(class) { kept_returncodes => { "0" }; promise_kept => { "$(class)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/repositories.cf.sub0000644000175100017510000002306612352022221024157 0ustar00a10038a1003800000000000000# Tests that package upgrade works properly body common control { inputs => { "../default.cf.sub" }; bundlesequence => { "init", "test" }; version => "1.0"; } bundle agent init { methods: "make filerepo" usebundle => file_make($(G.testfile), ""); } body package_method test_method_filerepo(currentdir) { package_changes => "individual"; package_list_command => "$(G.cat) $(currentdir)/test_repository/installed.txt | $(G.grep) 'i '"; package_installed_regex => "i .*"; package_list_name_regex => "^[ia] (\S+?)\s\S+?\s\S+$"; package_list_version_regex => "^[ia] \S+?\s(\S+?)\s\S+$"; package_list_arch_regex => "^[ia] \S+?\s\S+?\s(\S+)$"; # Normally one would use $(G.echo), but it messes up redirection when you have arguments # following the redirected filename on Windows, so use the stock "echo" in this case. package_add_command => "echo >>$(G.testfile) filerepo ADD"; package_update_command => "echo >>$(G.testfile) filerepo UPDATE"; package_delete_command => "echo >>$(G.testfile) filerepo DELETE"; package_file_repositories => { translatepath("$(currentdir)/test_repository") }; package_name_convention => "$(name)-$(version).$(arch).rpm"; } bundle agent test { vars: "currentdir" string => translatepath("$(this.promise_dirname)"); packages: "install-exact-version" package_policy => "addupdate", package_select => "==", package_version => "2.2.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-exact-version" package_policy => "addupdate", package_select => "==", package_version => "2.2.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "delete-exact-version" package_policy => "delete", package_select => "==", package_version => "2.2.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "install-lessorequal-version" package_policy => "addupdate", package_select => "<=", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-lessorequal-version" package_policy => "addupdate", package_select => "<=", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "install-lessthan-version" package_policy => "addupdate", package_select => "<", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-lessthan-version" package_policy => "addupdate", package_select => "<", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "install-greaterorequal-version" package_policy => "addupdate", package_select => ">=", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-greaterorequal-version" package_policy => "addupdate", package_select => ">=", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-greaterorequal-version-already-greater-installed" package_policy => "addupdate", package_select => ">=", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "install-greaterthan-version" package_policy => "addupdate", package_select => ">", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-greaterthan-version" package_policy => "addupdate", package_select => ">", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "update-to-greaterthan-version-already-greater-installed" package_policy => "addupdate", package_select => ">", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-install-exact-version" package_policy => "addupdate", package_select => "==", package_version => "2.1.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-update-to-exact-version" package_policy => "addupdate", package_select => "==", package_version => "2.1.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-delete-exact-version" package_policy => "delete", package_select => "==", package_version => "2.1.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-install-lessorequal-version" package_policy => "addupdate", package_select => "<=", package_version => "2.1.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-update-to-lessorequal-version" package_policy => "addupdate", package_select => "<=", package_version => "2.1.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-install-lessthan-version" package_policy => "addupdate", package_select => "<", package_version => "2.1.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-update-to-lessthan-version" package_policy => "addupdate", package_select => "<", package_version => "2.1.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-install-greaterorequal-version" package_policy => "addupdate", package_select => ">=", package_version => "2.4.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-update-to-greaterorequal-version" package_policy => "addupdate", package_select => ">=", package_version => "2.4.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-install-greaterthan-version" package_policy => "addupdate", package_select => ">", package_version => "2.4.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "mismatch-update-to-greaterthan-version" package_policy => "addupdate", package_select => ">", package_version => "2.4.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-install-exact-version" package_policy => "addupdate", package_select => "==", package_version => "2.2.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-update-to-exact-version" package_policy => "addupdate", package_select => "==", package_version => "2.2.3", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-install-lessorequal-version" package_policy => "addupdate", package_select => "<=", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-update-to-lessorequal-version" package_policy => "addupdate", package_select => "<=", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-install-lessthan-version" package_policy => "addupdate", package_select => "<", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-update-to-lessthan-version" package_policy => "addupdate", package_select => "<", package_version => "2.4.5", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-install-greaterorequal-version" package_policy => "addupdate", package_select => ">=", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-update-to-greaterorequal-version" package_policy => "addupdate", package_select => ">=", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-install-greaterthan-version" package_policy => "addupdate", package_select => ">", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); "missing-update-to-greaterthan-version" package_policy => "addupdate", package_select => ">", package_version => "2.0.1", package_architectures => { "i386" }, package_method => test_method_filerepo($(currentdir)); } cfengine-3.6.2/tests/acceptance/07_packages/repositories.cf0000644000175100017510000000466212352022221023370 0ustar00a10038a1003800000000000000# Tests that package upgrade works properly body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "d" string => "$(const.dirsep)"; # Due to shell rules, windows includes certain characters on certain commands, # while Unix does not. windows:: "q" string => '"'; "s" string => ' '; !windows:: "q" string => ''; "s" string => ''; methods: "make" usebundle => file_make("$(G.testfile).expected", " $(s)filerepo DELETE delete-exact-version-2.2.3.i386.rpm $(s)filerepo ADD $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)install-greaterthan-version-2.2.3.i386.rpm$(q) $(s)filerepo ADD $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)install-greaterorequal-version-2.2.3.i386.rpm$(q) $(s)filerepo ADD $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)install-lessthan-version-2.2.3.i386.rpm$(q) $(s)filerepo ADD $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)install-lessorequal-version-2.2.3.i386.rpm$(q) $(s)filerepo ADD $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)install-exact-version-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-greaterthan-version-already-greater-installed-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-greaterthan-version-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-greaterorequal-version-already-greater-installed-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-greaterorequal-version-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-lessthan-version-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-lessorequal-version-2.2.3.i386.rpm$(q) $(s)filerepo UPDATE $(q)$(G.cwd)$(d).$(d)07_packages$(d)test_repository$(d)update-to-exact-version-2.2.3.i386.rpm$(q)"); } bundle agent test { methods: "run" usebundle => dcs_runagent("$(this.promise_filename).sub"); } bundle agent check { methods: "any" usebundle => sorted_check_diff("$(G.testfile)", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dry-run-install.cf0000644000175100017510000000136512243421446023715 0ustar00a10038a1003800000000000000# Test that if the action => 'warn' is specified, no packages are installed. body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { vars: "subout" string => execresult("$(sys.cf_agent) -Kv -f $(this.promise_filename).sub | $(G.grep) should-not-be-called", "useshell"); } bundle agent check { classes: "ok" not => regcmp(".*should-not-be-called.*", "$(test.subout)"); reports: DEBUG:: "$(test.subout)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/dependency-checks-package_patch_list_command.cf0000644000175100017510000000421412243421446031522 0ustar00a10038a1003800000000000000####################################################### # Test for presence of "main" attribute, given the presence of "dependent" # attributes, which do not make sense without the "main" attribute. # # main attribute: package_patch_list_command # dependent attributes: # package_patch_installed_regex ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle agent test { packages: "bash-1.0-amd64" package_policy => "add", package_method => mock_no_patch_list_command_patch_installed_regex, classes => test_set_class("no_patch_list_command_patch_installed_regex_succ", "no_patch_list_command_patch_installed_regex_fail"); } body package_method mock_no_patch_list_command_patch_installed_regex { package_changes => "individual"; package_name_regex => "^([^-]+)"; package_version_regex => "^[^-]+-([^-]+)"; package_arch_regex => "^[^-]+-[^-]+-(.*)"; package_list_command => "$(G.printf) 'bash-1.0-amd64'"; package_installed_regex => ".*"; package_list_name_regex => "^([^-]+)"; package_list_version_regex => "^[^-]+-([^-]+)"; package_list_arch_regex => "^[^-]+-[^-]+-(.*)"; package_add_command => "$(G.false)"; package_update_command => "$(G.false)"; package_delete_command => "$(G.false)"; package_verify_command => "$(G.false)"; package_patch_installed_regex => ""; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" and => { "!no_patch_list_command_patch_installed_regex_succ", "no_patch_list_command_patch_installed_regex_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/07_packages/upgrade-package-version.cf0000644000175100017510000000250212352022221025333 0ustar00a10038a1003800000000000000# Tests that package upgrade works properly with "more than" version body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { meta: # Windows has its own mechanism to list packages, and doesn't use the package body. "test_skip_needs_work" string => "windows"; vars: "dummy" string => "dummy"; } body package_method yum_rpm { package_changes => "individual"; package_list_command => "$(G.printf) 'which 1 i386'"; package_list_name_regex => "^(\S+?)\s\S+?\s\S+$"; package_list_version_regex => "^\S+?\s(\S+?)\s\S+$"; package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$"; package_installed_regex => ".*"; package_add_command => "$(G.false)"; package_update_command => "$(G.true)"; package_delete_command => "$(G.false)"; } bundle agent test { packages: "which" package_policy => "addupdate", package_select => ">", package_version => "2", package_method => yum_rpm, classes => if_repaired("whichrepaired"); } bundle agent check { reports: whichrepaired:: "$(this.promise_filename) Pass"; !whichrepaired:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 29 cfengine-3.6.2/tests/acceptance/10_files/0000755000175100017510000000000012411001073017633 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/12_acl/0000755000175100017510000000000012316547775020730 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/12_acl/file_copy_acl.cf0000644000175100017510000001037012316547775024033 0ustar00a10038a1003800000000000000###################################################### # # ACL tests for file copying. # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { classes: "cfengine_internal_getfacl" expression => fileexists("/var/cfengine/bin/getfacl"); "system_getfacl" expression => fileexists("/usr/bin/getfacl"); vars: linux.cfengine_internal_getfacl:: "cmd" string => "/var/cfengine/bin/getfacl"; linux.!cfengine_internal_getfacl.system_getfacl:: "cmd" string => "/usr/bin/getfacl"; windows:: "cmd" string => "C:\windows\system32\cmd.exe /C cacls"; files: "$(G.testdir)/source_plain" create => "true"; "$(G.testdir)/source_ext" create => "true", acl => testacl; } body acl testacl { !windows:: acl_method => "append"; aces => { "user:root:wx" }; windows:: acl_method => "overwrite"; aces => { "user:Administrator:r" }; acl_inherit => "false"; } bundle agent test { meta: "test_skip_needs_work" string => "windows"; files: "$(G.testdir)/destination_plain" copy_from => source_plain; "$(G.testdir)/destination_ext_preserve" copy_from => source_ext_preserve; "$(G.testdir)/destination_ext_no_preserve" copy_from => source_ext_no_preserve; } body copy_from source_plain { source => "$(G.testdir)/source_plain"; } body copy_from source_ext_preserve { source => "$(G.testdir)/source_ext"; preserve => "yes"; } body copy_from source_ext_no_preserve { source => "$(G.testdir)/source_ext"; preserve => "no"; } bundle agent check { vars: "destination_ext_preserve_output" string => execresult("$(init.cmd) $(G.testdir)$(const.dirsep)destination_ext_preserve", "noshell"); "destination_ext_no_preserve_output" string => execresult("$(init.cmd) $(G.testdir)$(const.dirsep)destination_ext_no_preserve", "noshell"); !windows:: "destination_plain_output" string => execresult("/bin/ls -lZ $(G.testdir)$(const.dirsep)destination_plain", "noshell"); "source_ext_output" string => execresult("$(init.cmd) $(G.testdir)$(const.dirsep)source_ext", "noshell"); classes: !windows:: "destination_plain_ok" not => regcmp(".*[-rwx]{10}\+.*", "$(destination_plain_output)"); "source_ext_ok" expression => regcmp(".*user:root:-wx.*", "$(source_ext_output)"); "destination_ext_preserve_ok" expression => regcmp(".*user:root:-wx.*", "$(destination_ext_preserve_output)"); "destination_ext_no_preserve_ok" not => regcmp(".*user:root:-wx.*", "$(destination_ext_no_preserve_output)"); "targets_ok" and => { "destination_plain_ok", "destination_ext_preserve_ok", "destination_ext_no_preserve_ok" }; # The !source_ext_ok test is in case the underlying file system does not support ACLs. "ok" or => { "!source_ext_ok", "targets_ok" }; windows:: "destination_ext_preserve_ok" expression => regcmp(".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*", "$(destination_ext_preserve_output)"); "destination_ext_no_preserve_ok" not => regcmp(".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*", "$(destination_ext_no_preserve_output)"); "ok" and => { "destination_ext_preserve_ok", "destination_ext_no_preserve_ok" }; reports: DEBUG.!windows:: "Destination file permissions (should not contain a '+'): $(destination_plain_output)"; "Destination file permissions (should contain \"user:root:-wx\"): $(destination_ext_preserve_output)"; "Destination file permissions (should not contain \"user:root:-wx\"): $(destination_ext_no_preserve_output)"; DEBUG.windows:: "Destination file permissions (should contain read attributes): $(destination_ext_preserve_output)"; "Destination file permissions (should not contain read attributes): $(destination_ext_no_preserve_output)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/12_acl/acl.cf.sub0000644000175100017510000003537012316547775022601 0ustar00a10038a1003800000000000000###################################################### # # ACL tests # This test is not convergent, since it tests the # same file over and over. But it saves us a lot # of test code. # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "init", "test" }; version => "1.0"; } ####################################################### bundle agent init { classes: "cfengine_internal_getfacl" expression => fileexists("/var/cfengine/bin/getfacl"); "system_getfacl" expression => fileexists("/usr/bin/getfacl"); vars: linux.cfengine_internal_getfacl:: "cmd" string => "/var/cfengine/bin/getfacl"; linux.!cfengine_internal_getfacl.system_getfacl:: "cmd" string => "/usr/bin/getfacl"; windows:: "cmd" string => "C:\windows\system32\cmd.exe /C cacls"; vars: windows:: "rootuser" string => "Administrator"; !windows:: "rootuser" string => "root"; vars: # ACLs may work on many Unixes, but only Linux has the tool we use to check the permissions. linux:: # Ordering is important here, in the case of append. "acl_method[regular_posix]" string => "overwrite"; "aces[regular_posix]" slist => { "user:*:=rw:allow", "group:*:=rw:allow", "all:=r:allow" }; "regcmp[regular_posix]" string => ".*user::rw-.*group::rw-.*other::r--.*"; "acl_method[regular_posix2]" string => "overwrite"; "aces[regular_posix2]" slist => { "user:*:=x:allow", "group:*:=x:allow", "all:=w:allow" }; "regcmp[regular_posix2]" string => ".*user::--x.*group::--x.*other::-w-.*"; "acl_method[specific_user]" string => "overwrite"; "aces[specific_user]" slist => { "user:*:=r:allow", "group:*:=r:allow", "all:=r:allow", "user:root:=rwx:allow" }; "regcmp[specific_user]" string => ".*user::r--.*user:root:rwx.*group::r--.*other::r--.*"; "notregcmp[specific_user]" string => ".*group:root:.*"; "acl_method[specific_group_append]" string => "append"; "aces[specific_group_append]" slist => { "group:root:=rw:allow" }; "regcmp[specific_group_append]" string => ".*user::r--.*user:root:rwx.*group::r--.*group:root:rw-.*other::r--.*"; "acl_method[no_mask]" string => "overwrite"; "aces[no_mask]" slist => { "user:*:=r:allow", "group:*:=r:allow", "all:=r:allow", "user:root:=rx:allow" }; "regcmp[no_mask]" string => ".*user::r--.*user:root:r-x.*group::r--.*mask::r-x.*other::r--.*"; "acl_type[specific_mask]" string => "posix"; "acl_method[specific_mask]" string => "overwrite"; "aces[specific_mask]" slist => { "user:*:=r:allow", "group:*:=r:allow", "mask:=r:allow", "all:=r:allow", "user:root:=rw:allow" }; "regcmp[specific_mask]" string => ".*user::r--.*user:root:rw-.*group::r--.*mask::r--.*other::r--.*"; "notregcmp[specific_mask]" string => ".*group:root:.*"; "acl_method[mask_and_append_group]" string => "append"; "aces[mask_and_append_group]" slist => { "group:root:=rx:allow" }; "regcmp[mask_and_append_group]" string => ".*user::r--.*user:root:rw-.*group::r--.*group:root:r-x.*mask::rwx.*other::r--.*"; "acl_method[no_perm_group]" string => "append"; "aces[no_perm_group]" slist => { "group:root:=:allow" }; "regcmp[no_perm_group]" string => ".*user::r--.*user:root:rw-.*group::r--.*group:root:---.*mask::rw-.*other::r--.*"; "acl_method[add_perm]" string => "append"; "aces[add_perm]" slist => { "user:*:+x:allow" }; "regcmp[add_perm]" string => ".*user::r-x.*user:root:rw-.*group::r--.*group:root:---.*mask::rw-.*other::r--.*"; "acl_method[add_perm_user]" string => "append"; "aces[add_perm_user]" slist => { "user:root:+x:allow" }; "regcmp[add_perm_user]" string => ".*user::r-x.*user:root:rwx.*group::r--.*group:root:---.*mask::rwx.*other::r--.*"; "acl_method[rm_perm]" string => "append"; "aces[rm_perm]" slist => { "all:-r:allow", "user:root:-rw:allow" }; "regcmp[rm_perm]" string => ".*user::r-x.*user:root:--x.*group::r--.*group:root:---.*mask::r-x.*other::---.*"; "acl_method[overwrite_add_remove]" string => "overwrite"; # Overwrite starts with blank permissions. "aces[overwrite_add_remove]" slist => { "all:+r:allow", "user:*:-x:allow", "group:*:+x:allow" }; "regcmp[overwrite_add_remove]" string => ".*user::---.*group::--x.*other::r--.*"; "notregcmp[overwrite_add_remove]" string => ".*user:root:.*|.*group:root:.*"; # This test oscillates between pass and fail. Check out "other::r--" vs "other::r-x" "acl_method[default]" string => "overwrite"; "aces[default]" slist => { "all:r:allow", "user:*:rwx:allow", "group:*:rw:allow" }; "acl_default[default]" string => "access"; "use_dir[default]" string => "true"; "regcmp[default]" string => ".*user::rwx.*group::rw-.*other::r--.*default:user::rwx.*default:group::rw-.*default:other::r--.*"; # Fails but should pass. "acl_method[default_specify]" string => "overwrite"; "aces[default_specify]" slist => { "user:*:r:allow", "group:*:r:allow", "all:r:allow" }; "acl_default[default_specify]" string => "specify"; "specify_default_aces[default_specify]" slist => { "user:*:rwx:allow", "group:*:rw:allow", "all:rw:allow", "user:root:x:allow" }; "use_dir[default_specify]" string => "true"; "regcmp[default_specify]" string => ".*user::r--.*group::r--.*other::r--.*default:user::rwx.*default:user:root:--x.*default:group::rw-.*default:other::rw-.*"; "tests" slist => { "regular_posix", "regular_posix2", "specific_user", "specific_group_append", "no_mask", "specific_mask", "mask_and_append_group", "no_perm_group", "add_perm", "add_perm_user", "rm_perm", "overwrite_add_remove", #"default", #"default_specify", } ; windows:: "acl_method[read]" string => "overwrite"; "aces[read]" slist => { "user:Administrator:r:allow" }; "acl_inherit[read]" string => "false"; "regcmp[read]" string => ".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*"; "notregcmp[read]" string => ".*\(ID\).*"; "acl_method[write]" string => "overwrite"; "aces[write]" slist => { "user:Administrator:w:allow" }; "regcmp[write]" string => ".*Administrator:.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_WRITE_EA.*FILE_WRITE_ATTRIBUTES.*"; "notregcmp[write]" string => ".*\(ID\).*"; "acl_method[append_read]" string => "append"; "aces[append_read]" slist => { "user:Administrator:r:allow" }; "regcmp[append_read]" string => ".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*"; "notregcmp[append_read]" string => ".*(Administrator:.*(FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)|\(ID\)).*"; "acl_method[add_write]" string => "append"; "aces[add_write]" slist => { "user:Administrator:+w:allow" }; "regcmp[add_write]" string => ".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "notregcmp[add_write]" string => ".*\(ID\).*"; "acl_method[rm_write]" string => "append"; "aces[rm_write]" slist => { "user:Administrator:-w:allow" }; "regcmp[rm_write]" string => ".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*"; "notregcmp[rm_write]" string => ".*\(ID\).*"; "acl_method[no_default]" string => "overwrite"; "aces[no_default]" slist => { "user:Administrator:rwx:allow" }; "acl_default[no_default]" string => "clear"; "use_dir[no_default]" string => "true"; "regcmp[no_default]" string => ".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_EXECUTE.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "notregcmp[no_default]" string => ".*(\(OI\)|\(CI\)).*"; "acl_method[default]" string => "overwrite"; "aces[default]" slist => { "user:Administrator:rwx:allow" }; "acl_default[default]" string => "access"; "use_dir[default]" string => "true"; "regcmp[default]" string => ".*Administrator:\(OI\)\(CI\).*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_EXECUTE.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "acl_method[inherit]" string => "overwrite"; "aces[inherit]" slist => { "group:Everyone:r:allow" }; "acl_inherit[inherit]" string => "true"; "regcmp[inherit]" string => ".*Everyone:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*Administrator:\(ID\).*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "acl_method[inherit_nochange]" string => "append"; "aces[inherit_nochange]" slist => { "group:Everyone:+w:allow" }; "acl_inherit[inherit_nochange]" string => "nochange"; "regcmp[inherit_nochange]" string => ".*Everyone:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*Administrator:\(ID\).*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "acl_method[empty]" string => "append"; "aces[empty]" slist => { "group:Everyone:-rw:allow" }; "acl_inherit[empty]" string => "nochange"; "regcmp[empty]" string => ".*Administrator:\(ID\).*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "notregcmp[empty]" string => ".*Everyone.*"; "acl_method[no_inherit]" string => "append"; "aces[no_inherit]" slist => { "group:Everyone:+rw:allow" }; "acl_inherit[no_inherit]" string => "false"; "regcmp[no_inherit]" string => ".*Everyone:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_GENERIC_WRITE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_WRITE_EA.*FILE_READ_ATTRIBUTES.*FILE_WRITE_ATTRIBUTES.*"; "notregcmp[no_inherit]" string => ".*\(ID\).*"; "acl_type[ext_attr_delete]" string => "ntfs"; "acl_method[ext_attr_delete]" string => "overwrite"; "aces[ext_attr_delete]" slist => { "user:Administrator:(d):allow" }; "regcmp[ext_attr_delete]" string => ".*Administrator:.*DELETE.*"; "notregcmp[ext_attr_delete]" string => ".*(\(ID\)|READ|WRITE).*"; "acl_type[ext_attr_half1]" string => "ntfs"; "acl_method[ext_attr_half1]" string => "append"; "aces[ext_attr_half1]" slist => { "user:Administrator:+(rtxTwa):allow" }; "regcmp[ext_attr_half1]" string => ".*Administrator:.*DELETE.*FILE_READ_DATA.*FILE_WRITE_DATA.*FILE_APPEND_DATA.*FILE_READ_EA.*FILE_EXECUTE.*FILE_READ_ATTRIBUTES.*"; "notregcmp[ext_attr_half1]" string => ".*\(ID\).*"; "acl_type[ext_attr_half2]" string => "ntfs"; "acl_method[ext_attr_half2]" string => "append"; "aces[ext_attr_half2]" slist => { "user:Administrator:-(drtxTwa),+(bBpcoD):allow" }; "regcmp[ext_attr_half2]" string => ".*Administrator:.*READ_CONTROL.*WRITE_DAC.*WRITE_OWNER.*FILE_WRITE_EA.*FILE_DELETE_CHILD.*FILE_WRITE_ATTRIBUTES.*"; "notregcmp[ext_attr_half2]" string => ".*(\(ID\)|[^_]DELETE|FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_READ_EA|FILE_EXECUTE|FILE_READ_ATTRIBUTES).*"; "tests" slist => { "read", "write", "append_read", "add_write", "rm_write", "no_default", "default", "inherit", "inherit_nochange", "empty", "no_inherit", "ext_attr_delete", "ext_attr_half1", "ext_attr_half2", }; files: "$(G.testdir)$(const.dirsep)file" create => "true"; } ####################################################### bundle agent test { methods: linux|windows:: "any" usebundle => test_and_check("$(init.tests)"); } bundle agent test_and_check(testname) { classes: "use_dir" expression => isvariable("init.use_dir[$(testname)]"); methods: use_dir:: "any" usebundle => test_exec("$(testname)", "$(G.testdir)"); "any" usebundle => test_check("$(testname)", "$(G.testdir)"); !use_dir:: "any" usebundle => test_exec("$(testname)", "$(G.testdir)$(const.dirsep)file"); "any" usebundle => test_check("$(testname)", "$(G.testdir)$(const.dirsep)file"); } bundle agent test_exec(testname, file) { classes: "acl_type" expression => isvariable("init.acl_type[$(testname)]"); "acl_default" expression => isvariable("init.acl_default[$(testname)]"); acl_default:: "specify_default_aces" expression => strcmp("init.acl_default[$(testname)]", "specify"); files: "$(file)" acl => acldef("$(testname)", "$(file)"); } body acl acldef(testname, file) { acl_method => "$(init.acl_method[$(testname)])"; acl_inherit => "$(init.acl_inherit[$(testname)])"; aces => { "@(init.aces[$(testname)])" }; acl_type:: acl_type => "$(init.acl_type[$(testname)])"; !acl_type:: acl_type => "generic"; acl_default:: acl_default => "$(init.acl_default[$(testname)])"; specify_default_aces:: specify_default_aces => { "@(init.specify_default_aces[$(testname)])" }; } bundle agent test_check(testname, file) { vars: "output" string => execresult("$(init.cmd) $(file)", "noshell"); classes: "regcmp_matched" expression => regcmp("$(init.regcmp[$(testname)])", "$(output)"); "notregcmp_exists" expression => isvariable("init.notregcmp[$(testname)]"); notregcmp_exists:: "notregcmp_matched" expression => regcmp("$(init.notregcmp[$(testname)])", "$(output)"); reports: !regcmp_matched|notregcmp_matched:: "Test \"$(testname)\" failed: Got \"$(output)\""; "Should contain \"$(init.regcmp[$(testname)])\""; (!regcmp_matched|notregcmp_matched)¬regcmp_exists:: "Should NOT contain \"$(init.notregcmp[$(testname)])\""; } cfengine-3.6.2/tests/acceptance/10_files/12_acl/file_edit_acl.cf0000644000175100017510000000577212316547775024020 0ustar00a10038a1003800000000000000###################################################### # # ACL tests for file editing. # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { classes: "cfengine_internal_getfacl" expression => fileexists("/var/cfengine/bin/getfacl"); "system_getfacl" expression => fileexists("/usr/bin/getfacl"); vars: linux.cfengine_internal_getfacl:: "cmd" string => "/var/cfengine/bin/getfacl"; linux.!cfengine_internal_getfacl.system_getfacl:: "cmd" string => "/usr/bin/getfacl"; windows:: "cmd" string => "C:\windows\system32\cmd.exe /C cacls"; files: "$(G.testdir)/file_plain" create => "true"; "$(G.testdir)/basetest_ext" create => "true", acl => testacl; "$(G.testdir)/file_ext" create => "true", acl => testacl; } body acl testacl { !windows:: acl_method => "append"; aces => { "user:root:wx" }; windows:: acl_method => "overwrite"; aces => { "user:Administrator:r" }; acl_inherit => "false"; } bundle agent test { meta: "test_skip_needs_work" string => "windows"; files: "$(G.testdir)/file_plain" edit_line => file_edit; files: "$(G.testdir)/file_ext" edit_line => file_edit; } bundle edit_line file_edit { insert_lines: "New line!"; } bundle agent check { vars: "file_ext_output" string => execresult("$(init.cmd) $(G.testdir)$(const.dirsep)file_ext", "noshell"); !windows:: "file_plain_output" string => execresult("/bin/ls -lZ $(G.testdir)$(const.dirsep)file_plain", "noshell"); "basetest_ext_output" string => execresult("$(init.cmd) $(G.testdir)$(const.dirsep)basetest_ext", "noshell"); classes: !windows:: "file_plain_ok" not => regcmp(".*[-rwx]{10}\+.*", "$(file_plain_output)"); "basetest_ext_ok" expression => regcmp(".*user:root:-wx.*", "$(basetest_ext_output)"); "file_ext_ok" expression => regcmp(".*user:root:-wx.*", "$(file_ext_output)"); # The !basetest_ext_ok test is in case the underlying file system does not support ACLs. "ext_ok" or => { "!basetest_ext_ok", "file_ext_ok" }; "ok" and => { "file_plain_ok", "ext_ok" }; windows:: "ok" expression => regcmp(".*Administrator:.*READ_CONTROL.*FILE_GENERIC_READ.*FILE_READ_DATA.*FILE_READ_EA.*FILE_READ_ATTRIBUTES.*", "$(file_ext_output)"); reports: DEBUG.!windows:: "Destination file permissions (should not contain a '+'): $(file_plain_output)"; "Destination file permissions (should contain \"user:root:-wx\"): $(file_ext_output)"; DEBUG.windows:: "Destination file permissions (should contain read attributes): $(file_ext_output)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/12_acl/acl.cf0000644000175100017510000000444612316547775022011 0ustar00a10038a1003800000000000000###################################################### # # ACL tests # ##################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { classes: "cfengine_internal_getfacl" expression => fileexists("/var/cfengine/bin/getfacl"); "system_getfacl" expression => fileexists("/usr/bin/getfacl"); vars: linux.cfengine_internal_getfacl:: "cmd" string => "/var/cfengine/bin/getfacl"; linux.!cfengine_internal_getfacl.system_getfacl:: "cmd" string => "/usr/bin/getfacl"; files: "$(G.testdir)$(const.dirsep)file" create => "true", acl => acl_sanity_check; } body acl acl_sanity_check { acl_method => "append"; aces => { "all:=rwx:allow" }; } ####################################################### bundle agent test { meta: "test_skip_needs_work" string => "windows"; vars: linux:: "sanity_perms" string => execresult("$(init.cmd) $(G.testdir)$(const.dirsep)file 2>&1 | $(G.grep) -v 'Removing leading'", "noshell"); classes: linux:: # Some filesystems don't have ACL capability, so we do this sanity check. "linux_go_ahead" expression => regcmp(".*other::rwx.*", "$(sanity_perms)"); vars: linux_go_ahead|windows:: "result" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub", "noshell"); !linux_go_ahead.!windows:: "result" string => ""; reports: DEBUG.!linux_go_ahead.!windows:: "ACL support not detected. Try remounting the filesystem with -o acl."; } ####################################################### bundle agent check { classes: "ok" not => regcmp(".*(error|failed).*", "$(test.result)"); reports: DEBUG:: "Tests various ACL features"; DEBUG.!ok:: "Subtest(s) failing: $(test.result)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; files: "$(G.testdir)$(const.dirsep)file" acl => acl_sanity_check_reset; } body acl acl_sanity_check_reset { acl_method => "append"; aces => { "all:-rwx:allow" }; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/0000755000175100017510000000000012412221023021734 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/02_maintain/204.cf0000644000175100017510000000530312316547775022610 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size or change owner/group (different ordering of groups) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "mode" int => "01751"; linux:: "owner" string => "sys"; "group" string => "sys"; freebsd:: "owner" string => "bin"; "group" string => "sys"; !(linux|freebsd):: "owner" string => "undefined-please-fix"; "group" string => "undefined-please-fix"; pass2.!windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("$(init.mode)"); } body perms test_perms(m) { mode => "$(m)"; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "ok" expression => strcmp("$(init.result)", "$(result)"); "not_ok" not => regcmp("$(init.result[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(init.result[$(fields)])'"; "got: $(fields) = '$(check.result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/absolute_link_and_no_move_obstructions.cf0000644000175100017510000000424712332665147032316 0ustar00a10038a1003800000000000000####################################################### # # Create an relative link to a file, expect absolute link promise to want # to change it to an absolute link (but fail to) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => init_link; } body link_from init_link { source => "$(G.etc_group)"; link_type => "relative"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; "test_suppress_fail" string => "freebsd", meta => { "redmine5261" }; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" classes => init_if_failed("test_ok"), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "absolute"; } body classes init_if_failed(c) { repair_failed => { "$(c)" }; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); # This tells us where the link points "link_target" string => filestat("$(G.testfile)", "linktarget"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "okT" not => strcmp("$(link_target)", "$(G.etc_group)"); "ok" and => { "test_ok", "okL", "okT", strcmp("$(test.inode)", "$(result)"), regcmp("\..*", "$(link_target)") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; "got this too: '$(G.etc_group)' => '$(link_target)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/symlink_link_and_no_move_obstructions.cf0000644000175100017510000000427012332665147032162 0ustar00a10038a1003800000000000000####################################################### # # Create an relative link to a file, expect subsequent symlink promise to # be unhappy with that (symlink is supposed to be synonymous with absolute) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => init_link; } body link_from init_link { source => "$(G.etc_group)"; link_type => "relative"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; "test_suppress_fail" string => "freebsd", meta => { "redmine5261" }; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" classes => test_if_ok("test_ok"), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "symlink"; } body classes test_if_ok(c) { repair_failed => { "$(c)" }; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); # This tells us where the link points "link_target" string => filestat("$(G.testfile)", "linktarget"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "okT" not => strcmp("$(link_target)", "$(G.etc_group)"); "ok" and => { "test_ok", "okL", "okT", strcmp("$(test.inode)", "$(result)"), regcmp("\..*", "$(link_target)") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; "got this too: '$(G.etc_group)' => '$(link_target)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/018.cf0000644000175100017510000000262412316547775022616 0ustar00a10038a1003800000000000000####################################################### # # Test that disable_mode => "000" in body rename works (Issue 688) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testfile)" rename => disable_file; } body rename disable_file { disable_mode => "000"; disable => "true"; } ####################################################### bundle agent check { vars: "expect[permoct]" string => "0"; "expect[nlink]" string => "1"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile).cfdisabled", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ## PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/changes_depth_search.cf0000644000175100017510000000677112412221023026402 0ustar00a10038a1003800000000000000# Checks whether a whole directory is monitored correctly with # a file changes promise. body common control { inputs => { "../../dcs.cf.sub", "../../plucked.cf.sub", "check_file_changes_log.cf.sub", }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { methods: "any" usebundle => setup_files; } bundle agent setup_files { methods: # Note: sorted, not in actual order, due to file system order sensitivity. "any" usebundle => file_make("$(G.testfile).expected", "file.content,C,Content changed file.content,C,Content changed file.content,C,Content changed file.content,C,Content changed file.content,C,Content changed file.content,N,New file found file.content.cf-before-edit,N,New file found file.content.cf-before-edit,N,New file found file.content.cf-before-edit,N,New file found file.content.cf-before-edit,R,File removed file.content.cf-before-edit,R,File removed file.created,N,New file found file.created,N,New file found file.created,N,New file found file.created,R,File removed file.created,R,File removed file.new-ignored.content,N,New file found file.new-ignored.content,N,New file found file.new-ignored.content,N,New file found file.new-ignored.content,R,File removed file.new-ignored.content,R,File removed file.new-ignored.content,R,File removed file.new-ignored.removed,N,New file found file.new-ignored.removed,N,New file found file.new-ignored.removed,N,New file found file.new-ignored.removed,R,File removed file.new-ignored.removed,R,File removed file.new-ignored.removed,R,File removed file.new-ignored.same,N,New file found file.new-ignored.same,N,New file found file.new-ignored.same,N,New file found file.new-ignored.same,R,File removed file.new-ignored.same,R,File removed file.new-ignored.same,R,File removed file.removed,N,New file found file.removed,N,New file found file.removed,N,New file found file.removed,R,File removed file.removed,R,File removed file.removed,R,File removed file.same,N,New file found subdir,N,New file found subfile.content,C,Content changed subfile.content,C,Content changed subfile.content,C,Content changed subfile.content,C,Content changed subfile.content,C,Content changed subfile.content,N,New file found subfile.content.cf-before-edit,N,New file found subfile.content.cf-before-edit,N,New file found subfile.content.cf-before-edit,N,New file found subfile.content.cf-before-edit,R,File removed subfile.content.cf-before-edit,R,File removed subfile.created,N,New file found subfile.created,N,New file found subfile.created,N,New file found subfile.created,R,File removed subfile.created,R,File removed subfile.removed,N,New file found subfile.removed,N,New file found subfile.removed,N,New file found subfile.removed,R,File removed subfile.removed,R,File removed subfile.removed,R,File removed subfile.same,N,New file found"); } bundle agent test { commands: "$(sys.cf_agent) -Dpass1 -Kf $(this.promise_filename).sub"; "$(sys.cf_agent) -Dpass2 -Kf $(this.promise_filename).sub"; "$(sys.cf_agent) -Dpass3 -Kf $(this.promise_filename).sub"; } bundle agent check { methods: "any" usebundle => check_file_changes_log("$(G.testfile).expected", "test_changes_log_ok", "test_changes_log_fail", "sorted"); classes: "ok" and => { "test_changes_log_ok", "!test_changes_log_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/413.cf.sub0000644000175100017510000000155212236160673023371 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "test" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => append_nonsense, edit_defaults => rotate; } body edit_defaults rotate { edit_backup => "rotate"; rotate => "4"; max_file_size => "300000"; } bundle edit_line append_nonsense { vars: useless0:: "contents" string => "0"; useless1:: "contents" string => "1"; useless2:: "contents" string => "2"; useless3:: "contents" string => "3"; useless4:: "contents" string => "4"; insert_lines: any:: "$(contents)"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/RM5411.cf0000644000175100017510000000114512352022221023102 0ustar00a10038a1003800000000000000# RedMine 5411: segfaults. -*- Mode: cfengine -*- body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testdir)/src" create => "true"; } bundle agent test { files: "$(G.testdir)/dst" copy_from => chained("$(G.testdir)/src"); } body copy_from chained(sourcedir) { source => "$(sourcedir)"; servers => { "x", "localhost" }; } bundle agent check { reports: # If we made it this far, we didn't segfault. "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/205.cf0000644000175100017510000000620412332665147022602 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, but DOES change owner, group (symbolic IDs) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } ####################################################### bundle agent init { vars: freebsd|solaris:: "mode" int => "04751"; !freebsd.!solaris:: "mode" int => "01751"; linux:: "owner" string => "sys"; "group" string => "sys"; freebsd:: "owner" string => "bin"; "group" string => "sys"; !(linux|freebsd):: "owner" string => "undefined-please-fix"; "group" string => "undefined-please-fix"; pass2.(freebsd|solaris):: "expect[modeoct]" string => "104755"; pass2.!(freebsd|solaris|windows):: "expect[modeoct]" string => "101755"; pass2.!windows:: "expect[uid]" string => "0"; "expect[gid]" string => "0"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("a+r"); } body perms test_perms(m) { mode => "$(m)"; owners => { "root" }; linux|hpux|solaris|qnx:: groups => { "root" }; freebsd|netbsd|openbsd|darwin|dragonfly:: groups => { "wheel" }; aix:: groups => { "system" }; cray:: groups => { "sys" }; # Still need unix_sv, sco, vmware } ####################################################### bundle agent check { vars: freebsd|solaris:: "expect[modeoct]" string => "104755"; !freebsd.!solaris.!windows:: "expect[modeoct]" string => "101755"; !windows:: "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "result: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/105.cf0000644000175100017510000000355412316547775022616 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous absolute symbolic link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile).SOURCE" create => "true"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(test.mode)), link_from => test_link; } body link_from test_link { link_type => "absolute"; source => "$(G.testfile).SOURCE"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: "expect[permoct]" string => "$(test.mode)"; "expect[nlink]" string => "1"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/check_file_changes_log.cf.sub0000644000175100017510000000341212352557236027470 0ustar00a10038a1003800000000000000# Checks whether the given content matches the content in # /var/cfengine/state/file_changes.log, but removes "unstable" # fields first (timestamp, promise ID, absolute path). # # The checks argument is a comma separated list of the following # options to check. # # - check_mtime # - sorted # # If the "check_*" flags are not given, those fields are filtered out # before comparing, since they are typically unstable. # # The "sorted" flag is to sort the log before comparing. This is # necessary for tests that depend on file system order, but the test # won't be as accurate. body file control { inputs => { "../../plucked.cf.sub" }; } bundle agent check_file_changes_log(file, pass_class, fail_class, checks) { vars: "classes_to_define" slist => splitstring($(checks), ",", 10); classes: "$(classes_to_define)" expression => "any"; "actual_exists" expression => fileexists("$(file).actual"); files: !actual_exists:: "$(file).actual" copy_from => local_cp("$(sys.workdir)/state/file_changes.log"); any:: "$(file).actual" edit_line => remove_unstable_fields($(file)); methods: sorted:: "any" usebundle => dcs_sort("$(file).actual", "$(file).actual.sort"); "any" usebundle => dcs_if_diff("$(file).actual.sort", "$(file)", "$(pass_class)", "$(fail_class)"); !sorted:: "any" usebundle => dcs_if_diff("$(file).actual", "$(file)", "$(pass_class)", "$(fail_class)"); } bundle edit_line remove_unstable_fields(file) { replace_patterns: # Get rid of timestamp, promise ID and absolute path. "^[0-9]+,[^,]*,[^,]+/" replace_with => value(""); delete_lines: !check_mtime:: ".*,S,Modified time:.*"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/017.cf0000644000175100017510000000163612243421446022600 0ustar00a10038a1003800000000000000####################################################### # # Test that copy_from body with source does not crash (Issue 687) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "$(G.testdir)/." create => "true", move_obstructions => "true", copy_from => update_nobackup; } body copy_from update_nobackup() { copy_backup => "false"; } ####################################################### bundle agent check { reports: cfengine_3:: "$(this.promise_filename) Pass"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/symlink_link_kept.cf0000644000175100017510000000413612332665147026024 0ustar00a10038a1003800000000000000####################################################### # # Create an absolute link to a file, expect subsequent symlink promise to # be happy with that # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).linked_to" create => "true"; "$(G.testfile)" create => "true", move_obstructions => "true", link_from => init_link; } body link_from init_link { source => "$(G.testfile).linked_to"; link_type => "absolute"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "inode" string => filestat("$(G.testfile).linked_to", "ino"); files: "$(G.testfile)" classes => test_if_ok("test_ok"), link_from => test_link; } body link_from test_link { source => "$(G.testfile).linked_to"; link_type => "symlink"; } body classes test_if_ok(c) { promise_kept => { "$(c)" }; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); # This tells us where the link points "link_target" string => filestat("$(G.testfile)", "linktarget"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "ok" and => { "test_ok", "okL", strcmp("$(test.inode)", "$(result)"), strcmp("$(link_target)", "$(G.testfile).linked_to") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; "got this too: '$(G.testfile).linked_to' => '$(link_target)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/112.cf0000644000175100017510000000266012316547775022611 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous link with default and move_obstructions # to succeed # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); classes: "ok" expression => strcmp("$(test.inode)", "$(result)"); reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/007.cf0000644000175100017510000000347612316547775022622 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with binary compare to succeed # but not change owner/group # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" string => filestat("$(G.etc_group)", "modeoct"); files: "$(G.testfile)" create => "true", perms => test_og, copy_from => test_copy; } body perms test_og { owners => { "3" }; groups => { "3" }; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "binary"; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "$(test.mode)"; "expect[uid]" string => "3"; "expect[gid]" string => "3"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testdir)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/015.cf0000644000175100017510000000167112243421446022575 0ustar00a10038a1003800000000000000####################################################### # # Test that we can supply relative filename to link_from # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "$(G.testdir)/destdir" link_from => sync_cp("./srcdirrr"); } body link_from sync_cp(from) { source => "$(from)"; } ####################################################### bundle agent check { classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/011.cf0000644000175100017510000000324012352022221022550 0ustar00a10038a1003800000000000000####################################################### # # Test that symlinks outside of copying root are NOT set aside while copying trees of directorise (Issue 585) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testdir)/srcdir/" create => "true"; "$(G.testdir)/srcdir/foo" create => "true"; "$(G.testdir)/realdestdir/" create => "true"; "$(G.testdir)/destdir" comment => "Create a relative link to the target.", link_from => ln_s("$(G.testdir)/realdestdir"); } body link_from ln_s(x) { link_type => "relative"; source => "$(x)"; when_no_source => "nop"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testdir)/destdir/foo" copy_from => test_sync_cp("$(G.testdir)/srcdir/foo"); } body copy_from test_sync_cp(from) { source => "$(from)"; } ####################################################### bundle agent check { vars: "expect" string => "symlink"; "result" string => filestat("$(G.testdir)/destdir", "type"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/206.cf0000644000175100017510000000565412332665147022613 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, but DOES change owner, group - numeric UID/GID # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } ####################################################### bundle agent init { vars: freebsd|solaris:: "mode" int => "04751"; !freebsd.!solaris:: "mode" int => "01751"; linux:: "owner" string => "sys"; "group" string => "sys"; freebsd:: "owner" string => "bin"; "group" string => "sys"; !(linux|freebsd):: "owner" string => "undefined-please-fix"; "group" string => "undefined-please-fix"; pass2.(freebsd|solaris):: "expect[modeoct]" string => "104755"; pass2.!(freebsd|solaris|windows):: "expect[modeoct]" string => "101755"; pass2.!windows:: "expect[uid]" string => "0"; "expect[gid]" string => "0"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("a+r"); } body perms test_perms(m) { mode => "$(m)"; owners => { "456" }; groups => { "567" }; } ####################################################### bundle agent check { vars: freebsd|solaris:: "expect[modeoct]" string => "104755"; !freebsd.!solaris.!windows:: "expect[modeoct]" string => "101755"; !windows:: "expect[uid]" string => "456"; "expect[gid]" string => "567"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "result: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/111.x.cf0000644000175100017510000000312712316547775023055 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous none no-filename link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", link_from => test_link; } body link_from test_link { link_type => "none"; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/209.cf0000644000175100017510000000533512332665147022612 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, but DOES change owner, group, because # we start with a non-registered user/group name. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } ####################################################### bundle agent init { vars: freebsd|solaris:: "mode" int => "04751"; !freebsd.!solaris:: "mode" int => "01751"; any:: "owner" string => "786756"; "group" string => "786756"; pass2.!windows:: "expect[modeoct]" string => "\d+$(init.mode)"; "expect[uid]" string => "$(init.owner)"; "expect[gid]" string => "$(init.group)"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; compare => "mtime"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { # Mode, owner is unspecified - should not change anything groups => { "23459", "none" }; # Should change to 23459 } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "\d+$(init.mode)"; "expect[uid]" string => "$(init.owner)"; "expect[gid]" string => "23459"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "result: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/copy-relative-link.cf0000644000175100017510000000177212332665147026017 0ustar00a10038a1003800000000000000# Test that copying relative link does not mangle it (Mantis #1117) body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { commands: "$(G.mkdir) -p $(G.testdir)/a"; "$(G.touch) $(G.testdir)/a/dest"; "$(G.ln) -s dest $(G.testdir)/a/link"; } bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testdir)/b" copy_from => local_cp("$(G.testdir)/a"), depth_search => recurse("inf"); } bundle agent check { vars: "expect" string => "dest"; "result" string => filestat("$(G.testdir)/b/link", "linktarget"); classes: "ok" expression => strcmp("$(result)", "$(expect)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/414.cf0000644000175100017510000000245212243421446022576 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { commands: "$(G.touch) $(G.testfile)"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub"; commands: "$(cmd)"; "$(cmd) -D useless1"; "$(cmd) -D useless2"; "$(cmd) -D useless3"; "$(cmd) -D useless4"; } ####################################################### bundle agent check { classes: "filestillthere" expression => fileexists("$(G.testfile)"); "fileisrotated" expression => fileexists("$(G.testfile).cf-before-edit.1"); "nooverflow" not => fileexists("$(G.testfile).cf-before-edit.2"); "ok" and => { "filestillthere", "fileisrotated", "nooverflow" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/114.cf0000644000175100017510000000313012316547775022604 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous link with symlink and move_obstructions # to succeed # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "symlink"; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "ok" and => { "okL", strcmp("$(test.inode)", "$(result)") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/103.cf0000644000175100017510000000344112316547775022607 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous symbolic link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "symlink"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: "expect[permoct]" string => "$(test.mode)"; "expect[nlink]" string => "1"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/004.cf0000644000175100017510000000347512316547775022616 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with atime compare to succeed # but not change owner/group # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" string => filestat("$(G.etc_group)", "modeoct"); files: "$(G.testfile)" create => "true", perms => test_og, copy_from => test_copy; } body perms test_og { owners => { "3" }; groups => { "3" }; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "atime"; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "$(test.mode)"; "expect[uid]" string => "3"; "expect[gid]" string => "3"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/203.cf0000644000175100017510000000555212316547775022615 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, owner, group (different ordering of groups) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "mode" int => "01751"; linux:: "owner" string => "sys"; "group" string => "sys"; freebsd:: "owner" string => "bin"; "group" string => "sys"; !(linux|freebsd):: "owner" string => "undefined-please-fix"; "group" string => "undefined-please-fix"; pass2.!windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("$(init.mode)", "$(init.owner)", "$(init.group)"); } body perms test_perms(m, o, g) { mode => "$(m)"; owners => { "root", "$(o)" }; linux:: groups => { "root", "$(g)" }; freebsd:: groups => { "wheel", "$(g)" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "ok" expression => strcmp("$(init.result)", "$(result)"); "not_ok" not => regcmp("$(init.result[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(init.result[$(fields)])'"; "got: $(fields) = '$(check.result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/changes_update_hashes.cf0000644000175100017510000001714612352557236026611 0ustar00a10038a1003800000000000000# Test that monitoring file status of an updated file gives right promises # status. body common control { inputs => { "../../default.cf.sub", "check_file_changes_log.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { files: # Not in database. "$(G.testfile).update.new" create => "true"; # Should be in database. "$(G.testfile).update.same" create => "true", changes => test_changes_update; "$(G.testfile).update.updated" create => "true", changes => test_changes_update; # Not in database. "$(G.testfile).noupdate.new" create => "true"; # Should be in database. "$(G.testfile).noupdate.same" create => "true", changes => test_changes_noupdate; "$(G.testfile).noupdate.updated" create => "true", changes => test_changes_noupdate; } bundle agent test { files: "$(G.testfile).update.updated" edit_line => insert_text; "$(G.testfile).noupdate.updated" edit_line => insert_text; methods: # Update each file twice. We cannot reuse the bundles because CFEngine # will skip bundles it has done before. "test_update_new" usebundle => test_update_new; "test_update_same" usebundle => test_update_same; "test_update_updated" usebundle => test_update_updated; "test_update_new_again" usebundle => test_update_new_again; "test_update_same_again" usebundle => test_update_same_again; "test_update_updated_again" usebundle => test_update_updated_again; "test_noupdate_new" usebundle => test_noupdate_new; "test_noupdate_same" usebundle => test_noupdate_same; "test_noupdate_updated" usebundle => test_noupdate_updated; "test_noupdate_new_again" usebundle => test_noupdate_new_again; "test_noupdate_same_again" usebundle => test_noupdate_same_again; "test_noupdate_updated_again" usebundle => test_noupdate_updated_again; } bundle edit_line insert_text { insert_lines: "Text"; } bundle agent test_update_new { files: "$(G.testfile).update.new" changes => test_changes_update, classes => kept_repaired_notkept("test_update_new_kept", "test_update_new_repaired", "test_update_new_notkept"); } bundle agent test_update_same { files: "$(G.testfile).update.same" changes => test_changes_update, classes => kept_repaired_notkept("test_update_same_kept", "test_update_same_repaired", "test_update_same_notkept"); } bundle agent test_update_updated { files: "$(G.testfile).update.updated" changes => test_changes_update, classes => kept_repaired_notkept("test_update_updated_kept", "test_update_updated_repaired", "test_update_updated_notkept"); } bundle agent test_update_new_again { files: "$(G.testfile).update.new" changes => test_changes_update, classes => kept_repaired_notkept("test_update_new_kept", "test_update_new_repaired", "test_update_new_notkept"); } bundle agent test_update_same_again { files: "$(G.testfile).update.same" changes => test_changes_update, classes => kept_repaired_notkept("test_update_same_kept", "test_update_same_repaired", "test_update_same_notkept"); } bundle agent test_update_updated_again { files: "$(G.testfile).update.updated" changes => test_changes_update, classes => kept_repaired_notkept("test_update_updated_kept", "test_update_updated_repaired", "test_update_updated_notkept"); } bundle agent test_noupdate_new { files: "$(G.testfile).noupdate.new" changes => test_changes_noupdate, classes => kept_repaired_notkept("test_noupdate_new_kept", "test_noupdate_new_repaired", "test_noupdate_new_notkept"); } bundle agent test_noupdate_same { files: "$(G.testfile).noupdate.same" changes => test_changes_noupdate, classes => kept_repaired_notkept("test_noupdate_same_kept", "test_noupdate_same_repaired", "test_noupdate_same_notkept"); } bundle agent test_noupdate_updated { files: "$(G.testfile).noupdate.updated" changes => test_changes_noupdate, classes => kept_repaired_notkept("test_noupdate_updated_kept", "test_noupdate_updated_repaired", "test_noupdate_updated_notkept"); } bundle agent test_noupdate_new_again { files: "$(G.testfile).noupdate.new" changes => test_changes_noupdate, classes => kept_repaired_notkept("test_noupdate_new_kept", "test_noupdate_new_repaired", "test_noupdate_new_notkept"); } bundle agent test_noupdate_same_again { files: "$(G.testfile).noupdate.same" changes => test_changes_noupdate, classes => kept_repaired_notkept("test_noupdate_same_kept", "test_noupdate_same_repaired", "test_noupdate_same_notkept"); } bundle agent test_noupdate_updated_again { files: "$(G.testfile).noupdate.updated" changes => test_changes_noupdate, classes => kept_repaired_notkept("test_noupdate_updated_kept", "test_noupdate_updated_repaired", "test_noupdate_updated_notkept"); } body changes test_changes_update { hash => "sha256"; report_changes => "all"; update_hashes => "yes"; } body changes test_changes_noupdate { hash => "sha256"; report_changes => "all"; update_hashes => "no"; } body classes kept_repaired_notkept(kept, repaired, notkept) { promise_kept => { "$(kept)" }; promise_repaired => { "$(repaired)" }; repair_failed => { "$(notkept)" }; repair_denied => { "$(notkept)" }; repair_timeout => { "$(notkept)" }; } bundle agent check { vars: "classes_set" slist => classesmatching("test_.*"); methods: # Seems like CFEngine does two passes over files where we don't update # hash, so the last four entries should really be two entries. # If the number of "Content changed" lines is wrong, this is the first # place to look. "any" usebundle => file_make("$(G.testfile).file_changes_log", "TEST.cfengine.update.updated,C,Content changed TEST.cfengine.noupdate.updated,C,Content changed TEST.cfengine.noupdate.updated,C,Content changed TEST.cfengine.noupdate.updated,C,Content changed TEST.cfengine.noupdate.updated,C,Content changed"); "any" usebundle => check_file_changes_log("$(G.testfile).file_changes_log", "test_changes_log_ok", "test_changes_log_fail", ""); classes: "ok" and => { "checksum_alerts", "test_update_new_repaired", "!test_update_new_notkept", "!test_update_same_repaired", "test_update_same_kept", "!test_update_same_notkept", "test_update_updated_repaired", "!test_update_updated_notkept", "test_noupdate_new_repaired", "!test_noupdate_new_notkept", "!test_noupdate_same_repaired", "test_noupdate_same_kept", "!test_noupdate_same_notkept", "!test_noupdate_updated_repaired", "test_noupdate_updated_notkept", "test_changes_log_ok", "!test_changes_log_fail", }; reports: DEBUG:: "Set classes: $(classes_set)"; !checksum_alerts.DEBUG:: "The checksum_alerts class was NOT set as expected."; checksum_alerts.EXTRA:: "The checksum_alerts class was set as expected."; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/relative_link_and_no_move_obstructions.cf0000644000175100017510000000416412332665147032311 0ustar00a10038a1003800000000000000####################################################### # # Create an absolute link to a file, expect relative link promise to want # to change it to an relative link (but fail to) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => init_link; } body link_from init_link { source => "$(G.etc_group)"; link_type => "absolute"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" classes => init_if_failed("test_ok"), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "relative"; } body classes init_if_failed(c) { repair_failed => { "$(c)" }; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); # This tells us where the link points "link_target" string => filestat("$(G.testfile)", "linktarget"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "ok" and => { "test_ok", "okL", strcmp("$(test.inode)", "$(result)"), # Might be slightly different from link_target because of redundant '../../'. regcmp("/.*/group", "$(link_target)") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; "got this too: '$(G.etc_group)' => '$(link_target)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/absolute_link_and_move_obstructions.cf0000644000175100017510000000371112332665147031615 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous link with absolute and move_obstructions # to succeed # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "absolute"; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); # This tells us where the link points "link_target" string => filestat("$(G.testfile)", "linktarget"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "ok" and => { "okL", strcmp("$(test.inode)", "$(result)"), # Might be slightly different from link_target because of redundant '../../'. regcmp("/.*/group", "$(link_target)") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; "got this too: '$(G.etc_group)' => '$(link_target)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/102.cf0000644000175100017510000000337312316547775022612 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous hard link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "hardlink"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/016.cf0000644000175100017510000000257512352022221022567 0ustar00a10038a1003800000000000000####################################################### # # Test that timestamped copying adds .cfsaved suffix (Issue 666) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testdir)/afile" create => "true"; # We can't use files promise here as it will remember we have created the file # and will not generate backup file which we are trying to get. commands: "$(G.echo) LimpBizkit > $(G.testdir)/destfile" contain => shell; } body contain shell { useshell => "true"; } ####################################################### bundle agent test { files: "$(G.testdir)/destfile" copy_from => cp_2_file("$(G.testdir)/afile"); } body copy_from cp_2_file(x) { source => "$(x)"; copy_backup => "timestamp"; compare => "digest"; } ####################################################### bundle agent check { files: "$(G.testdir)/destfile.*\.cfsaved" touch => "true", classes => if_repaired("ok"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/008.cf0000644000175100017510000000340612316547775022614 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with exists compare to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "exists"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/403.x.cf0000644000175100017510000000264412316547775023064 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { default_repository => "non-absolute-path"; # Intentionally wrong } bundle agent init { files: "$(g.repofile).*" delete => init_delete; "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "test" not => fileexists("$(G.testfile).cfsaved"); "repo" expression => fileexists("$(g.repofile).cfsaved"); "ok" and => { "test", "repo" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/104.cf0000644000175100017510000000345312316547775022613 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous relative symbolic link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "relative"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: "expect[permoct]" string => "$(test.mode)"; "expect[nlink]" string => "1"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/changes_depth_search_last_file.cf.sub0000644000175100017510000000107412352557236031230 0ustar00a10038a1003800000000000000body common control { inputs => { "../../dcs.cf.sub", "../../plucked.cf.sub", }; bundlesequence => { "init", "test" }; } bundle agent init { methods: pass1|pass3:: "any" usebundle => file_make("$(G.testdir)/file", "content"); files: pass2|pass4:: "$(G.testdir)/file" delete => tidy; } body changes changes_body { report_changes => "all"; update_hashes => "true"; } bundle agent test { files: "$(G.testdir)" depth_search => recurse("inf"), changes => changes_body; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/changes_depth_search_last_file.cf0000644000175100017510000000251112352557236030435 0ustar00a10038a1003800000000000000# Checks whether a whole directory is monitored correctly with # a file changes promise even when all files are removed. body common control { inputs => { "../../dcs.cf.sub", "../../plucked.cf.sub", "check_file_changes_log.cf.sub", }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { methods: "any" usebundle => setup_files; } bundle agent setup_files { methods: "any" usebundle => file_make("$(G.testfile).expected", "file,N,New file found file,R,File removed file,N,New file found file,R,File removed"); } bundle agent test { commands: "$(sys.cf_agent) -Dpass1 -Kf $(this.promise_filename).sub"; "$(sys.cf_agent) -Dpass2 -Kf $(this.promise_filename).sub"; "$(sys.cf_agent) -Dpass3 -Kf $(this.promise_filename).sub"; "$(sys.cf_agent) -Dpass4 -Kf $(this.promise_filename).sub"; } bundle agent check { methods: "any" usebundle => check_file_changes_log("$(G.testfile).expected", "test_changes_log_ok", "test_changes_log_fail", ""); classes: "ok" and => { "test_changes_log_ok", "!test_changes_log_fail", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/207.cf0000644000175100017510000000565312332665147022613 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, but DOES change owner, group (numeric IDs) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } ####################################################### bundle agent init { vars: freebsd|solaris:: "mode" int => "04751"; !freebsd.!solaris:: "mode" int => "01751"; linux:: "owner" string => "sys"; "group" string => "sys"; freebsd:: "owner" string => "bin"; "group" string => "sys"; !(linux|freebsd):: "owner" string => "undefined-please-fix"; "group" string => "undefined-please-fix"; pass2.(freebsd|solaris):: "expect[modeoct]" string => "104755"; pass2.!(freebsd|solaris|windows):: "expect[modeoct]" string => "101755"; pass2.!windows:: "expect[uid]" string => "333"; "expect[gid]" string => "444"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("a+r"); } body perms test_perms(m) { mode => "$(m)"; owners => { "333" }; groups => { "444" }; } ####################################################### bundle agent check { vars: freebsd|solaris:: "expect[modeoct]" string => "104755"; !freebsd.!solaris.!windows:: "expect[modeoct]" string => "101755"; !windows:: "expect[uid]" string => "333"; "expect[gid]" string => "444"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "result: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/changes_promise_status.cf0000644000175100017510000000531712316547775027061 0ustar00a10038a1003800000000000000# Test that monitoring file status gives the right promise status body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { files: "$(G.testdir)/existingfile" create => "true", changes => test_changes; } bundle agent test { files: "$(G.testdir)/nosuchfile" changes => test_changes, classes => kept_repaired_notkept("nosuchfile_kept", "nosuchfile_repaired", "nosuchfile_notkept"); "$(G.testdir)/newfile" create => "true", changes => test_changes, classes => kept_repaired_notkept("newfile_kept", "newfile_repaired", "newfile_notkept"); "$(G.testdir)/existingfile" changes => test_changes, classes => kept_repaired_notkept("existingfile_kept", "existingfile_repaired", "existingfile_notkept"); } body changes test_changes { hash => "sha256"; report_changes => "all"; update_hashes => "yes"; } body classes kept_repaired_notkept(kept, repaired, notkept) { promise_kept => { "$(kept)" }; promise_repaired => { "$(repaired)" }; repair_failed => { "$(notkept)" }; repair_denied => { "$(notkept)" }; repair_timeout => { "$(notkept)" }; } bundle agent check { classes: "ok" and => { "!nosuchfile_kept", "!nosuchfile_repaired", "nosuchfile_notkept", # Kept state can be either set or unset depending on number of passes. # Let's not depend on either. #"!newfile_kept", "newfile_repaired", "!newfile_notkept", "existingfile_kept", "!existingfile_repaired", "!existingfile_notkept", }; reports: DEBUG.nosuchfile_kept:: "nosuchfile_kept is set, but shouldn't be."; DEBUG.nosuchfile_repaired:: "nosuchfile_repaired is set, but shouldn't be."; DEBUG.!nosuchfile_notkept:: "nosuchfile_notkept is not set, but should be."; DEBUG.newfile_kept:: "newfile_kept is set, but shouldn't be. (tolerated, for now)"; DEBUG.!newfile_repaired:: "newfile_repaired is not set, but should be."; DEBUG.newfile_notkept:: "newfile_notkept is set, but shouldn't be."; DEBUG.!existingfile_kept:: "existingfile_kept is not set, but should be."; DEBUG.existingfile_repaired:: "existingfile_repaired is set, but shouldn't be."; DEBUG.existingfile_notkept:: "existingfile_notkept is set, but shouldn't be."; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/414.cf.sub0000644000175100017510000000127512243421446023370 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "test" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => append_nonsense, edit_defaults => rotate; } body edit_defaults rotate { edit_backup => "rotate"; max_file_size => "300000"; } bundle edit_line append_nonsense { vars: "ns" string => execresult("$(G.date) +%N", "noshell"); insert_lines: "$(ns)"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/changes_depth_search.cf.sub0000644000175100017510000000645212352557236027213 0ustar00a10038a1003800000000000000body common control { inputs => { "../../dcs.cf.sub", "../../plucked.cf.sub", }; bundlesequence => { "init", "test" }; } bundle agent init { files: "$(G.testdir)" depth_search => recurse("inf"), file_select => all, delete => tidy; methods: "any" usebundle => setup_files; "any" usebundle => init_monitoring; } bundle agent setup_files { methods: "any" usebundle => file_make("$(G.testdir)/file.same", "same"); "any" usebundle => file_make("$(G.testdir)/file.removed", "removed"); #"any" usebundle => file_make("$(G.testdir)/file.created", "created"); "any" usebundle => file_make("$(G.testdir)/file.content", "old content"); "any" usebundle => file_make("$(G.testdir)/file.always-ignored.same", "same"); "any" usebundle => file_make("$(G.testdir)/file.always-ignored.removed", "removed"); #"any" usebundle => file_make("$(G.testdir)/file.always-ignored.created", "created"); "any" usebundle => file_make("$(G.testdir)/file.always-ignored.content", "old content"); "any" usebundle => file_make("$(G.testdir)/file.new-ignored.same", "same"); "any" usebundle => file_make("$(G.testdir)/file.new-ignored.removed", "removed"); #"any" usebundle => file_make("$(G.testdir)/file.new-ignored.created", "created"); "any" usebundle => file_make("$(G.testdir)/file.new-ignored.content", "old content"); "any" usebundle => file_make("$(G.testdir)/subdir/subfile.same", "same"); #"any" usebundle => file_make("$(G.testdir)/subdir/subfile.created", "subfile created"); "any" usebundle => file_make("$(G.testdir)/subdir/subfile.removed", "subfile removed"); "any" usebundle => file_make("$(G.testdir)/subdir/subfile.content", "subfile old content"); } bundle agent init_monitoring { files: "$(G.testdir)" depth_search => recurse("inf"), file_select => init_select, changes => changes_body; } body file_select init_select { leaf_name => { ".*always-ignored.*" }; file_result => "!leaf_name"; } body changes changes_body { report_changes => "all"; update_hashes => "true"; } bundle agent test { vars: "remove" slist => { "file.removed", "file.always-ignored.removed", "file.new-ignored.removed", "subdir/subfile.removed", }; "create" slist => { "file.created", "file.always-ignored.created", "file.new-ignored.created", "subdir/subfile.created", }; "modify" slist => { "file.content", "file.always-ignored.content", "file.new-ignored.content", "subdir/subfile.content", }; files: "$(G.testdir)/$(remove)" delete => tidy; "$(G.testdir)/$(create)" create => "true"; "$(G.testdir)/$(modify)" edit_line => insert_lines("extra content"); files: "$(G.testdir)" depth_search => recurse("inf"), file_select => test_select, changes => changes_body; } body file_select test_select { leaf_name => { ".*ignored.*" }; file_result => "!leaf_name"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/201.cf0000644000175100017510000000445312316547775022612 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "mode" int => "01751"; pass2.!windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m) { mode => "$(m)"; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("$(init.mode)"); } body perms test_perms(m) { mode => "$(m)"; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "ok" expression => strcmp("$(init.result)", "$(result)"); "not_ok" not => regcmp("$(init.result[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(init.result[$(fields)])'"; "got: $(fields) = '$(check.result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/406.x.cf0000644000175100017510000000260412316547775023063 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(g.repofile).*" delete => init_delete; "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" repository => "non-absolute-path", # Intentionally wrong move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "test" not => fileexists("$(G.testfile).cfsaved"); "repo" expression => fileexists("$(g.repofile).cfsaved"); "ok" and => { "test", "repo" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/013.cf0000644000175100017510000000347212352022221022561 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testdir)/srcdir/" create => "true"; "$(G.testdir)/srcdir/intermediate/" create => "true"; "$(G.testdir)/srcdir/intermediate/intermediate2/" create => "true"; "$(G.testdir)/srcdir/intermediate/intermediate2/foo" create => "true"; "$(G.testdir)/realdestdir/" create => "true"; "$(G.testdir)/destdir" comment => "Create a relative link to the target.", link_from => ln_s("$(G.testdir)/realdestdir"); } body link_from ln_s(x) { link_type => "relative"; source => "$(x)"; when_no_source => "nop"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testdir)/destdir" copy_from => test_sync_cp("$(G.testdir)/srcdir"), depth_search => recurse("inf"); } body copy_from test_sync_cp(from) { source => "$(from)"; purge => "true"; preserve => "true"; } ####################################################### bundle agent check { vars: "expect" string => "symlink"; "result" string => filestat("$(G.testdir)/destdir", "type"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/408.cf0000644000175100017510000000301412316547775022613 0ustar00a10038a1003800000000000000####################################################### # # Copy symlink over file, test that file is correctly saved aside. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "srcfile" string => "$(G.testfile).source"; } ####################################################### bundle agent init { files: "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; "$(g.srcfile)" move_obstructions => "true", link_from => init_link; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } body link_from init_link { source => "$(G.true)"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testfile)" move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(g.srcfile)"; compare => "digest"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile).cfsaved"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/relative_link_and_move_obstructions.cf0000644000175100017510000000377312332665147031622 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous link with relative and move_obstructions # to succeed # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; "test_suppress_fail" string => "freebsd", meta => { "redmine5261" }; vars: "inode" string => filestat("$(G.etc_group)", "ino"); files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "relative"; } ####################################################### bundle agent check { vars: "result" string => filestat(filestat("$(G.testfile)", "linktarget"), "ino"); "Lresult" string => filestat("$(G.testfile)", "ino"); # This tells us where the link points "link_target" string => filestat("$(G.testfile)", "linktarget"); classes: "okL" not => strcmp("$(test.inode)", "$(Lresult)"); "okT" not => strcmp("$(link_target)", "$(G.etc_group)"); "ok" and => { "okL", "okT", strcmp("$(test.inode)", "$(result)"), regcmp("\..*", "$(link_target)") }; reports: DEBUG:: "expected: '$(test.inode)'"; "got: '$(Lresult)' => '$(result)'"; "got this too: '$(G.etc_group)' => '$(link_target)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/003.cf0000644000175100017510000000340412316547775022605 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with ctime compare to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "ctime"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/407.x.cf0000644000175100017510000000330412332665147023052 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; "repofile" string => "/var/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(g.repofile).*" delete => init_delete; "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" repository => "tmp", # Intentionally wrong move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "test" not => fileexists("$(G.testfile).cfsaved"); "repo" expression => fileexists("$(g.repofile).cfsaved"); "ok" and => { "test", "repo" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(g.repofile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/backup_repository.cf0000644000175100017510000000201312352022221026010 0ustar00a10038a1003800000000000000# Test that repository contains backup of file after updating it. body common control { bundlesequence => { default("$(this.promise_filename)") }; inputs => { "../../default.cf.sub" }; } body agent control { default_repository => $(init.repodir); } bundle agent init { vars: "repodir" string => "$(sys.workdir)/repository"; methods: "" usebundle => dcs_fini($(repodir)); "" usebundle => file_make("$(G.testfile).orig", "Original content"); "" usebundle => file_make("$(G.testfile).new", "Updated content"); "" usebundle => file_make("$(G.testfile).copy", "Original content"); } bundle agent test { methods: "" usebundle => file_copy("$(G.testfile).new", "$(G.testfile).copy"); } bundle agent check { vars: "backups" slist => findfiles("$(init.repodir)/*cfsaved"); methods: "any" usebundle => dcs_check_diff("$(G.testfile).orig", $(backups), "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/411.cf0000644000175100017510000000263112352022221022557 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 0 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "someline"; "expected" string => "someline"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" rename => rotate, action => warn_only; } body rename rotate { rotate => "0"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/005.cf0000644000175100017510000000340212316547775022605 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with hash compare to succeed # but not change owner/group # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" string => filestat("$(G.etc_group)", "modeoct"); files: "$(G.testfile)" create => "true", perms => test_og, copy_from => test_copy; } body perms test_og { owners => { "3" }; groups => { "3" }; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "hash"; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "$(test.mode)"; "expect[uid]" string => "3"; "expect[gid]" string => "3"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/412.cf0000644000175100017510000000234112243421446022571 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { commands: "$(G.touch) $(G.testfile)"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub"; commands: "$(cmd)"; "$(cmd) -D superfluous"; } ####################################################### bundle agent check { classes: "filestillthere" expression => fileexists("$(G.testfile)"); "fileisrotated" expression => fileexists("$(G.testfile).cf-before-edit.1"); "nounnamedbackup" not => fileexists("$(G.testfile).cf-before-edit"); "ok" and => { "filestillthere", "fileisrotated", "nounnamedbackup" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/006.cf0000644000175100017510000000347712316547775022622 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with digest compare to succeed # but not change owner/group # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" string => filestat("$(G.etc_group)", "modeoct"); files: "$(G.testfile)" create => "true", perms => test_og, copy_from => test_copy; } body perms test_og { owners => { "3" }; groups => { "3" }; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "digest"; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "$(test.mode)"; "expect[uid]" string => "3"; "expect[gid]" string => "3"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/009.cf0000644000175100017510000000442312316547775022615 0ustar00a10038a1003800000000000000####################################################### # # Test that copying file by relative symlink works # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testdir)/linkdir/" comment => "Create a directory."; "$(G.testdir)/linkdir/another/" comment => "Create another directory."; "$(G.testdir)/linkdir/another/target" comment => "A target file.", create => "true"; "$(G.testdir)/linkdir/link" comment => "Create a relative link to the target.", link_from => ln_s("$(G.testdir)/linkdir/another/target"); } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testdir)/copy_file" comment => "Copy the file behind the link.", perms => test_perms($(mode)), copy_from => cp_2_file("$(G.testdir)/linkdir/link"); } body link_from ln_s(x) { link_type => "relative"; source => "$(x)"; when_no_source => "nop"; } body copy_from cp_2_file(x) { source => "$(x)"; compare => "binary"; copy_backup => "false"; copylink_patterns => { ".*" }; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "\d+$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)$(const.dirsep)copy_file", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/410.cf0000644000175100017510000000236212352022221022557 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_null)"; compare => "digest"; } ####################################################### bundle agent test { files: "$(G.testfile)" rename => rotate, action => warn_only; } body rename rotate { rotate => "1"; } ####################################################### bundle agent check { classes: "filestillthere" expression => fileexists("$(G.testfile)"); "fileisnotrotated" not => fileexists("$(G.testfile).1"); "ok" and => { "filestillthere", "fileisnotrotated" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/002.cf0000644000175100017510000000340412316547775022604 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with mtime compare to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_group)"; compare => "mtime"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/0000755000175100017510000000000012346062163023406 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/402.cf0000644000175100017510000000332412316547775024245 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { default_repository => "/var/tmp"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; "repofile" string => "_tmp_TEST.cfengine"; "repo" string => "/var/tmp"; } ####################################################### bundle agent init { files: "$(g.repofile).*" delete => init_delete; "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "test" not => fileexists("$(G.testfile).cfsaved"); "repo" expression => fileexists("$(g.repo)/$(g.repofile).cfsaved"); "ok" and => { "test", "repo" }; reports: DEBUG:: "testfile = $(G.testfile)"; "repo = $(g.repo)"; "repofile = $(g.repofile)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/405.cf0000644000175100017510000000361412332665147024242 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; "repofile" string => "_tmp_TEST.cfengine"; "repo" string => "/var/tmp"; } ####################################################### bundle agent init { files: "$(g.repo)/$(g.repofile).*" delete => init_delete; "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", repository => "$(g.repo)", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "test" not => fileexists("$(G.testfile).cfsaved"); "repo" expression => fileexists("$(g.repo)/$(g.repofile).cfsaved"); "ok" and => { "test", "repo" }; reports: DEBUG:: "testfile = $(G.testfile)"; "repo = $(g.repo)"; "repofile = $(g.repofile)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); "any" usebundle => dcs_fini("$(g.repo)/$(g.repofile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/edit_immutable.cf0000644000175100017510000000524712332665147026722 0ustar00a10038a1003800000000000000####################################################### # # Redmine#3184: Test editing of an immutable file # Redmine#2100: Test chmod of an immutable file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle common chattr { vars: "chattr" string => "/usr/bin/chattr"; classes: "have_chattr" expression => fileexists($(chattr)); } bundle agent init { files: "$(G.testfile)" create => "true"; } bundle agent test { methods: "1" usebundle => test_setup($(G.testfile)); "2" usebundle => test_edit($(G.testfile)); "2" usebundle => test_chmod($(G.testfile)); "3" usebundle => test_teardown($(G.testfile)); } bundle agent test_setup(file) { commands: have_chattr:: "$(chattr.chattr)" args => "+i $(file)", classes => scoped_classes_generic("namespace", "chattr"); } bundle agent test_edit(file) { files: have_chattr:: "$(file)" edit_line => test_edit_line(), classes => scoped_classes_generic("namespace", "test"); } bundle agent test_chmod(file) { files: have_chattr:: "$(file)" perms => m("755"), classes => scoped_classes_generic("namespace", "chmod"); } body perms m(mode) { mode => "$(mode)"; } bundle agent test_teardown(file) { commands: have_chattr:: "$(chattr.chattr)" args => "-i $(file)", classes => scoped_classes_generic("namespace", "chattr"); } bundle edit_line test_edit_line() { insert_lines: "blah"; } ####################################################### bundle agent check { classes: # we're OK if: # - we don't have chattr # - chattr failed to DTRT (e.g. we're not root) # - the test failed to edit # - the test denied the chmod (TODO: should it be "denied" or "failed"? "ok" expression => "!have_chattr|chattr_failed|(test_failed.!test_kept.!test_denied.!test_timeout.!test_repaired.!chmod_failed.!chmod_kept.chmod_denied.!chmod_timeout.!chmod_repaired)"; methods: "report" usebundle => dcs_report_generic_classes("test"); "report" usebundle => dcs_report_generic_classes("chmod"); "report" usebundle => dcs_report_generic_classes("chattr"); reports: DEBUG.!have_chattr:: "Without $(chattr.chattr), the test will always pass"; DEBUG.chattr_failed:: "Since you can't run $(chattr.chattr) to set attributes, the test will always pass"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/109.x.cf0000644000175100017510000000336112332665147024510 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous relative symbolic no-filename link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; # This extracts the octal mode, and decimal nlink, uid, gid, size "command" string => 'printf "%o" . " %d" x 4, (stat("$(G.testfile)"))[2]&07777, (stat(_))[3..5,7]'; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", link_from => test_link; } body link_from test_link { link_type => "relative"; } ####################################################### bundle agent check { vars: "expect" string => "$(test.mode) 1 0 0 0"; "result" string => execresult( "$(G.perl) -le '$(g.command)'", "noshell"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/107.x.cf0000644000175100017510000000334412332665147024507 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous hard no-filename link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; # This extracts the octal mode, and decimal nlink, uid, gid, size "command" string => 'printf "%o" . " %d" x 4, (stat("$(G.testfile)"))[2]&07777, (stat(_))[3..5,7]'; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", link_from => test_link; } body link_from test_link { link_type => "hardlink"; } ####################################################### bundle agent check { vars: "expect" string => "$(test.mode) 1 0 0 0"; "result" string => execresult( "$(G.perl) -le '$(g.command)'", "noshell"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/copy-select-link-dereference.cf0000644000175100017510000000354412243421446031354 0ustar00a10038a1003800000000000000# Assume the following file-structure: # dir1/file1 # dir2/file2 # link -> dir1 # # We want to copy only what link points to, without explicitly specifying the link name. body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { commands: "$(G.mkdir) -p $(G.testdir)/from/dir1"; "$(G.mkdir) -p $(G.testdir)/from/dir2"; "$(G.echo) 'indir1' > $(G.testdir)/from/dir1/file1" contain => in_shell; "$(G.echo) 'indir2' > $(G.testdir)/from/dir2/file2" contain => in_shell; "$(G.ln) -s dir1 link", contain => in_dir("$(G.testdir)/from"); } bundle agent test { vars: "regular_dirs" slist => { ".*dir1",".*dir2" }; files: "$(G.testdir)/to" copy_from => dereference_all("$(G.testdir)/from"), depth_search => recurse("inf"), file_select => links_to( "@(regular_dirs)" ); } bundle agent check { vars: "file1_contents" string => readfile("$(G.testdir)/to/dir1/file1", 100); classes: "file1_contents_correct" expression => strcmp("$(file1_contents)", "indir1"); "file2_exists" expression => fileexists("$(G.testdir)/to/dir2/file2"); "ok" expression => "file1_contents_correct.(!file2_exists)"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body contain in_dir(s) { chdir => "$(s)"; } body contain in_shell { useshell => "true"; } body copy_from dereference_all(from) { source => "$(from)"; copylink_patterns => { ".*" }; } body file_select links_to(list) { issymlinkto => { @(list) }; file_result => "issymlinkto"; } body depth_search recurse(d) { depth => "$(d)"; xdev => "true"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/302.cf0000644000175100017510000000512112332665147024231 0ustar00a10038a1003800000000000000####################################################### # # Create a file using copy, expect second copy of different file to # have "promise_repaired" # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; classes: "cxl_succ" expression => "any"; "cxl_fail" expression => "any"; } ####################################################### bundle agent init { files: "$(G.testfile)" perms => init_mog, copy_from => init_copy("$(G.etc_group)"); } body perms init_mog { mode => "751"; owners => { "bin" }; groups => { "bin" }; } body copy_from init_copy(fn) { source => "$(fn)"; compare => "digest"; } ####################################################### bundle agent test { files: "$(G.testfile)" perms => init_mog, copy_from => init_copy("$(G.etc_passwd)"), classes => test_classes("failure", "success", "failure", "failure", "cxl_fail", "cxl_succ", "cxl_fail"); } body classes test_classes(kep, rep, fai, xxx, cxl_kep, cxl_rep, cxl_nkp) { promise_kept => { "$(kep)" }; promise_repaired => { "$(rep)" }; repair_failed => { "$(fai)" }; repair_denied => { "$(fai)" }; repair_timeout => { "$(fai)" }; cancel_kept => { "$(cxl_kep)" }; cancel_repaired => { "$(cxl_rep)" }; cancel_notkept => { "$(cxl_nkp)" }; } ####################################################### bundle agent check { classes: "ok" and => { "success", "!cxl_succ", "!failure", "cxl_fail" }; reports: DEBUG.success:: "class 'success' was set (should be)"; DEBUG.!success:: "class 'success' was not set (should be)"; DEBUG.cxl_succ:: "class 'cxl_succ' was still set (should not be)"; DEBUG.!cxl_succ:: "class 'cxl_succ' was not still set (should not be)"; DEBUG.failure:: "class 'failure' was set (should not be)"; DEBUG.!failure:: "class 'failure' was not set (should not be)"; DEBUG.cxl_fail:: "class 'cxl_fail' was still set (should be)"; DEBUG.!cxl_fail:: "class 'cxl_fail' was not still set (should not be)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/108.x.cf0000644000175100017510000000333512332665147024510 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous symbolic no-filename link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; # This extracts the octal mode, and decimal nlink, uid, gid, size "command" string => 'printf "%o" . " %d" x 4, (stat("$(G.testfile)"))[2]&07777, (stat(_))[3..5,7]'; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" link_from => test_link("$(baz)"); } body link_from test_link(foo) { link_type => "$(foo)"; } ####################################################### bundle agent check { vars: "expect" string => "$(test.mode) 1 0 0 0"; "result" string => execresult( "$(G.perl) -le '$(g.command)'", "noshell"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/401.cf0000644000175100017510000000270512332665147024236 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile).cfsaved"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/110.x.cf0000644000175100017510000000336112332665147024500 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous absolute symbolic no-filename link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; # This extracts the octal mode, and decimal nlink, uid, gid, size "command" string => 'printf "%o" . " %d" x 4, (stat("$(G.testfile)"))[2]&07777, (stat(_))[3..5,7]'; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", link_from => test_link; } body link_from test_link { link_type => "absolute"; } ####################################################### bundle agent check { vars: "expect" string => "$(test.mode) 1 0 0 0"; "result" string => execresult( "$(G.perl) -le '$(g.command)'", "noshell"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/staging/line_truncation_at_4096_chars.cf0000644000175100017510000000437112332665147031456 0ustar00a10038a1003800000000000000####################################################### # # Check if the lines in a file get truncated after 4096 # chars during file editing. # # Ticket: https://cfengine.com/dev/issues/3882 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("${this.promise_filename}") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "file_mode" int => "0644"; "char_number" int => "6144"; "line_to_add" string => "This is a nice short line."; files: "${G.testfile}" create => "true", perms => m("${file_mode}"); # Using system command instead of CFEngine itself to # prevent the bug to be here at file creation too. # It would create a false negative. commands: "${G.perl}" args => "-e 'print \"#\" x ${char_number}; print \"ENDMARK\n\"' > ${G.testfile}" contain => in_shell; } body perms m(mode) { mode => "${mode}"; } body contain in_shell { useshell => "true"; # canonical "useshell" but this is backwards-compatible } ####################################################### bundle agent test { files: "${G.testfile}" create => "false", edit_line => insert_lines("${init.line_to_add}"); } bundle edit_line insert_lines(lines) { insert_lines: "${lines}" comment => "Append lines if they don't exist"; } ####################################################### bundle agent check { classes: # ok is defined if the file still contains ENDMARK, meaning the end of the sample very # long line did not get truncated during file editing "ok" expression => returnszero("${G.grep} -q ENDMARK ${G.testfile}", "noshell"); reports: DEBUG.!ok:: "${this.promise_filename} FAILed as the generated file got at least a line truncated to 4096 characters" ok:: "${this.promise_filename} Pass"; !ok:: "${this.promise_filename} FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("${G.testfile}"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/208.cf0000644000175100017510000000542012332665147022604 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, group but DOES change owner, because # we start with a non-registered user/group name. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } ####################################################### bundle agent init { vars: freebsd|solaris:: "mode" int => "04751"; !freebsd.!solaris:: "mode" int => "01751"; any:: "owner" string => "786756"; "group" string => "786756"; pass2.!windows:: "expect[modeoct]" string => "\d+$(init.mode)"; "expect[uid]" string => "$(init.owner)"; "expect[gid]" string => "$(init.group)"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; compare => "mtime"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { # Mode is unspecified - should not change anything owners => { "12349", "none" }; # Should change to 12349 # Group is unspecified - should not change anything } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "\d+$(init.mode)"; "expect[uid]" string => "12349"; "expect[gid]" string => "$(init.group)"; any:: "expect[nlink]" string => "1"; "expect[size]" string => filestat("$(G.etc_group)", "size"); "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "result: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/202.cf0000644000175100017510000000551312316547775022611 0ustar00a10038a1003800000000000000####################################################### # # Copy a file, then ensure that subsequent create=true doesn't # overwrite mode, size, owner, group # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "mode" int => "01751"; linux:: "owner" string => "sys"; "group" string => "sys"; freebsd:: "owner" string => "bin"; "group" string => "sys"; !(linux|freebsd):: "owner" string => "undefined-please-fix"; "group" string => "undefined-please-fix"; pass2.!windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; pass2.any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); files: "$(G.testfile)" copy_from => init_copy("$(G.etc_group)"), perms => init_perms("$(mode)", "$(owner)", "$(group)"), classes => init_set_class("pass2"); } body copy_from init_copy(file) { source => "$(file)"; } body perms init_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)" }; groups => { "$(g)" }; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", perms => test_perms("$(init.mode)", "$(init.owner)", "$(init.group)"); } body perms test_perms(m, o, g) { mode => "$(m)"; owners => { "$(o)", "root" }; linux:: groups => { "$(g)", "root" }; freebsd:: groups => { "$(g)", "wheel" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "ok" expression => strcmp("$(init.result)", "$(result)"); "not_ok" not => regcmp("$(init.result[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(init.result[$(fields)])'"; "got: $(fields) = '$(check.result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/413.cf0000644000175100017510000000246612243421446022602 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { commands: "$(G.touch) $(G.testfile)"; } ####################################################### bundle agent test { vars: "cmd" string => "$(sys.cf_agent) -Kf $(this.promise_filename).sub"; commands: "$(cmd) -D useless0"; "$(cmd) -D useless1"; "$(cmd) -D useless2"; "$(cmd) -D useless3"; "$(cmd) -D useless4"; } ####################################################### bundle agent check { classes: "filestillthere" expression => fileexists("$(G.testfile)"); "fileisrotated" expression => fileexists("$(G.testfile).cf-before-edit.4"); "nooverflow" not => fileexists("$(G.testfile).cf-before-edit.5"); "ok" and => { "filestillthere", "fileisrotated", "nooverflow" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/412.cf.sub0000644000175100017510000000132412243421446023361 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename { rotate => 1 } (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "test" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => append_nonsense, edit_defaults => rotate; } body edit_defaults rotate { edit_backup => "rotate"; rotate => "4"; max_file_size => "300000"; } bundle edit_line append_nonsense { vars: "ns" string => execresult("$(G.date) +%N", "noshell"); insert_lines: "$(ns)"; } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/001.cf0000644000175100017510000000335312316547775022606 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous copy with default compare to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_group)"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/113.cf0000644000175100017510000000275212316547775022614 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous link with hardlink and move_obstructions # to succeed # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; "$(G.testfile).SOURCE" create => "true"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testfile)" create => "true", move_obstructions => "true", link_from => test_link; } body link_from test_link { source => "$(G.testfile).SOURCE"; link_type => "hardlink"; } ####################################################### bundle agent check { vars: "expect" string => filestat("$(G.testfile).SOURCE", "ino"); "result" string => filestat("$(G.testfile)", "ino"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/019.cf0000644000175100017510000000262712316547775022622 0ustar00a10038a1003800000000000000####################################################### # # Test that disable_mode => "333" in body rename works (Issue 688) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testfile)" rename => disable_file; } body rename disable_file { disable_mode => "333"; disable => "true"; } ####################################################### bundle agent check { vars: "expect[permoct]" string => "333"; "expect[nlink]" string => "1"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile).cfdisabled", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/404.x.cf0000644000175100017510000000326312332665147023053 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { default_repository => "tmp"; # Intentionally wrong } bundle common g { vars: "repofile" string => "/var/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(g.repofile).*" delete => init_delete; "$(G.testfile).*" delete => init_delete; "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; compare => "digest"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" move_obstructions => "true", copy_from => test_copy; } body copy_from test_copy { source => "$(G.etc_motd)"; compare => "digest"; } ####################################################### bundle agent check { classes: "test" not => fileexists("$(G.testfile).cfsaved"); "repo" expression => fileexists("$(g.repofile).cfsaved"); "ok" and => { "test", "repo" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(g.repofile)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/copy_from_translatepath.cf0000644000175100017510000000203312332665147027217 0ustar00a10038a1003800000000000000####################################################### # # Test that copying a file with double directory # separators work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { vars: "regex" string => escape("$(const.dirsep)"); "orig_path" string => translatepath("$(this.promise_filename)"); "path_list" slist => splitstring("$(orig_path)", "$(regex)", 100); "path" string => join("$(const.dirsep)$(const.dirsep)", "path_list"); files: "$(G.testfile)" copy_from => copy_body("$(path)"); } body copy_from copy_body(file) { source => "$(file)"; } bundle agent check { reports: DEBUG:: "Tested pathname: '$(test.path)'"; methods: "check" usebundle => dcs_check_diff("$(this.promise_filename)", "$(G.testfile)", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/10_files/02_maintain/copy-relative-link-existing.cf0000644000175100017510000000237212332665147027644 0ustar00a10038a1003800000000000000# Assume the following file-structure: # dest # link -> dest # link-currdir -> ./dest # # When verifying "link-currdir" is copy of "link", it is ok # to correct it (to be link-currdir -> dest), but after this, the promise must be kept. body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { commands: "$(G.mkdir) -p $(G.testdir)"; "$(G.touch) $(G.testdir)/dest"; "$(G.ln) -s dest link" contain => in_dir("$(G.testdir)"); "$(G.ln) -s ./dest link-currdir" contain => in_dir("$(G.testdir)"); } bundle agent test { files: "$(G.testdir)/link-currdir" copy_from => local_cp("$(G.testdir)/link"), move_obstructions => "true"; "$(G.testdir)/link-currdir" copy_from => local_cp("$(G.testdir)/link"), classes => if_kept("copy_link_kept"); } bundle agent check { classes: "ok" or => { "copy_link_kept" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body contain in_dir(s) { chdir => "$(s)"; } body classes if_kept(x) { promise_kept => { "$(x)" }; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/106.x.cf0000644000175100017510000000317112316547775023060 0ustar00a10038a1003800000000000000####################################################### # # Test wrong type of link_type. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; link_type => "none"; } ####################################################### bundle agent check { vars: "expect[permoct]" string => "$(test.mode)"; "expect[nlink]" string => "1"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/line_truncation_at_4096_chars.cf0000644000175100017510000000451212400110676030003 0ustar00a10038a1003800000000000000####################################################### # # Check if the lines in a file get truncated after 4096 # chars during file editing. # # Ticket: https://cfengine.com/dev/issues/3882 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("${this.promise_filename}") }; version => "1.0"; cache_system_functions => "off"; } ####################################################### bundle agent init { vars: any:: "file_mode" int => "0644"; "char_number" int => "6144"; "line_to_add" string => "This is a nice short line."; files: "${G.testfile}" create => "true", perms => m("${file_mode}"); # Using system command instead of CFEngine itself to # prevent the bug to be here at file creation too. # It would create a false negative. commands: "${G.perl}" args => "-e 'print \"#\" x ${char_number}; print \"ENDMARK\n\"' > ${G.testfile}", contain => in_shell; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "${G.testfile}" create => "false", edit_line => insert_lines("${init.line_to_add}"); } ####################################################### bundle agent check { classes: !solaris:: # ok is defined if the file still contains ENDMARK, meaning the end of the sample very # long line did not get truncated during file editing "ok" expression => returnszero("${G.grep} ENDMARK ${G.testfile}", "noshell"); solaris:: # Bug in xpg4 version of Solaris. grep internally has a limit of 4096 chars per line, # which is the very thing we're testing. Use /bin/grep. "ok" expression => returnszero("/bin/grep ENDMARK ${G.testfile}", "noshell"); reports: DEBUG.!ok:: "${this.promise_filename} FAILed as the generated file got at least a line truncated to 4096 characters"; ok:: "${this.promise_filename} Pass"; !ok:: "${this.promise_filename} FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("${G.testfile}"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/010.cf0000644000175100017510000000341112352022221022547 0ustar00a10038a1003800000000000000####################################################### # # Test that symlinks are set aside while copying trees of directories (Issue 569) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testdir)/srcdir/foo" create => "true"; "$(G.testdir)/realdestdir/" create => "true"; "$(G.testdir)/destdir" comment => "Create a relative link to the target.", link_from => ln_s("$(G.testdir)/realdestdir"); } body link_from ln_s(x) { link_type => "relative"; source => "$(x)"; when_no_source => "nop"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testdir)/destdir/" copy_from => test_sync_cp("$(G.testdir)/srcdir"), depth_search => recurse("inf"), move_obstructions => "true", action => if_elapsed(0); } body copy_from test_sync_cp(from) { source => "$(from)"; purge => "true"; preserve => "true"; type_check => "true"; } ####################################################### bundle agent check { vars: "expect" string => "directory"; "result" string => filestat("$(G.testdir)/destdir", "type"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/409.cf0000644000175100017510000000237612352022221022574 0ustar00a10038a1003800000000000000####################################################### # # Test that action => "warn" works correctly for rename => disable (Issue 841) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" move_obstructions => "true", copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_null)"; compare => "digest"; } ####################################################### bundle agent test { files: "$(G.testfile)" rename => disable, action => warn_only; } body rename disable { disable => "true"; } ####################################################### bundle agent check { classes: "filestillthere" expression => fileexists("$(G.testfile)"); "fileisnotdisabled" not => fileexists("$(G.testfile).cfdisabled"); "ok" and => { "filestillthere", "fileisnotdisabled" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/301.cf0000644000175100017510000000455112316547775022612 0ustar00a10038a1003800000000000000####################################################### # # Create a file using copy, expect second copy to have "promise_kept" # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { classes: "cxl_succ" expression => "any"; "cxl_fail" expression => "any"; } ####################################################### bundle agent init { files: "$(G.testfile)" perms => init_mog, copy_from => init_copy("$(G.etc_group)"); } body perms init_mog { mode => "751"; owners => { "0" }; groups => { "0" }; } body copy_from init_copy(fn) { source => "$(fn)"; compare => "digest"; } ####################################################### bundle agent test { files: "$(G.testfile)" perms => init_mog, copy_from => init_copy("$(G.etc_group)"), classes => test_classes("success", "failure", "failure", "failure", "cxl_succ", "cxl_fail", "cxl_fail"); } body classes test_classes(kep, rep, fai, xxx, cxl_kep, cxl_rep, cxl_nkp) { promise_kept => { "$(kep)" }; promise_repaired => { "$(rep)" }; repair_failed => { "$(fai)" }; repair_denied => { "$(fai)" }; repair_timeout => { "$(fai)" }; cancel_kept => { "$(cxl_kep)" }; cancel_repaired => { "$(cxl_rep)" }; cancel_notkept => { "$(cxl_nkp)" }; } ####################################################### bundle agent check { classes: "ok" and => { "success", "!cxl_succ", "!failure", "cxl_fail" }; reports: DEBUG.success:: "class 'success' was set (should be)"; DEBUG.!success:: "class 'success' was not set (should be)"; DEBUG.cxl_succ:: "class 'cxl_succ' was still set (should not be)"; DEBUG.!cxl_succ:: "class 'cxl_succ' was not still set (should not be)"; DEBUG.failure:: "class 'failure' was set (should not be)"; DEBUG.!failure:: "class 'failure' was not set (should not be)"; DEBUG.cxl_fail:: "class 'cxl_fail' was still set (should be)"; DEBUG.!cxl_fail:: "class 'cxl_fail' was not still set (should not be)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/012.cf0000644000175100017510000000343012352022221022552 0ustar00a10038a1003800000000000000####################################################### # # # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testdir)/srcdir/" create => "true"; "$(G.testdir)/srcdir/intermediate/" create => "true"; "$(G.testdir)/srcdir/intermediate/intermediate2/" create => "true"; "$(G.testdir)/srcdir/intermediate/intermediate2/foo" create => "true"; "$(G.testdir)/realdestdir/" create => "true"; "$(G.testdir)/destdir" comment => "Create a relative link to the target.", link_from => ln_s("$(G.testdir)/realdestdir"); } body link_from ln_s(x) { link_type => "relative"; source => "$(x)"; when_no_source => "nop"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testdir)/destdir/intermediate/intermediate2/foo" copy_from => test_sync_cp("$(G.testdir)/srcdir/intermediate/intermediate2/foo"); } body copy_from test_sync_cp(from) { source => "$(from)"; } ####################################################### bundle agent check { vars: "expect" string => "symlink"; "result" string => filestat("$(G.testdir)/destdir", "type"); classes: "ok" expression => strcmp("$(expect)", "$(result)"); reports: DEBUG:: "expected: '$(expect)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/02_maintain/101.cf0000644000175100017510000000333712316547775022611 0ustar00a10038a1003800000000000000####################################################### # # Create a file, expect simultaneous default link to fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0600"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)), link_from => test_link; } body link_from test_link { source => "$(G.etc_group)"; } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; "expect[uid]" string => "0"; "expect[gid]" string => "0"; any:: "expect[nlink]" string => "1"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/0000755000175100017510000000000012352022221022417 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/018.cf0000644000175100017510000000362012332665147023264 0ustar00a10038a1003800000000000000####################################################### # # Prepend field, testing blank values # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:XXX+echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX+,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/027.cf0000644000175100017510000000372012332665147023265 0ustar00a10038a1003800000000000000####################################################### # # Set field, after end of some lists # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo:XXX apple:banana:carrot:dogfood::XXX aardvark:baboon:colugo:dingo::XXX ampallang:: :dydoe:,:XXX:::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "6"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/017.cf0000644000175100017510000000361612332665147023270 0ustar00a10038a1003800000000000000####################################################### # # Append field, testing blank values # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo+XXX apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:,+XXX::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/015.cf0000644000175100017510000000375312332665147023270 0ustar00a10038a1003800000000000000####################################################### # # Prepend field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX,baker,booker,banker:charlie:delta:echo apple:XXX,banana:carrot:dogfood aardvark:XXX,baboon:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/024.cf0000644000175100017510000000375512332665147023272 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,bo0ker,bonker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX+baker,bo0ker,bonker:charlie:delta:echo apple:XXX+banana:carrot:dogfood aardvark:XXX+baboon:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/036.cf0000644000175100017510000000367312332665147023274 0ustar00a10038a1003800000000000000####################################################### # # Append field, testing blank values (default field_operation) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo+XXX apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:,+XXX::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; # field_operation => "append"; # Default value field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/006.x.cf0000644000175100017510000000377512332665147023542 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, illegal select_field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "-1"; # Must be greater than 1 start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/023.cf0000644000175100017510000000375512332665147023271 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX,baker,banker,booker:charlie:delta:echo apple:XXX,banana:carrot:dogfood aardvark:XXX,baboon:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/016.cf0000644000175100017510000000375312332665147023271 0ustar00a10038a1003800000000000000####################################################### # # Prepend field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX+baker,booker,banker:charlie:delta:echo apple:XXX+banana:carrot:dogfood aardvark:XXX+baboon:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/028.cf0000644000175100017510000000377012332665147023273 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field, lowercase # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker+xxx:charlie:delta:echo apple:banana+xxx:carrot:dogfood aardvark:baboon+xxx:colugo:dingo::fox ampallang:xxx: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "xxx"; select_field => "2"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/set_empty_field_erroneous_message.cf.sub0000644000175100017510000000065612352022221032511 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { editor }; } bundle agent editor { vars: "null_shadow_entries" ilist => {4, 5, 6, 7, 8}; files: "$(G.testfile)" handle => "null_root_user_account_expiration_shadow_entries", edit_line => set_user_field("root", $(null_shadow_entries), ""), classes => if_repaired("root_password_modified"); } cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/008.x.cf0000644000175100017510000000377512332665147023544 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, illegal select_field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "-1"; # Must be greater than 1 start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/003.cf0000644000175100017510000000376612332665147023271 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, simple case index 1 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/set_empty_field_erroneous_message.cf0000644000175100017510000000146612352022221031721 0ustar00a10038a1003800000000000000####################################################### # # catch spurious editing messages in field editing # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent check { methods: "" usebundle => file_make($(G.testfile), "root:sikrt:16104::::::"); "" usebundle => dcs_passif_output("", ".*(Edited|Setting).*", "$(sys.cf_agent) -KI -f $(this.promise_filename).sub | $(G.grep) field", $(this.promise_filename)); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/033.cf0000644000175100017510000000404412332665147023262 0ustar00a10038a1003800000000000000####################################################### # # Append field (default field_operation) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker,XXX:charlie:delta:echo apple:banana,XXX:carrot:dogfood aardvark:baboon,XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; # field_operation => "append"; # Default value field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/031.cf0000644000175100017510000000361212332665147023260 0ustar00a10038a1003800000000000000####################################################### # # Set field, not allowing blanks (test needs to be double-checked for accuracy) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo:XXX apple:banana:carrot:dogfood::XXX aardvark:baboon:colugo:dingo:fox:XXX ampallang: :dydoe:,::XXX :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "false"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "6"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/030.cf0000644000175100017510000000373612332665147023266 0ustar00a10038a1003800000000000000####################################################### # # Set field, after end of some lists without extend_fields # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::XXX ampallang:: :dydoe:,:XXX:::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "false"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "6"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/005.cf0000644000175100017510000000365112332665147023264 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, illegal select_field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "0"; # Must be greater than 1 to be legal start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/009.cf0000644000175100017510000000375112332665147023271 0ustar00a10038a1003800000000000000####################################################### # # Append field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker,XXX:charlie:delta:echo apple:banana,XXX:carrot:dogfood aardvark:baboon,XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/029.cf0000644000175100017510000000377012332665147023274 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field, lowercase # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,banker,booker,xxx:charlie:delta:echo apple:banana,xxx:carrot:dogfood aardvark:baboon,xxx:colugo:dingo::fox ampallang:xxx: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "xxx"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/032.cf0000644000175100017510000000362412332665147023264 0ustar00a10038a1003800000000000000####################################################### # # Delete fields, simple case # Bug, tracked on https://cfengine.com/dev/issues/3506 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,XXX,banker:charlie:delta:echo apple:XXX,banana:carrot:dogfood aardvark:baboon,XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "delete"; field_separator => ":"; field_value => "XXX"; select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/002.cf0000644000175100017510000000373312332665147023262 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, simple case, index 0 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "1"; start_fields_from_zero => "true"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/038.x.cf0000644000175100017510000000366712332665147023547 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, illegal value_separator # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "2"; value_separator => ",+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/0000755000175100017510000000000012332665147024075 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/025.cf0000644000175100017510000000362212332665147024720 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field, testing blank values # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:XXX,echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX,,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/043.x.cf0000644000175100017510000000353712332665147025173 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, missing field_value # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; # field_value => "XXX"; # useless without this! select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/011.x.cf0000644000175100017510000000364512332665147025166 0ustar00a10038a1003800000000000000####################################################### # # Append field, field_separator the same as value_separator # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker+XXX:charlie:delta:echo apple:banana+XXX:carrot:dogfood aardvark:baboon+XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ":"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/021.x.cf0000644000175100017510000000364312332665147025165 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field, field_separator missing # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; # value_separator => ","; # How can you alphanum if you don't have sep? } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/026.cf0000644000175100017510000000366512332665147024730 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field, testing blank values (spaces, not completely blank) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe: , ::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:XXX,echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX, , ::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/041.x.cf0000644000175100017510000000365012332665147025165 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, regex separator with value_separator included in it # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:XXX:delta:echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => "[:,]"; field_value => "XXX"; select_field => "5"; value_separator => ","; # This is included in the field_separator } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/022.x.cf0000644000175100017510000000365612332665147025172 0ustar00a10038a1003800000000000000####################################################### # # Alphanum field, field_separator same as value_separator # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ":"; # Shouldn't be the same as field_separator } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/035.x.cf0000644000175100017510000000375412332665147025175 0ustar00a10038a1003800000000000000####################################################### # # Append field, field_separator missing (default field_operation) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker?XXX:charlie:delta:echo apple:banana?XXX:carrot:dogfood aardvark:baboon?XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; # field_value => "XXX"; # Default value select_field => "2"; start_fields_from_zero => "false"; # value_separator => ","; # How can you append if you don't have sep? } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/042.x.cf0000644000175100017510000000354112332665147025165 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, missing field_value # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; # field_value => "XXX"; # useless without this! select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/045.x.cf0000644000175100017510000000353712332665147025175 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, missing field_value # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "delete"; field_separator => ":"; # field_value => "XXX"; # useless without this! select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/046.x.cf0000644000175100017510000000354112332665147025171 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, missing field_value # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "alphanum"; field_separator => ":"; # field_value => "XXX"; # useless without this! select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/040.cf0000644000175100017510000000365312332665147024721 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, regex separator value_separator not included in it # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:XXX:delta:echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => "[:,]"; field_value => "XXX"; select_field => "5"; value_separator => "/"; # This is not included in the field_separator } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/014.x.cf0000644000175100017510000000360112332665147025161 0ustar00a10038a1003800000000000000####################################################### # # Prepend field, field_separator same as value_separator # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ":"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/044.x.cf0000644000175100017510000000354012332665147025166 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, missing field_value # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; # field_value => "XXX"; # useless without this! select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/034.x.cf0000644000175100017510000000372212332665147025167 0ustar00a10038a1003800000000000000####################################################### # # Append field, field_separator the same as value_separator (default field_operation) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker+XXX:charlie:delta:echo apple:banana+XXX:carrot:dogfood aardvark:baboon+XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; # field_operation => "append"; # Default value field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => ":"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/012.x.cf0000644000175100017510000000367712332665147025174 0ustar00a10038a1003800000000000000####################################################### # # Append field, field_separator missing # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker?XXX:charlie:delta:echo apple:banana?XXX:carrot:dogfood aardvark:baboon?XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; # value_separator => ","; # How can you append if you don't have sep? } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/039.cf0000644000175100017510000000347312332665147024731 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, regex separator # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:XXX:delta:echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => "[:,]"; field_value => "XXX"; select_field => "5"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/staging/013.x.cf0000644000175100017510000000364012332665147025163 0ustar00a10038a1003800000000000000####################################################### # # Prepend field, field_separator missing # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; # value_separator => ","; # How can you prepend if you don't have sep? } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/004.x.cf0000644000175100017510000000377512332665147023540 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, broken start_fields_from_zero # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false "; # Illegal value value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/001.cf0000644000175100017510000000365212332665147023261 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, simple case # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "2"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/019.cf0000644000175100017510000000404212332665147023264 0ustar00a10038a1003800000000000000####################################################### # # Append field, testing blank values (spaces, not completely blank) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe: , ::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo,XXX apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe: , ,XXX::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/010.cf0000644000175100017510000000400412332665147023251 0ustar00a10038a1003800000000000000####################################################### # # Append field, different value_separator # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker+XXX:charlie:delta:echo apple:banana+XXX:carrot:dogfood aardvark:baboon+XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "append"; field_separator => ":"; field_value => "XXX"; select_field => "2"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/007.x.cf0000644000175100017510000000376712332665147023544 0ustar00a10038a1003800000000000000####################################################### # # Replace fields, illegal select_field # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:XXX:charlie:delta:echo apple:XXX:carrot:dogfood aardvark:XXX:colugo:dingo::fox ampallang:XXX: :dydoe:,::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "set"; field_separator => ":"; field_value => "XXX"; select_field => "xyz"; # Must be numeric start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/020.cf0000644000175100017510000000404412332665147023256 0ustar00a10038a1003800000000000000####################################################### # # Prepend field, testing blank values (spaces, not completely blank) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe: , ::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:XXX,echo apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe:XXX, , ::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; field_operation => "prepend"; field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => ","; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/08_field_edits/037.cf0000644000175100017510000000373612332665147023275 0ustar00a10038a1003800000000000000####################################################### # # Append field, testing blank values (spaces, not completely blank) (default field_operation) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "able:baker,booker,banker:charlie:delta:echo apple:banana:carrot:dogfood aardvark:baboon:colugo:dingo::fox ampallang:: :dydoe: , ::::: :blowfish:conger:dogfish:eel:flounder"; "expected" string => "able:baker,booker,banker:charlie:delta:echo+XXX apple:banana:carrot:dogfood:XXX aardvark:baboon:colugo:dingo:XXX:fox ampallang:: :dydoe: , +XXX::::: :blowfish:conger:dogfish:eel:flounder"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_edit; } bundle edit_line test_edit { field_edits: "a.*" edit_field => test_col; } body edit_field test_col { allow_blank_fields => "true"; extend_fields => "true"; # field_operation => "append"; # Default value field_separator => ":"; field_value => "XXX"; select_field => "5"; start_fields_from_zero => "false"; value_separator => "+"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/03_transform/0000755000175100017510000000000012412512360022157 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/03_transform/003.cf0000644000175100017510000000415212412512360022775 0ustar00a10038a1003800000000000000####################################################### # # Ensure that the transformer runs only once for every file in a recursive tree # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "off"; # for execresult in check bundle } ####################################################### bundle agent init { vars: "files" slist => { "1", "2", "3" }; files: "$(G.testdir)/files/." create => "true"; "$(G.testdir)/files/$(files)" copy_from => init_copy; } body copy_from init_copy { source => "$(G.etc_group)"; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { vars: "counter" string => "$(G.testdir)/counter"; files: windows:: "$(G.testdir)/files" transformer => "$(G.echo) $(this.promiser) >> $(counter)", file_select => test_plain, depth_search => test_recurse; !windows:: "$(G.testdir)/files" transformer => "/bin/sh -c 'echo $(this.promiser) >> $(counter)'", file_select => test_plain, depth_search => test_recurse; } body file_select test_plain { file_types => { "plain" }; file_result => "file_types"; } body depth_search test_recurse { depth => "inf"; } ####################################################### bundle agent check { vars: "count" string => execresult("$(G.wc) -l $(test.counter)", "noshell"); DEBUG:: "list" string => execresult("$(G.ls) -1 $(G.testdir)/files", "noshell"); classes: "ok" expression => regcmp("^\s*3\s.*", "$(count)"); reports: DEBUG.!ok:: "3 transformations expected, saw (wc): '$(count)'"; "3 copies of $(G.etc_group) expected, saw (ls): '$(list)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/03_transform/002.cf0000644000175100017510000000434212316547775023022 0ustar00a10038a1003800000000000000####################################################### # # Ensure that the transformer does not run when --dry-run is used # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "files" slist => { "1", "2", "3" }; files: "$(G.testdir)/." create => "true"; "$(G.testdir)/$(files)" copy_from => init_copy("$(G.etc_group)"); } body copy_from init_copy(file) { source => "$(file)"; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { commands: "$(sys.cf_agent) -f $(this.promise_filename) -D AUTO -K -b init,test_dry_run --dry-run" contain => start_from_cwd; } body contain start_from_cwd { chdir => "$(G.cwd)"; } bundle agent test_dry_run { files: "$(G.testdir)" transformer => "$(G.gzip) $(this.promiser)", file_select => test_plain, depth_search => test_recurse; reports: !opt_dry_run:: "$(this.promise_filename) --dry-run FAIL"; } body file_select test_plain { file_types => { "plain" }; file_result => "file_types"; } body depth_search test_recurse { depth => "inf"; } ####################################################### bundle agent check { vars: "files" slist => { @{init.files} }; classes: "ok$(files)" expression => fileexists("$(G.testdir)/$(files)"); "no$(files)" expression => fileexists("$(G.testdir)/$(files).gz"); "ok" and => { "ok1", "ok2", "ok3", "!no1", "!no2", "!no3", }; reports: DEBUG:: "$(G.testdir)/$(files) exists with no $(G.testdir)/$(files).gz" ifvarclass => "ok$(files).!no$(files)"; "$(G.testdir)/$(files).gz was created during --dry-run!" ifvarclass => "no$(files)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/03_transform/001.cf0000644000175100017510000000337112316547775023022 0ustar00a10038a1003800000000000000####################################################### # # Ensure that the transformer runs for every file in a recursive tree # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: any:: "files" slist => { "1", "2", "3" }; files: "$(G.testdir)/." create => "true"; "$(G.testdir)/$(files)" copy_from => init_copy("$(G.etc_group)"); } body copy_from init_copy(file) { source => "$(file)"; } body classes init_set_class(class) { promise_kept => { "$(class)" }; promise_repaired => { "$(class)" }; } ####################################################### bundle agent test { files: "$(G.testdir)" transformer => "$(G.gzip) $(this.promiser)", file_select => test_plain, depth_search => test_recurse; } body file_select test_plain { file_types => { "plain" }; file_result => "file_types"; } body depth_search test_recurse { depth => "inf"; } ####################################################### bundle agent check { vars: "files" slist => { @{init.files} }; classes: "ok$(files)" expression => fileexists("$(G.testdir)/$(files).gz"); "ok" and => { "ok1", "ok2", "ok3" }; reports: DEBUG:: "$(G.testdir)/$(files).gz exists as expected" ifvarclass => "ok$(files)"; "$(G.testdir)/$(files).gz was not created!" ifvarclass => "!ok$(files)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/0000755000175100017510000000000012411001073022575 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/647.cf0000644000175100017510000000401012332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/204.cf0000644000175100017510000000342112332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of lines at once, different way # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "header header BEGIN trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/418.cf0000644000175100017510000000350512332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/519.cf0000644000175100017510000000352012332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/537.cf0000644000175100017510000000372312332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/515.cf0000644000175100017510000000353312332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/125.cf0000644000175100017510000000417212332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: # Note - regex doesn't qualify for "starts_with"! "tstr" slist => { " Three potatoe", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/119.cf0000644000175100017510000000371012332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region and therefore the third edit will not be possible. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: # Second edit destroys the region "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/143.cf0000644000175100017510000000403212332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/608.cf0000644000175100017510000000372012332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/443.cf0000644000175100017510000000367112332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/523.cf0000644000175100017510000000350512243421446023440 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/420.cf0000644000175100017510000000355012332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/138.cf0000644000175100017510000000377512332665147023462 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/340.cf0000644000175100017510000000377012332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/243.cf0000644000175100017510000000375512332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/503.cf0000644000175100017510000000333012332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of three lines at once # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN Three potatoe END trailer END trailer"; "expected" string => "header BEGIN header trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => "BEGIN Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/638.cf0000644000175100017510000000400512332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/018.cf0000644000175100017510000000320612332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/509.cf0000644000175100017510000000343412332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/120.cf0000644000175100017510000000401512332665147023435 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: # Second edit destroys the region "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/025.cf0000644000175100017510000000354312332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: # Note - regex doesn't qualify for "starts_with"! "tstr" slist => { " Three potatoe", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/226.cf0000644000175100017510000000403312332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/514.cf0000644000175100017510000000333512332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/210.cf0000644000175100017510000000355112332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/332.cf0000644000175100017510000000375612332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/530.cf0000644000175100017510000000372712332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/646.cf0000644000175100017510000000347012332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/542.cf0000644000175100017510000000367612332665147023461 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/629.cf0000644000175100017510000000407112332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four potatoe END middle middle BEGIN One potato Two potato Three potatoe Four potatoe END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe END middle middle BEGIN One potato Two potato Three potatoe Four potatoe END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/129.cf0000644000175100017510000000404512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/440.cf0000644000175100017510000000372412332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/205.cf0000644000175100017510000000335212332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/334.cf0000644000175100017510000000367412332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/046.cf0000644000175100017510000000304112332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/305.cf0000644000175100017510000000356512332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # select_region, only include_start_delimiter # Notice that after the first iteration the region will never # be matched again because the start marker does not exist anymore. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "BEGIN", " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/027.cf0000644000175100017510000000334612332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/611.cf0000644000175100017510000000366412332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/105.cf0000644000175100017510000000367112332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # Region editing, include_start_delimiter and include_end_delimiter # Notice that this is a misinterpretation of our language, once the # start_delimiter is deleted, the region will not be matched again. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "BEGIN", " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/644.cf0000644000175100017510000000423112332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/117.cf0000644000175100017510000000407212332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: # Second edit destroys the region "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/017.cf0000644000175100017510000000322012332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$"; # Anchors should make no difference "BEGIN"; "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/045.cf0000644000175100017510000000303712332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => " One potato Two potato Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/642.cf0000644000175100017510000000403612332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/133.cf0000644000175100017510000000407412332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/402.cf0000644000175100017510000000347212332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/534.cf0000644000175100017510000000363712332665147023457 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/507.cf0000644000175100017510000000350012332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "\s+Three.*" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/225.cf0000644000175100017510000000411512332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: # Note - regex doesn't qualify for "starts_with"! "tstr" slist => { " Three potatoe", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/432.cf0000644000175100017510000000371212332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/535.cf0000644000175100017510000000367712332665147023464 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/244.cf0000644000175100017510000000377312332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/339.cf0000644000175100017510000000374712332665147023464 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/404.cf0000644000175100017510000000335512332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of lines at once, different way, should do nothing because # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "BEGIN$(const.n)$(str)$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/308.cf0000644000175100017510000000347312332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way # select_region, only include_start_delimiter # This will only work for the first match, the same reason # as 306 and 307. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/405.cf0000644000175100017510000000330312332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "BEGIN", " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/144.cf0000644000175100017510000000405012332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/224.cf0000644000175100017510000000373512332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/626.cf0000644000175100017510000000427112332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/026.cf0000644000175100017510000000346112332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/142.cf0000644000175100017510000000403012332665147023436 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/130.cf0000644000175100017510000000406112332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/313.cf0000644000175100017510000000345512332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n)BEGIN$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/112.cf0000644000175100017510000000353012332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe BEGIN END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/007.cf0000644000175100017510000000310412332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN"; "\s+Three.*"; "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/015.cf0000644000175100017510000000313712332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe"; "BEGIN"; "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/527.cf0000644000175100017510000000364312332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/107.cf0000644000175100017510000000400412332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # Region editing, include_start_delimiter and include_end_delimiter # Region is destroyed by first edit # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: # Region is destroyed by first edit "BEGIN" select_region => test_select; "\s+Three.*" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/235.cf0000644000175100017510000000375412332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/319.cf0000644000175100017510000000356712332665147023462 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/639.cf0000644000175100017510000000405012332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "hre", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/011.cf0000644000175100017510000000321212332665147023432 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/539.cf0000644000175100017510000000371212332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/206.cf0000644000175100017510000000356112332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; " Three potatoe" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/506.cf0000644000175100017510000000347012332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; " Three potatoe" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/641.cf0000644000175100017510000000377212332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/417.cf0000644000175100017510000000362512332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/423.cf0000644000175100017510000000347612243421446023446 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/345.cf0000644000175100017510000000343312332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/233.cf0000644000175100017510000000401712332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/024.cf0000644000175100017510000000336312332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/426.cf0000644000175100017510000000374712332665147023461 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/209.cf0000644000175100017510000000352512332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/531.cf0000644000175100017510000000364412332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/633.cf0000644000175100017510000000425512332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/510.cf0000644000175100017510000000346012332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/344.cf0000644000175100017510000000375312332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/635.cf0000644000175100017510000000403712332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/217.cf0000644000175100017510000000370512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/135.cf0000644000175100017510000000403112332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/315.cf0000644000175100017510000000360212332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/343.cf0000644000175100017510000000373512332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/434.cf0000644000175100017510000000363012332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/414.cf0000644000175100017510000000334612332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/504.cf0000644000175100017510000000335512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of lines at once, different way # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN Three potatoe END trailer END trailer"; "expected" string => "header BEGIN header trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "BEGIN$(const.n)$(str)$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/538.cf0000644000175100017510000000364312332665147023460 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/114.cf0000644000175100017510000000361312332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: # Second edit destroys the region "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/141.cf0000644000175100017510000000376412332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/435.cf0000644000175100017510000000367012332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/429.cf0000644000175100017510000000370412332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/215.cf0000644000175100017510000000362412332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/307.cf0000644000175100017510000000343412332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # select_region, only include_start_delimiter # As with 306, this will not work since only the first line # will be selected. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/103.cf0000644000175100017510000000346512332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a contiguous group of three lines # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "header header trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => "BEGIN Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/004.cf0000644000175100017510000000307212332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a contiguous group of three lines, different way # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "header header trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "BEGIN$(const.n)$(str)$(const.n)END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/502.cf0000644000175100017510000000350112332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/036.cf0000644000175100017510000000341012332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/323.cf0000644000175100017510000000354212243421446023437 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/203.cf0000644000175100017510000000340512332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of three lines at once # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "header header BEGIN trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/222.cf0000644000175100017510000000347612243421446023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/545.cf0000644000175100017510000000335512332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header One potato Two potato Three potatoe trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true", select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/601.cf0000644000175100017510000000356212332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # Two regions - Only the first region will be selected. # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/232.cf0000644000175100017510000000377612332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/035.cf0000644000175100017510000000340212332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/342.cf0000644000175100017510000000373312332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/023.cf0000644000175100017510000000321012243421446023424 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"); } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/403.cf0000644000175100017510000000332212332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of three lines at once, should do nothing because # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => "BEGIN Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/407.cf0000644000175100017510000000351112332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "\s+Three.*" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/518.cf0000644000175100017510000000347412332665147023460 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/628.cf0000644000175100017510000000404512332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/239.cf0000644000175100017510000000376712332665147023465 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/312.cf0000644000175100017510000000343312332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe BEGIN END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/231.cf0000644000175100017510000000372112332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/126.cf0000644000175100017510000000411012332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/102.cf0000644000175100017510000000363312332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/228.cf0000644000175100017510000000376012332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/230.cf0000644000175100017510000000400412332665147023435 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/607.cf0000644000175100017510000000365612332665147023461 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "\s+Three.*" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/622.cf0000644000175100017510000000371212243421446023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/016.cf0000644000175100017510000000314712332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*"; "BEGIN"; "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/341.cf0000644000175100017510000000366712332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/211.cf0000644000175100017510000000357112332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/245.cf0000644000175100017510000000345512332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/216.cf0000644000175100017510000000363412332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/241.cf0000644000175100017510000000370712332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/516.cf0000644000175100017510000000354312332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/044.cf0000644000175100017510000000342112332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/631.cf0000644000175100017510000000400312332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/127.cf0000644000175100017510000000377512332665147023460 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/645.cf0000644000175100017510000000353612332665147023460 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/147.cf0000644000175100017510000000401012332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/447.cf0000644000175100017510000000364712332665147023463 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/501.cf0000644000175100017510000000341012332665147023436 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/439.cf0000644000175100017510000000370312332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/511.cf0000644000175100017510000000350012332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/311.cf0000644000175100017510000000345112332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # select_region, only include_start_delimiter # Same as with 310 and 309, "END" is not deleted. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/008.cf0000644000175100017510000000314612332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/242.cf0000644000175100017510000000375312332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/132.cf0000644000175100017510000000405312332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/619.cf0000644000175100017510000000370412332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/123.cf0000644000175100017510000000363712243421446023442 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/047.cf0000644000175100017510000000336212332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/104.cf0000644000175100017510000000350712332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of lines at once, different way # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "header header trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "BEGIN$(const.n)$(str)$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/220.cf0000644000175100017510000000363012332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/634.cf0000644000175100017510000000377612332665147023464 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/109.cf0000644000175100017510000000374012332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # Region editing, include_start_delimiter and include_end_delimiter # Region is destroyed by first edit # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: # Region is destroyed by first edit "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/028.cf0000644000175100017510000000340612332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/207.cf0000644000175100017510000000357112332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "\s+Three.*" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/234.cf0000644000175100017510000000371412332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/137.cf0000644000175100017510000000405512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/425.cf0000644000175100017510000000374112332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/424.cf0000644000175100017510000000365112332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/445.cf0000644000175100017510000000337512332665147023457 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/533.cf0000644000175100017510000000374212332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/640.cf0000644000175100017510000000424612332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/310.cf0000644000175100017510000000350012332665147023434 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # select_region, only include_start_delimiter # As with 309.cf "END" will not be deleted because is not part of the # selected region. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/406.cf0000644000175100017510000000350112332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; " Three potatoe" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/303.cf0000644000175100017510000000333312332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of three lines at once # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => "BEGIN Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/116.cf0000644000175100017510000000402112332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: # Second edit destroys the region "\s+Three.*" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/201.cf0000644000175100017510000000346512332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/040.cf0000644000175100017510000000343612332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/213.cf0000644000175100017510000000347512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n)BEGIN$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/314.cf0000644000175100017510000000362512332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # select_region, only include_start_delimiter # "END" is not going to be deleted, this time because "BEGIN" is deleted # before, therefore the region will not be selected when "END" is used. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/441.cf0000644000175100017510000000362312332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/615.cf0000644000175100017510000000370612332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/136.cf0000644000175100017510000000403712332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/444.cf0000644000175100017510000000370712332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/042.cf0000644000175100017510000000340112332665147023436 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/544.cf0000644000175100017510000000371612332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/302.cf0000644000175100017510000000353612332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/333.cf0000644000175100017510000000377712332665147023461 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/013.cf0000644000175100017510000000312412332665147023436 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "BEGIN$(const.n)$(str)$(const.n)END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/043.cf0000644000175100017510000000340312332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/038.cf0000644000175100017510000000334612332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/237.cf0000644000175100017510000000400012332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/525.cf0000644000175100017510000000404012332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: # Note - regex doesn't qualify for "starts_with"! "tstr" slist => { " Three potatoe", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/408.cf0000644000175100017510000000356212332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/014.cf0000644000175100017510000000304712332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/346.cf0000644000175100017510000000337312332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/212.cf0000644000175100017510000000345312332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe BEGIN END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/003.cf0000644000175100017510000000303712332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a contiguous group of three lines # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "header header trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => "BEGIN Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/337.cf0000644000175100017510000000376012332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/547.cf0000644000175100017510000000365612332665147023464 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/419.cf0000644000175100017510000000353112332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/627.cf0000644000175100017510000000400212332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/508.cf0000644000175100017510000000355112332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/632.cf0000644000175100017510000000406012332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/227.cf0000644000175100017510000000372012332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/529.cf0000644000175100017510000000371312332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/624.cf0000644000175100017510000000402112332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/606.cf0000644000175100017510000000364612332665147023457 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; " Three potatoe" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/131.cf0000644000175100017510000000377612332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/625.cf0000644000175100017510000000410412332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", " Five", " Two", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/033.cf0000644000175100017510000000344512332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/031.cf0000644000175100017510000000334712332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/030.cf0000644000175100017510000000343212332665147023437 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/325.cf0000644000175100017510000000407512332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: # Note - regex doesn't qualify for "starts_with"! "tstr" slist => { " Three potatoe", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/326.cf0000644000175100017510000000401312332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/306.cf0000644000175100017510000000343312332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # select_region, only include_start_delimiter # This way of selecting lines does not work. Only the # first line will be considered. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/411.cf0000644000175100017510000000351112332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/446.cf0000644000175100017510000000332712332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/145.cf0000644000175100017510000000352412332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "true", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/005.cf0000644000175100017510000000300412332665147023434 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "BEGIN", " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/431.cf0000644000175100017510000000363512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/412.cf0000644000175100017510000000336712332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe BEGIN END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/617.cf0000644000175100017510000000376012332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/229.cf0000644000175100017510000000377012332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/637.cf0000644000175100017510000000423612332665147023457 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/006.cf0000644000175100017510000000307412332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN"; " Three potatoe"; "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/335.cf0000644000175100017510000000373412332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/009.cf0000644000175100017510000000314612332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/110.cf0000644000175100017510000000376412332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # Region editing, include_start_delimiter and include_end_delimiter # Region is destroyed by first edit # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; delete_lines: # Region is destroyed by first edit "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/029.cf0000644000175100017510000000341612332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/327.cf0000644000175100017510000000370012332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/630.cf0000644000175100017510000000424212332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/401.cf0000644000175100017510000000340112332665147023435 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/032.cf0000644000175100017510000000342412332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/528.cf0000644000175100017510000000370312332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/410.cf0000644000175100017510000000347112332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/002.cf0000644000175100017510000000320512332665147023434 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/433.cf0000644000175100017510000000373312332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*eade.*", ".*EGI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/532.cf0000644000175100017510000000372112332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*GI.*", ".*ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/322.cf0000644000175100017510000000345612243421446023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/442.cf0000644000175100017510000000366712332665147023460 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/146.cf0000644000175100017510000000347012332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/512.cf0000644000175100017510000000336412332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe BEGIN END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/022.cf0000644000175100017510000000312412243421446023427 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"); } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/522.cf0000644000175100017510000000342112243421446023434 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/304.cf0000644000175100017510000000336612332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of lines at once, different way # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN Three potatoe END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "BEGIN$(const.n)$(str)$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/218.cf0000644000175100017510000000356512332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/438.cf0000644000175100017510000000363412332665147023457 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/541.cf0000644000175100017510000000363212332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/041.cf0000644000175100017510000000333512332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/208.cf0000644000175100017510000000364212332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "BEGIN" select_region => test_select; "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/122.cf0000644000175100017510000000355312243421446023436 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/320.cf0000644000175100017510000000360612332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/520.cf0000644000175100017510000000353712332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/338.cf0000644000175100017510000000370012332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/202.cf0000644000175100017510000000355612332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/413.cf0000644000175100017510000000341112332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n)BEGIN$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/111.cf0000644000175100017510000000400412332665147023433 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns # Region editing, include_start_delimiter and include_end_delimiter # Region is destroyed by first edit # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: # Region is destroyed by first edit "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/139.cf0000644000175100017510000000404412332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/115.cf0000644000175100017510000000401112332665147023435 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: # Second edit destroys the region " Three potatoe" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/223.cf0000644000175100017510000000356212243421446023440 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/614.cf0000644000175100017510000000367212332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/602.cf0000644000175100017510000000401412332665147023441 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/001.cf0000644000175100017510000000311412332665147023432 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/113.cf0000644000175100017510000000355212332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n)BEGIN$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/643.cf0000644000175100017510000000415212332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Two regions - Only one region is selected # select_region, doesn't include header or trailer # Notice that the list is evaluated in one step, not in # several iterations. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/427.cf0000644000175100017510000000363412332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/019.cf0000644000175100017510000000323212332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/505.cf0000644000175100017510000000327212332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "BEGIN", " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/623.cf0000644000175100017510000000402012243421446023432 0ustar00a10038a1003800000000000000####################################################### # # Don't delete a line, set a class # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe "; # NOTE, DOES NOT MATCH! files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body classes test_class(a) { promise_kept => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/347.cf0000644000175100017510000000371312332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/422.cf0000644000175100017510000000341212243421446023433 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, set a class # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => test_class("ok"), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body classes test_class(a) { promise_repaired => { "$(a)" }; } ####################################################### bundle agent check { reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/118.cf0000644000175100017510000000375212332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # Region editing, include_start_delimiter and include_end_delimiter # Second edit destroys the region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: # Second edit destroys the region "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/238.cf0000644000175100017510000000372012332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/318.cf0000644000175100017510000000354312332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/247.cf0000644000175100017510000000373312332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@{test.tstr}"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/513.cf0000644000175100017510000000340612332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n)BEGIN$(const.n)END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/526.cf0000644000175100017510000000364012332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Double (nested) header/trailer # No line will be removed. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "header", " Two.*", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/336.cf0000644000175100017510000000374212332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/517.cf0000644000175100017510000000361412332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header header One potato Two potato Four trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/613.cf0000644000175100017510000000373512332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # Two matching regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe break Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe break Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n) Four" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/324.cf0000644000175100017510000000371512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/236.cf0000644000175100017510000000376212332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/605.cf0000644000175100017510000000401712332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist # Two regions - Only first region is selected # select_region, doesn't include header or trailer # Notice that neither "BEGIN" nor "END" are included in # the selected region, therefore only "Three potatoe" is # deleted. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "BEGIN", " Three potatoe", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/636.cf0000644000175100017510000000417012332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Two regions - Only the first region is going to be selected # select_region, doesn't include header or trailer # Notice that the list is expanded in one step, not iterated # over. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/329.cf0000644000175100017510000000375012332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/416.cf0000644000175100017510000000355412332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/124.cf0000644000175100017510000000401212332665147023436 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/604.cf0000644000175100017510000000362612332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of lines at once, different way # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)$(const.n) Four" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/540.cf0000644000175100017510000000373312332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/108.cf0000644000175100017510000000405512332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way # Region editing, include_start_delimiter and include_end_delimiter # Region is destroyed by first edit # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: # Region is destroyed by first edit "BEGIN" select_region => test_select; "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/430.cf0000644000175100017510000000372012332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/620.cf0000644000175100017510000000372012332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/330.cf0000644000175100017510000000376412332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T", " O" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/546.cf0000644000175100017510000000333612332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/415.cf0000644000175100017510000000354412332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines (different order than in original) # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: " Three potatoe" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/309.cf0000644000175100017510000000347112332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # select_region, only include_start_delimiter # Notice that deleting "END" will fail because the end # delimiter is not included in the region. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/214.cf0000644000175100017510000000342612332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist (different order than in original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe", "BEGIN", "END" }; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/039.cf0000644000175100017510000000341512332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which don't match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "Three", "GI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/140.cf0000644000175100017510000000406512332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/428.cf0000644000175100017510000000367412332665147023462 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/610.cf0000644000175100017510000000364412332665147023450 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/616.cf0000644000175100017510000000371612332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # Two regions - Only the first one is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/618.cf0000644000175100017510000000366012332665147023456 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way (different order than original) # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { " Three potatoe", "BEGIN", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/317.cf0000644000175100017510000000366312332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines, using regexes different way (different order than in original) # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "^\s+Three.*$" # Anchors should make no difference select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/536.cf0000644000175100017510000000370512332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/134.cf0000644000175100017510000000377112332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/246.cf0000644000175100017510000000341312332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" not_matching => "false", select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/331.cf0000644000175100017510000000370112332665147023442 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/010.cf0000644000175100017510000000317212332665147023436 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*BEGIN.*", ".*Three.*", ".*END.*" }; delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/240.cf0000644000175100017510000000401012332665147023433 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which don't match # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "eade", "EGI", "ND" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/034.cf0000644000175100017510000000334212332665147023443 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/543.cf0000644000175100017510000000370012332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN Two potato Three potatoe Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { "T", "C" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_not_contains_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/128.cf0000644000175100017510000000403512332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/437.cf0000644000175100017510000000371412332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/524.cf0000644000175100017510000000366012332665147023452 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list # Double (nested) header/trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header BEGIN header BEGIN One potato Two potato Three potatoe Four END trailer END trailer"; "expected" string => "header BEGIN header BEGIN One potato Two potato Four END trailer END trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " Three potatoe" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "header"; select_end => "trailer"; } body delete_select test_match(m) { delete_if_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/409.cf0000644000175100017510000000344512332665147023455 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/106.cf0000644000175100017510000000377412332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines # Region editing, include_start_delimiter and include_end_delimiter # Region is destroyed by first edit # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: # Region is destroyed by first edit "BEGIN" select_region => test_select; " Three potatoe" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/316.cf0000644000175100017510000000361212332665147023446 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines as separate lines, using regexes (different order than in original) # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { delete_lines: "\s+Three.*" select_region => test_select; "BEGIN" select_region => test_select; "END" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/301.cf0000644000175100017510000000344512332665147023444 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/219.cf0000644000175100017510000000361112332665147023447 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way, different patterns (different order than original) # select_region, include_start_delimiter, include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/012.cf0000644000175100017510000000310212332665147023431 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "$(actual)"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => "BEGIN Three potatoe END"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/612.cf0000644000175100017510000000372712332665147023454 0ustar00a10038a1003800000000000000####################################################### # # Don't delete multiple lines if they are not in the exact order # Two matching regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe break Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe break Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe Four"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/020.cf0000644000175100017510000000325112332665147023435 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, original way, different patterns (different order than original) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header One potato Two potato Four trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*Three.*", ".*BEGIN.*", ".*END.*" }; files: "$(G.testfile).actual" edit_line => test_delete("$(tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/101.cf0000644000175100017510000000354212332665147023440 0ustar00a10038a1003800000000000000####################################################### # # Delete a line # Region editing, include_start_delimiter and include_end_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; include_end_delimiter => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/603.cf0000644000175100017510000000361212332665147023445 0ustar00a10038a1003800000000000000####################################################### # # Delete a group of three lines at once # Two regions - Only the first region is selected # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " Three potatoe Four"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/609.cf0000644000175100017510000000361612332665147023457 0ustar00a10038a1003800000000000000####################################################### # # Delete a number of lines via an slist, different way # Two regions - expect changes to occur in both # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Four END middle middle BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_delete; } bundle edit_line test_delete { vars: "str" slist => { "BEGIN", " Three potatoe", "END" }; delete_lines: "$(str)" select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/328.cf0000644000175100017510000000374012332665147023453 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a singleton list which matches # select_region, only include_start_delimiter # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { " T" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; include_start_delimiter => "true"; } body delete_select test_match(m) { delete_if_not_startwith_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/037.cf0000644000175100017510000000342612332665147023451 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, all of which match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*O.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}); } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/07_delete_lines/436.cf0000644000175100017510000000367612332665147023463 0ustar00a10038a1003800000000000000####################################################### # # Delete a line using a list, some of which match # select_region, doesn't include header or trailer # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "header header BEGIN One potato Two potato Three potatoe Four END trailer trailer"; "expected" string => "header header BEGIN Two potato Three potatoe Four END trailer trailer"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" slist => { ".*T.*", ".*C.*" }; files: "$(G.testfile).actual" edit_line => test_delete(".*potat.*", "@(test.tstr)"); } bundle edit_line test_delete(str, match) { delete_lines: "$(str)" delete_select => test_match(@{match}), select_region => test_select; } body select_region test_select { select_start => "BEGIN"; select_end => "END"; } body delete_select test_match(m) { delete_if_not_match_from_list => { @{m} }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/this_promiser.cf0000644000175100017510000001240312411001073023034 0ustar00a10038a1003800000000000000####################################################### # # Test this.promiser on files promises # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body classes promiser0_generic { promise_repaired => { "$(this.promiser)_repaired", "$(this.promiser)_0_ok" }; promise_kept => { "$(this.promiser)_kept", "$(this.promiser)_0_ok" }; } body classes promiser1_generic { promise_repaired => { "$(this.promiser)_repaired", "$(this.promiser)_1_ok" }; promise_kept => { "$(this.promiser)_kept", "$(this.promiser)_1_ok" }; } body classes promiser2_generic { promise_repaired => { "$(this.promiser)_repaired", "$(this.promiser)_2_ok" }; promise_kept => { "$(this.promiser)_kept", "$(this.promiser)_2_ok" }; } body classes promiser3_generic { promise_repaired => { "$(this.promiser)_repaired", "$(this.promiser)_3_ok" }; promise_kept => { "$(this.promiser)_kept", "$(this.promiser)_3_ok" }; } body classes promiser4_generic { promise_repaired => { "$(this.promiser)_repaired", "$(this.promiser)_4_ok" }; promise_kept => { "$(this.promiser)_kept", "$(this.promiser)_4_ok" }; } bundle agent init { vars: "files" slist => { "aa", "ab", "ac", "ba", "bb", "bc" }; files: "$(G.testdir)/copy_me_source" create => "true"; } ####################################################### bundle agent test { commands: "$(G.true)" classes => promiser0_generic; files: # 6 promisers "$(G.testdir)/$(init.files)" create => "true", classes => promiser1_generic; # 3 promisers "$(G.testdir)/a.*" perms => m("666"), classes => promiser2_generic; # 2 promisers - dir + 1 file "$(G.testdir)" file_select => by_exec_cmd, perms => m("666"), classes => promiser2_generic, depth_search => test_recurse; # 7 promisers - dir + 6 files "$(G.testdir)" file_select => test_plain, depth_search => test_recurse, delete => tidyfiles, classes => promiser3_generic; "$(G.testdir)/copy_me" copy_from => local_cp("$(this.promiser)_source"); methods: "template_test" usebundle => template_test; } bundle agent template_test { vars: "testdir" string => "$(G.testdir)/template_test"; "cfe_files" slist => { "cfe_file1", "cfe_file2" }; "mustache_files" slist => { "mustache_file1", "mustache_file2" }; files: # create empty files so that we can test pattern and file_select cases "$(testdir)/." create => "true"; "$(testdir)/$(cfe_files)" create => "true"; "$(testdir)/$(mustache_files)" create => "true"; "$(testdir)/$(cfe_files).cf-template" create => "true", edit_line => insert_lines("Just a cfengine line for $(this.promiser)."); "$(testdir)/$(mustache_files).mustache" create => "true", edit_line => insert_lines("Just a mustache line for $(this.promiser)."); "$(testdir)/cfe_file[1,2]" perms => m("666"), template_method => "cfengine", edit_template => "$(this.promiser).cf-template", classes => promiser4_generic; "$(testdir)/mustache_.*" file_select => mustache_files, perms => m("666"), template_method => "mustache", edit_template => "$(this.promiser).mustache", classes => promiser4_generic; } body file_select mustache_files { leaf_name => { "@(template_test.mustache_files)" }; file_result => "leaf_name"; } body delete tidyfiles { dirlinks => "delete"; rmdirs => "true"; } body file_select test_plain { leaf_name => { "[a,b][a,b,c]" }; file_types => { "plain" }; file_result => "file_types.leaf_name"; } body file_select by_exec_cmd # Redmine #3530 { leaf_name => {"ba"}; exec_program => "/bin/ls $(this.promiser)"; file_result => "leaf_name.exec_program"; } body depth_search test_recurse { depth => "inf"; } ####################################################### bundle agent check { vars: "ok_promisers" slist => classesmatching(".*_ok"); "ok_0_count" int => countclassesmatching(".*_0_ok"); "ok_1_count" int => countclassesmatching(".*_1_ok"); "ok_2_count" int => countclassesmatching(".*_2_ok"); "ok_3_count" int => countclassesmatching(".*_3_ok"); "ok_4_count" int => countclassesmatching(".*_4_ok"); classes: "ok_expand" expression => none("__this_promiser_[0,1,2,3]_ok", ok_promisers); "ok0" expression => strcmp("$(ok_0_count)", 1); "ok1" expression => strcmp("$(ok_1_count)", 6); "ok2" expression => strcmp("$(ok_2_count)", 5); "ok3" expression => strcmp("$(ok_3_count)", 7); "ok4" expression => strcmp("$(ok_4_count)", 4); "ok5" expression => fileexists("$(G.testdir)/copy_me"); "ok" and => { "ok_expand", "ok0", "ok1", "ok2", "ok3", "ok4", "ok5" }; reports: DEBUG:: "$(ok_promisers)"; "0: $(ok_0_count)"; "1: $(ok_1_count)"; "2: $(ok_2_count)"; "3: $(ok_3_count)"; "4: $(ok_4_count)"; DEBUG.!ok5:: "5: file not copied"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/replace_patterns/0000755000175100017510000000000012332665147023212 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/replace_patterns/noop_replace.cf0000644000175100017510000000343612332665147026200 0ustar00a10038a1003800000000000000####################################################### # # Replace a pattern and use match.0 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN kernel /vmlinuz-2.6.18-348.el5 ro noapic nolapic apci=off time process_timing=everything root=LABEL=/foo kernel /vmlinuz-2.6.18-348.el5 ro root=LABEL=/1 END"; "expected" string => "BEGIN kernel /vmlinuz-2.6.18-348.el5 ro noapic nolapic apci=off time process_timing=everything root=LABEL=/foo kernel /vmlinuz-2.6.18-348.el5 ro root=LABEL=/1 END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ###################################################### # bundle agent test { files: "$(G.testfile).actual" edit_line => test_replace("$(init.parameters)"); } bundle edit_line test_replace(parameters) { replace_patterns: # should not change anything "^.+$" replace_with => value("$(match.0)"); } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/replace_patterns/basic_replace.cf0000644000175100017510000000272212332665147026303 0ustar00a10038a1003800000000000000####################################################### # # Replace a pattern and use match.0 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN END"; "expected" string => "BEGIN_REPLACED END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ###################################################### # bundle agent test { files: "$(G.testfile).actual" edit_line => test_replace("$(init.parameters)"); } bundle edit_line test_replace(parameters) { replace_patterns: "^BEGIN$" replace_with => value("BEGIN_REPLACED"); } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/replace_patterns/staging/0000755000175100017510000000000012332665147024646 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/replace_patterns/staging/advanced_replace.cf0000644000175100017510000000457212332665147030430 0ustar00a10038a1003800000000000000####################################################### # # Replace a pattern and use match.0 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN kernel /vmlinuz-2.6.18-348.el5 ro noapic nolapic apci=off time process_timing=everything root=LABEL=/foo kernel /vmlinuz-2.6.18-348.el5 ro root=LABEL=/1 END"; "parameters" string => "noapic nolapic apci=off time process_timing=everything"; "expected" string => "BEGIN kernel /vmlinuz-2.6.18-348.el5 ro root=LABEL=/1 noapic nolapic apci=off time process_timing=everything kernel /vmlinuz-2.6.18-348.el5 ro root=LABEL=/foo noapic nolapic apci=off time process_timing=everything END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ###################################################### # bundle agent test { files: "$(G.testfile).actual" edit_line => test_replace("$(init.parameters)"); } bundle edit_line test_replace(parameters) { replace_patterns: # replace the parameters with an empty string "$(parameters)" handle => "test_replace_parameters", replace_with => value(""); # should append $(parameters) to any line that begins with "kernel" "^\s*(kernel.+)$" depends_on => { "test_replace_parameters" }, replace_with => value("$(match.1) $(parameters)"); # should not change anything "^\s*(kernel.+)$" replace_with => value("$(match.0)"); } body replace_with value(x) { replace_value => "$(x)"; occurrences => "all"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/0000755000175100017510000000000012352022221021576 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/05_classes/004.cf0000644000175100017510000000372212352022221022417 0ustar00a10038a1003800000000000000####################################################### # # Delete a line that isn't there, action_policy=>"warn", ensure that a promise_kept class gets set # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "keep this and this keep this too"; "expected" string => "keep this and this keep this too"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => ".*delete.*"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" action => test_warn_only, classes => full_set; } body action test_warn_only { action_policy => "warn"; } body classes full_set { promise_kept => { "pass" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { methods: pass.!fail:: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); reports: !pass|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/102.cf0000644000175100017510000000673012243421446022433 0ustar00a10038a1003800000000000000####################################################### # # Test multiple promise_repaired and cancel_repaired (contrived example) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_repaired => { "promise_repaired", "p2_repaired" }; cancel_repaired => { "cancel_repaired", "cancel_kept", "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[p2_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "p2_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/#008.cf#0000644000175100017510000000251012246156041022535 0ustar00a10038a1003800000000000000########################################################################### # # Test that a files promise consisting only of body_select, verifies # that a file exists, without changing anything if it does not. # # file exists => promise kept, not repaired, not failed # # file does not exist => promise failed, not kept, not repaired # ########################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### body edit_defaults empty { empty_file_before_editing => "true"; edit_backup => "false"; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } bundle agent init { files: "$(G.testdir)/empty_file" delete => clean; "$(G.testdir)/full_file" create => "true", edit_defaults => empty, edit_line => init_insert("$(body)"); } ####################################################### body file_select only_empty { search_size => irange("0", "0"); file_result => "size"; } body classes if_repair_failed(x) { repair_failed => { "$(x)" }; } body classes if_satisfied(x) { promise_repaired => { "$(x)" }; } body classes if_kept(x) { promise_kept => { "$(x)" }; } bundle agent test { }cfengine-3.6.2/tests/acceptance/10_files/05_classes/006.cf0000644000175100017510000000372012352022221022417 0ustar00a10038a1003800000000000000####################################################### # # Delete a line that isn't there, action_policy=>"nop", ensure that a promise_kept class gets set # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "keep this and this keep this too"; "expected" string => "keep this and this keep this too"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => ".*delete.*"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" action => test_warn_only, classes => full_set; } body action test_warn_only { action_policy => "nop"; } body classes full_set { promise_kept => { "pass" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { methods: pass.!fail:: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); reports: !pass|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/002.cf0000644000175100017510000000353412332665147022440 0ustar00a10038a1003800000000000000####################################################### # # Delete a line that isn't there, ensure that a promise_kept class gets set # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "keep this and this keep this too"; "expected" string => "keep this and this keep this too"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => ".*delete.*"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => full_set; } body classes full_set { promise_kept => { "pass" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { methods: pass.!fail:: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); reports: !pass|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/0000755000175100017510000000000012332665147023254 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/105.cf0000644000175100017510000000755712243421446024102 0ustar00a10038a1003800000000000000####################################################### # # Test promise_kept+repaired and cancel_kept+repaired (broken multiple promises set classes, see comments) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => init_insert("$(init.body)"), edit_defaults => init_empty; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and test, it is only executed ONCE, so it only # sets the repaired promises. "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/112.cf0000644000175100017510000000715112243421446024066 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" # create => "true", # file will not exist! edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => "ON"; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => ""; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/007.cf0000644000175100017510000000426412243421446024073 0ustar00a10038a1003800000000000000####################################################### # # Delete a line that isn't there, action_policy=>"nop", ensure that a promise_kept class gets set # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", perms => test_mode("0644"); "$(G.testfile).link" link_from => init_link("$(G.testfile)"); } body link_from init_link(src) { source => "$(src)"; } ####################################################### bundle agent test { files: "$(G.testfile).link" perms => test_mode("0600"), classes => fail_check; "$(G.testfile)" perms => test_mode("0644"), classes => kept_check; } body perms test_mode(m) { mode => "$(m)"; } body classes fail_check { promise_kept => { "fail1" }; promise_repaired => { "fail1" }; repair_failed => { "pass1" }; # Cannot chmod a sylink! repair_denied => { "fail1" }; repair_timeout => { "fail1" }; } body classes kept_check { promise_kept => { "pass2" }; # Original mode should not have changed promise_repaired => { "fail2" }; repair_failed => { "fail2" }; repair_denied => { "fail2" }; repair_timeout => { "fail2" }; } ####################################################### bundle agent check { classes: "ok" and => { "pass1", "pass2", "!fail1", "!fail2" }; reports: DEBUG.!pass1:: "Trying to chmod a symlink did not fail like it should"; DEBUG.fail1:: "Trying to chmod a symlink gave a return other than repair_failed"; DEBUG.!pass2:: "Something was funky with the target of a symlink"; DEBUG.fail2:: "Doing a chmod on a symlink changed the target file instead!"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/107.cf0000644000175100017510000001025512243421446024071 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (still incorrectly done!) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", edit_line => test_insert, edit_defaults => init_empty; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/114.cf0000644000175100017510000000703112316547775024104 0ustar00a10038a1003800000000000000####################################################### # # Test setting two classes in one promise # Copy file with one mode, then copy again with different mode # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; files: "$(G.testfile)" copy_from => local("$(G.etc_group)"), perms => mode("666"); } body copy_from local(f) { source => "$(f)"; } body perms mode(m) { mode => "$(m)"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" copy_from => local("$(G.etc_group)"), # Same file perms => mode("644"), # Different mode classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/103.cf0000644000175100017510000000716512243421446024073 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired (different location in edit_line) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/104.cf0000644000175100017510000000716312243421446024072 0ustar00a10038a1003800000000000000####################################################### # # Test promise_kept and cancel_kept # Insert lines to a file, then verify that insert promise is kept # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => init_insert("$(init.body)"), edit_defaults => init_empty, classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/109.cf0000644000175100017510000001030212243421446024064 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (correctly done!) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/003.cf0000644000175100017510000000423112332665147024070 0ustar00a10038a1003800000000000000####################################################### # # Try to delete a line, action_policy=>"warn", ensure that a repair_denied class gets set (issue 441) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "keep this and this but delete one line keep this too"; "expected" string => "keep this and this but delete one line keep this too"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => ".*delete.*"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => full_set; } body classes full_set { promise_kept => { "fail" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "pass" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { classes: "no_difference" expression => returnszero( "$(G.diff) -q $(G.testfile).actual $(G.testfile).expected", "noshell"); "ok" and => { "pass", "!fail", "no_difference" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/005.cf0000644000175100017510000000436012332665147024075 0ustar00a10038a1003800000000000000####################################################### # # Attempt to delete a line, action_policy=>"nop", ensure that a repair_denied class gets set (issue 441) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "keep this and this but delete one line keep this too"; "expected" string => "keep this and this but delete one line keep this too"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => ".*delete.*"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" action => warn_only, classes => full_set; } body action warn_only { action_policy => "nop"; } body classes full_set { promise_kept => { "fail" }; promise_repaired => { "fail" }; repair_failed => { "fail" }; repair_denied => { "pass" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { classes: "no_difference" expression => returnszero( "$(G.diff) -q $(G.testfile).actual $(G.testfile).expected", "noshell"); "ok" and => { "pass", "!fail", "no_difference" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile).*"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/110.cf0000644000175100017510000001015212243421446024057 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (correctly done!) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => test_insert; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/111.cf0000644000175100017510000001026412243421446024064 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (second promise is not kept because files are different) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => test_insert, edit_defaults => init_empty; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => "ON"; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => ""; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/113.cf0000644000175100017510000000727612243421446024077 0ustar00a10038a1003800000000000000####################################################### # # Test repair_failed and cancel_notkept (different location and results) # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" # create => "true", # file will not exist! edit_line => init_insert("$(body)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)", # Promise never executed, so classes not set! classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => ""; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => "ON"; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/108.cf0000644000175100017510000001026412243421446024072 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (second promise is not kept because files are different) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; "body2" string => "BEGIN One potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" edit_line => test_insert, edit_defaults => init_empty; } bundle edit_line test_insert { insert_lines: "$(init.body2)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/106.cf0000644000175100017510000001015112243421446024063 0ustar00a10038a1003800000000000000####################################################### # # Same as 105.cf, but two separate edit_line promises (incorrect test, see comments) # Test promise_kept+repaired and cancel_kept+repaired (multiple promises set classes) # Insert lines to a file (setting/clearing classes), verify that insert # promise is kept (which sets/clears more classes) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)" classes => all_classes; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", edit_line => test_insert("$(init.body)"), edit_defaults => init_empty; } bundle edit_line test_insert(str) { insert_lines: "$(str)" classes => all_classes; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: # NOTE: bundle edit_line init_insert(str) is CACHED, so even though it # is mentioned in init and we call test_insert from test, the promises are # the same, and are only executed ONCE, so it only sets the repaired # promises. "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/staging/101.cf0000644000175100017510000000712412243421446024064 0ustar00a10038a1003800000000000000####################################################### # # Test promise_repaired and cancel_repaired # Insert lines to a file, verify that insert promise is repaired # # Present in both 00_basics/03_bodies and 10_files/05_classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "body" string => "BEGIN One potato Two potato Three potatoes Four END"; files: "$(G.testfile)" create => "true", edit_line => init_insert("$(body)"), edit_defaults => init_empty, classes => all_classes; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } # These set/clear global classes, so they can be tested in another bundle body classes all_classes { promise_kept => { "promise_kept" }; promise_repaired => { "promise_repaired" }; repair_failed => { "repair_failed" }; repair_denied => { "repair_denied" }; repair_timeout => { "repair_timeout" }; cancel_kept => { "cancel_kept" }; cancel_repaired => { "cancel_repaired" }; cancel_notkept => { "cancel_notkept" }; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { # These variables determine the conditions being tested vars: "expect[promise_kept]" string => ""; "expect[promise_repaired]" string => "ON"; "expect[repair_failed]" string => ""; "expect[repair_denied]" string => ""; "expect[repair_timeout]" string => ""; "expect[cancel_kept]" string => "ON"; "expect[cancel_repaired]" string => ""; "expect[cancel_notkept]" string => "ON"; # Everything from here down is "boilerplate" to these 1xx.cf tests "lookfor" slist => { "promise_kept", "promise_repaired", "repair_failed", "repair_denied", "repair_timeout", "cancel_kept", "cancel_repaired", "cancel_notkept", }; classes: "p1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "$(lookfor)", }; "p2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "!$(lookfor)", }; "pass_$(lookfor)" xor => { "p1_$(lookfor)", "p2_$(lookfor)" }; "f1_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", "ON"), "!$(lookfor)", }; "f2_$(lookfor)" and => { strcmp("$(expect[$(lookfor)])", ""), "$(lookfor)", }; "f3_$(lookfor)" not => isvariable("expect[$(lookfor)]"); "fail_$(lookfor)" or => {"f1_$(lookfor)", "f2_$(lookfor)", "f3_$(lookfor)"}; "oops" expression => classmatch("fail.*"); "ok" and => { classmatch("pass.*"), "!oops" }; reports: DEBUG:: "ok: class '$(lookfor)' was set (should be)" ifvarclass => "p1_$(lookfor)"; "ok: class '$(lookfor)' was not set (should not be)" ifvarclass => "p2_$(lookfor)"; "ERROR: class '$(lookfor)' WAS NOT set (should be)" ifvarclass => "f1_$(lookfor)"; "ERROR: class '$(lookfor)' was set (should NOT be)" ifvarclass => "f2_$(lookfor)"; "ERROR: missing variable expect['$(lookfor)']" ifvarclass => "f3_$(lookfor)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/05_classes/001.cf0000644000175100017510000000354312332665147022437 0ustar00a10038a1003800000000000000####################################################### # # Delete a line, ensure that a promise_repaired class gets set # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "keep this and this but delete one line keep this too"; "expected" string => "keep this and this keep this too"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => ".*delete.*"; files: "$(G.testfile).actual" edit_line => test_delete("$(test.tstr)"); } bundle edit_line test_delete(str) { delete_lines: "$(str)" classes => full_set; } body classes full_set { promise_kept => { "fail" }; promise_repaired => { "pass" }; repair_failed => { "fail" }; repair_denied => { "fail" }; repair_timeout => { "fail" }; } ####################################################### bundle agent check { methods: pass.!fail:: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); reports: !pass|fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/0000755000175100017510000000000012400110676022007 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/templating/empty_template_empty_file.cf.template0000644000175100017510000000010712316547775031423 0ustar00a10038a1003800000000000000[%CFEngine no_such_class:: %] Redmine#3870: text will not be inserted cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_render_quote.cf0000644000175100017510000000325712400110676026715 0ustar00a10038a1003800000000000000####################################################### # # Acceptance test to ensure that mustache renders quotes in variables # correctly. # # Redmine: https://dev.cfengine.com/issues/6516 ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "variable_containing_double_quote" string => 'Something "special" with quotes'; "variable_containing_single_quote" string => "Something 'special' with quotes"; files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "template_file" string => "$(this.promise_filename).mustache"; files: "$(G.testfile)" create => "true", edit_template => "$(template_file)", template_method => "mustache"; reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile)"; } ####################################################### bundle agent check { vars: "expect" string => readfile("$(this.promise_filename).expected", 4000); "actual" string => readfile("$(G.testfile)", 4000); classes: "ok" expression => regcmp("$(expect)", "$(actual)"); reports: DEBUG:: "expect: '$(expect)'"; "actual: '$(actual)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_expect_list_find_string.cf0000644000175100017510000001326512352022221031124 0ustar00a10038a1003800000000000000####################################################### # # Test that mustache DTRT when encountering string when expects list. Also # check that after mustache template is applied you have a different filestat # (indicating you wrote to a different file and moved into place) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { methods: "empty good" usebundle => file_empty("$(G.testfile).good"); "empty bad" usebundle => file_empty("$(G.testfile).bad"); "first filestat good" usebundle => init_filestat("good1", "$(G.testfile).good"); "first filestat bad" usebundle => init_filestat("bad1", "$(G.testfile).bad"); "Remove good" usebundle => dcs_fini("$(G.testfile).good"); "Remove bad" usebundle => dcs_fini("$(G.testfile).bad"); "ready good" usebundle => file_make("$(G.testfile).good", "# Set good"); "ready bad" usebundle => file_make("$(G.testfile).bad", "# Set bad"); "link good" usebundle => file_hardlink("$(G.testfile).good", "$(G.testfile).goodlink"); "link bad" usebundle => file_hardlink("$(G.testfile).bad", "$(G.testfile).badlink"); "second filestat good" usebundle => init_filestat("good2", "$(G.testfile).good"); "second filestat bad" usebundle => init_filestat("bad2", "$(G.testfile).bad"); } bundle agent init_filestat(n, f) { vars: "filestat_$(n)" string => format("%s,%s", filestat($(f), "basename"), filestat($(f), "nlink")); } ####################################################### bundle agent test { methods: "mustache good" usebundle => file_mustache_jsonstring($(template), '{"mykeys": ["template expects list of strings"]}', "$(G.testfile).good"); "mustache bad" usebundle => file_mustache_jsonstring($(template), '{"mykeys": "string but template expects list of strings"}', "$(G.testfile).bad"); "third filestat good" usebundle => init_filestat("good3", "$(G.testfile).good"); "third filestat bad" usebundle => init_filestat("bad3", "$(G.testfile).bad"); vars: "template" string => "$(this.promise_filename).mustache"; "actual_good" string => readfile("$(G.testfile).good", 4096); "actual_bad" string => readfile("$(G.testfile).bad", 4096); } ####################################################### bundle agent check { vars: "expected_good" string => "#DO NOT EDIT - MANAGED FILE template expects list of strings "; "expected_bad" string => "# Set bad"; "filestats_good" slist => { "$(init_filestat.filestat_good1)", "$(init_filestat.filestat_good2)", "$(init_filestat.filestat_good3)" }; "filestats_bad" slist => { "$(init_filestat.filestat_bad1)", "$(init_filestat.filestat_bad2)", "$(init_filestat.filestat_bad3)" }; "filestats_good_str" string => format("%S", filestats_good); "filestats_bad_str" string => format("%S", filestats_bad); classes: "ok_filestats_good_1_2" not => strcmp("$(init_filestat.filestat_good1)", "$(init_filestat.filestat_good2)"); "ok_filestats_good_2_3" not => strcmp("$(init_filestat.filestat_good2)", "$(init_filestat.filestat_good3)"); "ok_filestats_bad_1_2" not => strcmp("$(init_filestat.filestat_bad1)", "$(init_filestat.filestat_bad2)"); "ok_filestats_bad_2_3" expression => strcmp("$(init_filestat.filestat_bad2)", "$(init_filestat.filestat_bad3)"); "ok_content_good" expression => strcmp($(expected_good), $(test.actual_good)); "ok_content_bad" expression => strcmp($(expected_bad), $(test.actual_bad)); methods: "" usebundle => dcs_passif_expected("ok_filestats_good_1_2,ok_filestats_good_2_3,ok_filestats_bad_1_2,ok_filestats_bad_2_3,ok_content_good,ok_content_bad", "", $(this.promise_filename)), inherit => "true"; reports: EXTRA:: "OK: As expected good '$(expected_good)'" ifvarclass => "ok_content_good"; "OK: As expected bad '$(expected_bad)'" ifvarclass => "ok_content_bad"; "OK: good filestats $(filestats_good_str) change from step 1 to step 2" ifvarclass => "ok_filestats_good_1_2"; "OK: good filestats $(filestats_good_str) change from step 2 to step 3" ifvarclass => "ok_filestats_good_2_3"; "OK: bad filestats $(filestats_bad_str) change from step 1 to step 2" ifvarclass => "ok_filestats_bad_1_2"; "OK: bad filestats $(filestats_bad_str) don't change from step 2 to step 3" ifvarclass => "ok_filestats_bad_2_3"; DEBUG:: "FAIL: Expected '$(expected_good)' <> '$(test.actual_good)'" ifvarclass => "!ok_content_good"; "FAIL: Expected '$(expected_bad)' <> '$(test.actual_bad)'" ifvarclass => "!ok_content_bad"; "FAIL: good filestats $(filestats_good_str) don't change enough from step 1 to step 2" ifvarclass => "!ok_filestats_good_1_2"; "FAIL: good filestats $(filestats_good_str) don't change enough from step 2 to step 3" ifvarclass => "!ok_filestats_good_2_3"; "FAIL: bad filestats $(filestats_bad_str) don't change enough from step 1 to step 2" ifvarclass => "!ok_filestats_bad_1_2"; "FAIL: bad filestats $(filestats_bad_str) change from step 2 to step 3" ifvarclass => "!ok_filestats_bad_2_3"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/cftemplate.cf.template0000644000175100017510000000006612316547775026305 0ustar00a10038a1003800000000000000[%CFEngine any:: %] 1 2 [%CFEngine cfengine:: %] 3 4 5cfengine-3.6.2/tests/acceptance/10_files/templating/timed/0000755000175100017510000000000012400110676023111 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/templating/timed/expired_edit_line_locks.cf0000644000175100017510000000262512400110676030277 0ustar00a10038a1003800000000000000# Check whether file promises have a shorter expiry time than edit_line promises # resulting from templates. This will create an empty file because the file is # opened for editing, but all the edit_line promises have expired. body common control { inputs => { "../../../dcs.cf.sub", "../../../plucked.cf.sub" }; bundlesequence => { default($(this.promise_filename)) }; } bundle agent test { commands: # Note, no -K, we are testing locks. "$(sys.cf_agent) -v -D AUTO,DEBUG -f $(this.promise_filename).sub" contain => in_shell; } bundle agent check { methods: test_pass_1:: "any" usebundle => dcs_wait($(this.promise_filename), 70); vars: test_pass_2:: "content_edit_line" string => readfile("$(G.testfile).edit_line", 10000); "content_cftemplate" string => readfile("$(G.testfile).cftemplate", 10000); "content_mustache" string => readfile("$(G.testfile).mustache", 10000); classes: test_pass_2:: "ok_edit_line" expression => strcmp($(content_edit_line), "text"), scope => "namespace"; "ok_cftemplate" expression => strcmp($(content_cftemplate), "text"), scope => "namespace"; "ok_mustache" expression => strcmp($(content_mustache), "text"), scope => "namespace"; methods: test_pass_2:: "any" usebundle => dcs_passif("ok_edit_line.ok_cftemplate.ok_mustache", $(this.promise_filename)); } cfengine-3.6.2/tests/acceptance/10_files/templating/timed/expired_edit_line_locks.cf.sub0000644000175100017510000000132212352564253031072 0ustar00a10038a1003800000000000000body common control { inputs => { "../../../dcs.cf.sub", "../../../plucked.cf.sub" }; bundlesequence => { default($(this.promise_filename)) }; } bundle agent init { methods: "any" usebundle => file_make("$(G.testfile).template", "text"); } bundle agent test { files: "$(G.testfile).edit_line" create => "true", edit_line => insert_lines("text"), edit_defaults => empty; "$(G.testfile).cftemplate" create => "true", edit_template => "$(G.testfile).template", template_method => "cfengine"; "$(G.testfile).mustache" create => "true", edit_template => "$(G.testfile).template", template_method => "mustache"; } cfengine-3.6.2/tests/acceptance/10_files/templating/missing_template_file.cf0000644000175100017510000000273012352022221026660 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #4241: set correct classes if template is missing # ############################################################################## body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true", edit_template => "$(this.promise_filename).nonexistant", classes => scoped_classes_generic("namespace", "test_file_template"); methods: DEBUG:: "report" usebundle => dcs_report_generic_classes("test_file_template"); } ####################################################### bundle agent check { classes: "ok" and => { "!test_file_template_kept", "test_file_template_repaired", # create => "true" "test_file_template_failed", # edit_template "!test_file_template_denied", "!test_file_template_timeout" }; reports: DEBUG.created:: "Correctly created the test file $(G.testfile)"; DEBUG.!created:: "Erroneously did not create the test file $(G.testfile)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_section.cf0000644000175100017510000000167512332665147025703 0ustar00a10038a1003800000000000000####################################################### # # Check that we warn about Mustache sections over non-iterables/non-booleans # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { methods: "" usebundle => dcs_fini($(G.testfile)); } ####################################################### bundle agent check { methods: "" usebundle => dcs_passif_output1(".*Mustache sections can only take a boolean or a container.+value, but section 'x' isn't getting one of those.*", "$(sys.cf_agent) -KI -f $(this.promise_filename).sub | grep Mustache", $(this.promise_filename)); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_render_quote.cf.expected0000644000175100017510000000042512400110676030507 0ustar00a10038a1003800000000000000# Escaped variable references by default: Something "special" with quotes Something 'special' with quotes # Unescaped variable references: Something "special" with quotes Something 'special' with quotes Something "special" with quotes Something 'special' with quotes cfengine-3.6.2/tests/acceptance/10_files/templating/demo.expected0000644000175100017510000000020212243421446024455 0ustar00a10038a1003800000000000000

    Colors

  • red
  • green
  • blue
  • cfengine-3.6.2/tests/acceptance/10_files/templating/demo.mustache0000644000175100017510000000036512243421446024477 0ustar00a10038a1003800000000000000

    {{header}}

    {{#bug}} {{/bug}} {{#items}} {{#first}}
  • {{name}}
  • {{/first}} {{#link}}
  • {{name}}
  • {{/link}} {{/items}} {{#empty}}

    The list is empty.

    {{/empty}} cfengine-3.6.2/tests/acceptance/10_files/templating/large_template_blocks.cf.template0000644000175100017510000002025212316547775030502 0ustar00a10038a1003800000000000000This first block, smaller than 4096 characters is rendered: [%CFEngine BEGIN %] 00-1234567890123456789012345678901234567890123456789012345678901234567890 01-1234567890123456789012345678901234567890123456789012345678901234567890 02-1234567890123456789012345678901234567890123456789012345678901234567890 03-1234567890123456789012345678901234567890123456789012345678901234567890 04-1234567890123456789012345678901234567890123456789012345678901234567890 05-1234567890123456789012345678901234567890123456789012345678901234567890 06-1234567890123456789012345678901234567890123456789012345678901234567890 07-1234567890123456789012345678901234567890123456789012345678901234567890 08-1234567890123456789012345678901234567890123456789012345678901234567890 09-1234567890123456789012345678901234567890123456789012345678901234567890 [%CFEngine END %] The second block, which is larger than 4096 characters, is not rendered in CFE3.5.x: [%CFEngine BEGIN %] 00-1234567890123456789012345678901234567890123456789012345678901234567890 01-1234567890123456789012345678901234567890123456789012345678901234567890 02-1234567890123456789012345678901234567890123456789012345678901234567890 03-1234567890123456789012345678901234567890123456789012345678901234567890 04-1234567890123456789012345678901234567890123456789012345678901234567890 05-1234567890123456789012345678901234567890123456789012345678901234567890 06-1234567890123456789012345678901234567890123456789012345678901234567890 07-1234567890123456789012345678901234567890123456789012345678901234567890 08-1234567890123456789012345678901234567890123456789012345678901234567890 09-1234567890123456789012345678901234567890123456789012345678901234567890 10-1234567890123456789012345678901234567890123456789012345678901234567890 11-1234567890123456789012345678901234567890123456789012345678901234567890 12-1234567890123456789012345678901234567890123456789012345678901234567890 13-1234567890123456789012345678901234567890123456789012345678901234567890 14-1234567890123456789012345678901234567890123456789012345678901234567890 15-1234567890123456789012345678901234567890123456789012345678901234567890 16-1234567890123456789012345678901234567890123456789012345678901234567890 17-1234567890123456789012345678901234567890123456789012345678901234567890 18-1234567890123456789012345678901234567890123456789012345678901234567890 19-1234567890123456789012345678901234567890123456789012345678901234567890 20-1234567890123456789012345678901234567890123456789012345678901234567890 21-1234567890123456789012345678901234567890123456789012345678901234567890 22-1234567890123456789012345678901234567890123456789012345678901234567890 23-1234567890123456789012345678901234567890123456789012345678901234567890 24-1234567890123456789012345678901234567890123456789012345678901234567890 25-1234567890123456789012345678901234567890123456789012345678901234567890 26-1234567890123456789012345678901234567890123456789012345678901234567890 27-1234567890123456789012345678901234567890123456789012345678901234567890 28-1234567890123456789012345678901234567890123456789012345678901234567890 29-1234567890123456789012345678901234567890123456789012345678901234567890 30-1234567890123456789012345678901234567890123456789012345678901234567890 31-1234567890123456789012345678901234567890123456789012345678901234567890 32-1234567890123456789012345678901234567890123456789012345678901234567890 33-1234567890123456789012345678901234567890123456789012345678901234567890 34-1234567890123456789012345678901234567890123456789012345678901234567890 35-1234567890123456789012345678901234567890123456789012345678901234567890 36-1234567890123456789012345678901234567890123456789012345678901234567890 37-1234567890123456789012345678901234567890123456789012345678901234567890 38-1234567890123456789012345678901234567890123456789012345678901234567890 39-1234567890123456789012345678901234567890123456789012345678901234567890 40-1234567890123456789012345678901234567890123456789012345678901234567890 41-1234567890123456789012345678901234567890123456789012345678901234567890 42-1234567890123456789012345678901234567890123456789012345678901234567890 43-1234567890123456789012345678901234567890123456789012345678901234567890 44-1234567890123456789012345678901234567890123456789012345678901234567890 45-1234567890123456789012345678901234567890123456789012345678901234567890 46-1234567890123456789012345678901234567890123456789012345678901234567890 47-1234567890123456789012345678901234567890123456789012345678901234567890 48-1234567890123456789012345678901234567890123456789012345678901234567890 49-1234567890123456789012345678901234567890123456789012345678901234567890 50-1234567890123456789012345678901234567890123456789012345678901234567890 51-1234567890123456789012345678901234567890123456789012345678901234567890 52-1234567890123456789012345678901234567890123456789012345678901234567890 53-1234567890123456789012345678901234567890123456789012345678901234567890 54-1234567890123456789012345678901234567890123456789012345678901234567890 55-1234567890123456789012345678901234567890123456789012345678901234567890 56-1234567890123456789012345678901234567890123456789012345678901234567890 57-1234567890123456789012345678901234567890123456789012345678901234567890 58-1234567890123456789012345678901234567890123456789012345678901234567890 59-1234567890123456789012345678901234567890123456789012345678901234567890 60-1234567890123456789012345678901234567890123456789012345678901234567890 61-1234567890123456789012345678901234567890123456789012345678901234567890 62-1234567890123456789012345678901234567890123456789012345678901234567890 63-1234567890123456789012345678901234567890123456789012345678901234567890 64-1234567890123456789012345678901234567890123456789012345678901234567890 65-1234567890123456789012345678901234567890123456789012345678901234567890 66-1234567890123456789012345678901234567890123456789012345678901234567890 67-1234567890123456789012345678901234567890123456789012345678901234567890 68-1234567890123456789012345678901234567890123456789012345678901234567890 69-1234567890123456789012345678901234567890123456789012345678901234567890 70-1234567890123456789012345678901234567890123456789012345678901234567890 71-1234567890123456789012345678901234567890123456789012345678901234567890 72-1234567890123456789012345678901234567890123456789012345678901234567890 73-1234567890123456789012345678901234567890123456789012345678901234567890 74-1234567890123456789012345678901234567890123456789012345678901234567890 75-1234567890123456789012345678901234567890123456789012345678901234567890 76-1234567890123456789012345678901234567890123456789012345678901234567890 77-1234567890123456789012345678901234567890123456789012345678901234567890 78-1234567890123456789012345678901234567890123456789012345678901234567890 79-1234567890123456789012345678901234567890123456789012345678901234567890 80-1234567890123456789012345678901234567890123456789012345678901234567890 81-1234567890123456789012345678901234567890123456789012345678901234567890 82-1234567890123456789012345678901234567890123456789012345678901234567890 83-1234567890123456789012345678901234567890123456789012345678901234567890 84-1234567890123456789012345678901234567890123456789012345678901234567890 85-1234567890123456789012345678901234567890123456789012345678901234567890 86-1234567890123456789012345678901234567890123456789012345678901234567890 87-1234567890123456789012345678901234567890123456789012345678901234567890 88-1234567890123456789012345678901234567890123456789012345678901234567890 89-1234567890123456789012345678901234567890123456789012345678901234567890 90-1234567890123456789012345678901234567890123456789012345678901234567890 91-1234567890123456789012345678901234567890123456789012345678901234567890 92-1234567890123456789012345678901234567890123456789012345678901234567890 93-1234567890123456789012345678901234567890123456789012345678901234567890 94-1234567890123456789012345678901234567890123456789012345678901234567890 95-1234567890123456789012345678901234567890123456789012345678901234567890 96-1234567890123456789012345678901234567890123456789012345678901234567890 97-1234567890123456789012345678901234567890123456789012345678901234567890 98-1234567890123456789012345678901234567890123456789012345678901234567890 99-1234567890123456789012345678901234567890123456789012345678901234567890 [%CFEngine END %] cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_demo.cf0000644000175100017510000000305512352022221025133 0ustar00a10038a1003800000000000000####################################################### # # Demo from mustache.github.io # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "origtestdir" string => dirname("$(this.promise_filename)"); files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "template_file" string => "$(init.origtestdir)/demo.mustache"; files: "$(G.testfile)" create => "true", edit_template => "$(template_file)", template_method => "mustache", template_data => readjson("$(init.origtestdir)/demo.json", 10000); reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile)"; } ####################################################### bundle agent check { vars: "expect" string => readfile("$(init.origtestdir)/demo.expected", 10000); "actual" string => readfile("$(G.testfile)", 10000); classes: "ok" expression => regcmp("$(expect)", "$(actual)"); reports: DEBUG:: "expect: '$(expect)'"; "actual: '$(actual)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_section.cf.sub.mustache0000644000175100017510000000002112332665147030263 0ustar00a10038a1003800000000000000{{#x}}{{.}}{{/x}}cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_section.cf.sub0000644000175100017510000000060712352022221026443 0ustar00a10038a1003800000000000000body common control { inputs => { "../../plucked.cf.sub" }; bundlesequence => { test }; version => "1.0"; } bundle agent test { methods: "m" usebundle => file_mustache_jsonstring("$(this.promise_filename).mustache", '{ "x": "y" }', "$(sys.workdir)/state/out.txt"); } cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_repair_existing.cf0000644000175100017510000000334412352022221027404 0ustar00a10038a1003800000000000000####################################################### # # Test that _repaired classes are defined on template repair # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "origtestdir" string => dirname("$(this.promise_filename)"); files: "$(G.testfile)" create => "true", comment => "Need to see if we define repair when file exists"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "template_file" string => "$(init.origtestdir)/demo.mustache"; files: "$(G.testfile)" edit_template => "$(template_file)", template_method => "mustache", classes => classes_generic("templated_file"), template_data => readjson("$(init.origtestdir)/demo.json", 4096); reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile)"; } bundle agent check { vars: "expect" string => readfile("$(init.origtestdir)/demo.expected", 4096); "actual" string => readfile("$(G.testfile)", 4096); classes: "content_ok" expression => regcmp("$(expect)", "$(actual)"); "repair_ok" expression => "templated_file_repaired"; "ok" and => { "content_ok", "repair_ok" }; reports: DEBUG:: "expect: '$(expect)'"; "actual: '$(actual)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/large_template_blocks.cf0000644000175100017510000000271412316547775026673 0ustar00a10038a1003800000000000000####################################################### # # Test instatiation of template blocks larger than 4096 characters. # Redmine #3852 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "origtestdir" string => dirname("$(this.promise_filename)"); files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "template_file" string => "$(this.promise_filename).template"; classes: files: "$(G.testfile)" create => "true", edit_template => "$(template_file)"; reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile)"; } ####################################################### bundle agent check { vars: "expected" int => "110"; "actual" int => countlinesmatching(".*0123456789.*", "$(G.testfile)"); classes: "ok" expression => strcmp("$(expected)", "$(actual)"); reports: DEBUG:: "expected: '$(expected)'"; "actual: '$(actual)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/templating/empty_template_empty_file.cf0000644000175100017510000000315212316547775027614 0ustar00a10038a1003800000000000000####################################################### # # Redmine#3870: Test that an empty CFEngine template will empty the file. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" edit_defaults => init_empty, create => "true", edit_line => init_insert_lines("TEXT NOT GOOD"); } bundle edit_line init_insert_lines(lines) { insert_lines: "$(lines)" comment => "Append lines if they don't exist"; } body edit_defaults init_empty { empty_file_before_editing => "true"; edit_backup => "false"; #max_file_size => "300000"; } ####################################################### bundle agent test { vars: "template_file" string => "$(this.promise_filename).template"; files: "$(G.testfile)" edit_template => "$(template_file)"; reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile)"; } ####################################################### bundle agent check { vars: "expect" string => ""; "actual" string => readfile("$(G.testfile)", 1000); classes: "ok" expression => regcmp("$(expect)", "$(actual)"); reports: DEBUG:: "expect: '$(expect)'"; "actual: '$(actual)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/demo.datastate.mustache0000644000175100017510000000022312316547775026460 0ustar00a10038a1003800000000000000

    {{vars.test.header}}

    {{#vars.test.items}} {{.}} {{/vars.test.items}} {{#classes.empty}}

    The list is empty.

    {{/classes.empty}} cfengine-3.6.2/tests/acceptance/10_files/templating/cftemplate.cf.expected0000644000175100017510000000001112316547775026261 0ustar00a10038a10038000000000000001 2 3 4 5cfengine-3.6.2/tests/acceptance/10_files/templating/basic_classes.template0000644000175100017510000000014712236160673026355 0ustar00a10038a1003800000000000000[%CFEngine BEGIN %] one [%CFEngine END %] [%CFEngine two:: %] two [%CFEngine default:three:: %] threecfengine-3.6.2/tests/acceptance/10_files/templating/mustache_datastate_demo.cf0000644000175100017510000000333512352022221027166 0ustar00a10038a1003800000000000000####################################################### # # Demo of Mustache templates with no external JSON data # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "origtestdir" string => dirname("$(this.promise_filename)"); files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { classes: "empty" expression => "any"; vars: "template_file" string => "$(init.origtestdir)/demo.datastate.mustache"; "header" string => "Colors"; "items" slist => { "red", "green", "blue" }; files: "$(G.testfile)" create => "true", edit_template => "$(template_file)", template_method => "mustache"; reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile)"; } ####################################################### bundle agent check { vars: "expect" string => '

    Colors

    red green blue

    The list is empty.

    '; "actual" string => readfile("$(G.testfile)", 10000); classes: "ok" expression => strcmp($(expect), $(actual)); reports: DEBUG:: "'$(expect)' != '$(actual)'" ifvarclass => "!ok"; "'$(expect)' == '$(actual)'" ifvarclass => "ok"; "expect: '$(expect)'"; "actual: '$(actual)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/templating/basic_classes.cf0000644000175100017510000000336612332665147025143 0ustar00a10038a1003800000000000000####################################################### # # Test basic classes for CFEngine templates. # Redmine #2928 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_defaults => init_empty, edit_line => init_expect; "$(G.testfile).template" create => "true", edit_line => template, edit_defaults => init_empty; } ####################################################### bundle agent test { classes: "two" expression => "any"; "three" expression => "any"; files: "$(G.testfile).actual" create => "true", edit_defaults => init_empty, edit_template => "$(G.testfile).template"; } ####################################################### bundle edit_line template { insert_lines: "[%CFEngine BEGIN %] one [%CFEngine END %] [%CFEngine two:: %] two [%CFEngine default:three:: %] three " insert_type => "preserve_block"; } ####################################################### bundle edit_line init_expect { insert_lines: "one two three " insert_type => "preserve_block"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_invalid_template.cf0000644000175100017510000000307612332665147027555 0ustar00a10038a1003800000000000000####################################################### # # Test that invalid mustache template does not cause a segfault # Redmine:4702 (https://cfengine.com/dev/issues/4702) ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "template_content" string => ' {{#vars.sys.interfaces}}{{.}} {{#vars.sys.interface_flags[{{.}}]}} {{/vars.sys.interfaces}}'; files: "$(G.testfile).template" create => "true", edit_line => insert_lines($(template_content)), edit_defaults => empty; "$(G.testfile).output" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "template_file" string => "$(G.testfile).template"; files: "$(G.testfile).output" create => "true", edit_template => "$(template_file)", template_method => "mustache"; reports: DEBUG:: "Rendering template file $(template_file) to $(G.testfile).output"; } ####################################################### bundle agent check { classes: "ok" expression => "any", comment => "If we made it to here we didnt segfault"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/templating/staging/0000755000175100017510000000000012352022221023435 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/templating/staging/cftemplate.cf0000644000175100017510000000244112332665147026116 0ustar00a10038a1003800000000000000####################################################### # # Test a complete CFEngine template, including trailing newlines. # Redmine #1900 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testfile).expected" copy_from => local_cp("$(this.promise_filename).expected"); "$(G.testfile).actual" create => "true", edit_defaults => init_empty, edit_template => "$(this.promise_filename).template"; } ####################################################### body copy_from local_cp(from) { source => "$(from)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/staging/array_expansion.cf0000644000175100017510000000315712352022221027157 0ustar00a10038a1003800000000000000####################################################### # # Test array expansion for CFEngine templates. # Redmine #3442 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "data[user-a][home]" string => "/tmp/test/user-a"; methods: "" usebundle => file_make("$(G.testfile).expected", "CASE1: passed var /tmp/test/user-a .foo .bar CASE2: local var /tmp/test/user-a .foo .bar"); "" usebundle => file_make("$(G.testfile).template", "CASE1: passed var $(const.dollar)($(const.dollar)(test2.info)[user-a][home]) .foo .bar CASE2: local var $(const.dollar)($(const.dollar)(test2.local_info)[user-a][home]) .foo .bar"); } ####################################################### bundle agent test { methods: "" usebundle => test2("init.data"); } bundle agent test2(info) { vars: "local_info" string => "init.data"; files: "$(G.testfile).actual" create => "true", edit_defaults => empty, edit_template => "$(G.testfile).template"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/templating/demo.json0000644000175100017510000000033712243421446023636 0ustar00a10038a1003800000000000000{ "header": "Colors", "items": [ {"name": "red", "first": true, "url": "#Red"}, {"name": "green", "link": true, "url": "#Green"}, {"name": "blue", "link": true, "url": "#Blue"} ], "empty": false } cfengine-3.6.2/tests/acceptance/10_files/templating/missing_file.cf.sub0000644000175100017510000000074612316547775025614 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3573: establish message for missing target file with a template # ############################################################################## bundle agent run { files: "/no/such/file" create => "false", edit_defaults => init_empty, edit_template => "$(this.promise_filename)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } cfengine-3.6.2/tests/acceptance/10_files/templating/missing_file.cf0000644000175100017510000000322212316547775025014 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #3573: establish message for missing target file with a template # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: any:: # Run subtests. Need to be in verbose mode to see the output. # The full verbose output is too big for variable assignment here. # So extract (grep) only potentially interesting lines. "subout" string => execresult("$(sys.cf_agent) -KI -b run -f $(this.promise_filename).sub 2>&1 | $(G.grep) '/no/such/file'", "useshell"); } ####################################################### bundle agent check { vars: "must_have" string => ".*Promised to edit.*but file does not exist.*"; "cant_have" string => ".*no longer access file.*"; classes: "ok_1" not => regcmp($(cant_have), "$(test.subout)"); "ok_2" expression => regcmp($(must_have), "$(test.subout)"); reports: DEBUG:: "Attempted subtest '$(this.promise_filename).sub'"; "Significant output was '$(test.subout)'."; DEBUG.!ok_1:: "failing: can't have pattern '$(cant_have)' in subtest"; DEBUG.!ok_2:: "failing: must have pattern '$(must_have)' in subtest"; ok_1.ok_2:: "$(this.promise_filename) Pass"; !(ok_1.ok_2):: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_render_quote.cf.mustache0000644000175100017510000000055312400110676030521 0ustar00a10038a1003800000000000000# Escaped variable references by default: {{vars.init.variable_containing_double_quote}} {{vars.init.variable_containing_single_quote}} # Unescaped variable references: {{&vars.init.variable_containing_double_quote}} {{&vars.init.variable_containing_single_quote}} {{{vars.init.variable_containing_double_quote}}} {{{vars.init.variable_containing_single_quote}}} cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_expect_list_find_string.cf.mustache0000644000175100017510000000007112352022221032723 0ustar00a10038a1003800000000000000#DO NOT EDIT - MANAGED FILE {{#mykeys}}{{.}} {{/mykeys}} cfengine-3.6.2/tests/acceptance/10_files/templating/mustache_abuse.cf0000644000175100017510000000545012243421446025322 0ustar00a10038a1003800000000000000####################################################### # # Abusive Mustache relationship # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "tests" slist => { "0", "1", "2", "3", "4", "5", "6" }; "templates" data => parsejson(' [ "{{x}}", "{{x}} {{y}}", "{{null}}", "{{}}", "{{#boolean}}IT IS TRUE{{/boolean}}", "{{^boolean}}IT IS FALSE{{/boolean}}", "{{#list}}{{k}}={{v}}, {{/list}}" ]'); files: "$(G.testfile).$(tests).tmpl" create => "true", edit_defaults => test_empty, edit_line => init_insert_lines("$(templates[$(tests)])"); } bundle edit_line init_insert_lines(lines) { insert_lines: "$(lines)" comment => "Append lines if they don't exist"; } ####################################################### bundle agent test { vars: "tdata" data => parsejson(' [ "{ \\\"x\\\": 123 }", "{ \\\"x\\\": 123, \\\"y\\\": 456 }", "[ null ]", "{ \\\"x\\\": 123, \\\"y\\\": 456 }", "{\\\"boolean\\\": true}", "{\\\"boolean\\\": false}", "{ \\\"list\\\": [ { \\\"k\\\": 789, \\\"v\\\": 0 }, { \\\"k\\\": null, \\\"v\\\": true }, { \\\"k\\\": -1, \\\"v\\\": -2 } ] }", ]'); files: "$(G.testfile).$(init.tests)" create => "true", edit_defaults => test_empty, edit_template => "$(G.testfile).$(init.tests).tmpl", template_method => "mustache", template_data => parsejson("$(tdata[$(init.tests)])"); reports: DEBUG:: "Rendering template file $(G.testfile).$(init.tests).tmpl to $(G.testfile).$(init.tests)"; } body edit_defaults test_empty { empty_file_before_editing => "true"; edit_backup => "false"; } ####################################################### bundle agent check { vars: "expected" data => parsejson(' [ "123", "123 456", "", "{{}}", "IT IS TRUE" "IT IS FALSE", "789=0, =true, -1=-2, " ]'); "actual_$(init.tests)" string => readfile("$(G.testfile).$(init.tests)", 10000); classes: "ok_$(init.tests)" expression => regcmp("$(expected[$(init.tests)])", "$(actual_$(init.tests))"); "ok" and => { ok_0, ok_1, ok_2, ok_3, ok_4, ok_5 }; reports: DEBUG:: "OK $(init.tests): Expected '$(expected[$(init.tests)])' == '$(actual_$(init.tests))'" ifvarclass => "ok_$(init.tests)"; "FAIL $(init.tests): Expected '$(expected[$(init.tests)])' <> '$(actual_$(init.tests))'" ifvarclass => "!ok_$(init.tests)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/0000755000175100017510000000000012243421446022141 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/delete_tree_001.cf0000644000175100017510000000461512243421446025322 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tree" string => " "; files: "$(G.testfile).actual" create => "true", edit_xml => test_delete("$(test.tree)"); } bundle edit_xml test_delete(str) { delete_tree: "$(str)" select_xpath => "/Potatoes/Potato[@name='OnePotato']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/insert_tree_001.cf0000644000175100017510000000462012243421446025360 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tree" string => " "; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.tree)"); } bundle edit_xml test_insert(str) { insert_tree: "$(str)" select_xpath => "/Potatoes/Potato[@name=\'OnePotato\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/set_text_002.cf0000644000175100017510000000362712243421446024703 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " Marlin"; "expected" string => " Nemo"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "text" string => "Nemo"; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.text)"); } bundle edit_xml test_insert(str) { set_text: "$(str)" build_xpath => "/Server/Service/Engine/OneFish[@type=\'clownfish\']/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine/OneFish[@type=\'clownfish\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/delete_tree_002.cf0000644000175100017510000000471712243421446025326 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " cfe_alias "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tree" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_xml => test_delete("$(test.tree)"); } bundle edit_xml test_delete(str) { delete_tree: "$(str)" build_xpath => "/Server/Service/Engine/OneFish/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/insert_text_002.cf0000644000175100017510000000367312243421446025415 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " Marlin"; "expected" string => " MarlinNemo"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "text" string => "Nemo"; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.text)"); } bundle edit_xml test_insert(str) { insert_text: "$(str)" build_xpath => "/Server/Service/Engine/OneFish/TwoFish[@type=\'clownfish\']/RedFish/BlueFish", select_xpath => "/Server/Service/Engine/OneFish/TwoFish[@type=\'clownfish\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/delete_attribute_001.cf0000644000175100017510000000373112243421446026364 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "attribute_name" string => "topping"; files: "$(G.testfile).actual" create => "true", edit_xml => test_delete_attribute("$(test.attribute_name)"); } bundle edit_xml test_delete_attribute(str) { delete_attribute: "$(str)" select_xpath => "/Potatoes/Potato[@topping=\'brocolli\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/set_attribute_003.cf0000644000175100017510000000404612243421446025717 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - test changing an existing attribute of a node # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "attribute_name" string => "topping"; files: "$(G.testfile).actual" create => "true", edit_xml => test_set("$(test.attribute_name)"); } bundle edit_xml test_set(str) { set_attribute: "$(str)" select_xpath => "/Potatoes/Potato[@name=\'OnePotato\']", attribute_value => "sourcream"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/delete_text_002.cf0000644000175100017510000000362412243421446025347 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " Nemo"; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "text" string => "Nemo"; files: "$(G.testfile).actual" create => "true", edit_xml => test_delete("$(test.text)"); } bundle edit_xml test_delete(str) { delete_text: "$(str)" build_xpath => "/Server/Service/Engine/OneFish[@type=\'clownfish\']/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine/OneFish[@type=\'clownfish\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/insert_tree_003.cf0000644000175100017510000000504012243421446025357 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - Inserting a tree into a non-empty file, using build_xpath body attribute # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " cfe_alias "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "content" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.content)"); } bundle edit_xml test_insert(str) { insert_tree: "$(str)" build_xpath => "/Server/Service/Engine/OneFish/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/delete_text_001.cf0000644000175100017510000000364612243421446025352 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " Hot Potatoes!!! "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "text" string => "Hot Potatoes!!!"; files: "$(G.testfile).actual" create => "true", edit_xml => test_delete("$(test.text)"); } bundle edit_xml test_delete(str) { delete_text: "$(str)" select_xpath => "/Potatoes/Potato[@name=\'OnePotato\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/build_xpath_002.cf0000644000175100017510000000343512243421446025344 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - example for building an XPath in a node in a non-empty file # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " cfe_alias"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "xpath" string => "/Server/Service/Engine/Host[ Alias = cfe_alias | @name=\"cfe_host\" ]"; files: "$(G.testfile).actual" create => "true", edit_xml => test_build("$(test.xpath)"); } bundle edit_xml test_build(str) { build_xpath: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/build_xpath_003.cf0000644000175100017510000000361412243421446025344 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - example for building an XPath in a node in a non-empty file # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " cfe_alias"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "xpath" string => "/Server/Service/Engine/OneFish/TwoFish/RedFish/BlueFish/Host[ Alias = cfe_alias | @name=\"cfe_host\" ]"; files: "$(G.testfile).actual" create => "true", edit_xml => test_build("$(test.xpath)"); } bundle edit_xml test_build(str) { build_xpath: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/build_xpath_001.cf0000644000175100017510000000336712243421446025347 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - example for building an XPath in an empty file # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "expected" string => " cfe_alias"; files: "$(G.testfile).actual" create => "true", edit_defaults => init_empty; "$(G.testfile).expected" create => "true", edit_line => init_insert("$(init.expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "xpath" string => "/Server/Service/Engine/Host[ @name=\"cfe_host\" | Alias = cfe_alias ]"; files: "$(G.testfile).actual" create => "true", edit_xml => test_build("$(test.xpath)"); } bundle edit_xml test_build(str) { build_xpath: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/set_attribute_002.cf0000644000175100017510000000357412243421446025723 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "attribute_name" string => "type"; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.attribute_name)"); } bundle edit_xml test_insert(str) { set_attribute: "$(str)" build_xpath => "/Server/Service/Engine/OneFish/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine/OneFish", attribute_value => "clownfish"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/staging/0000755000175100017510000000000012243421446023575 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/staging/insert_tree_004.cf0000644000175100017510000000516212243421446027021 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - Inserting a tree into an initially empty file, using build_xpath body attribute # Note that selext_xpath must still be specified, as file will no longer be empty after build_xpath is verified. # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "expected" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_defaults => init_empty; "$(G.testfile).expected" create => "true", edit_line => init_insert("$(init.expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "content" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_xml => test_create("$(test.content)"); } bundle edit_xml test_create(str) { insert_tree: "$(str)" build_xpath => "/Server/Service/Engine/OneFish/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine"; } ####################################################### bundle agent check { methods: "any" usebundle => check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/staging/insert_tree_002.cf0000644000175100017510000000435112243421446027016 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - Inserting a tree into an empty file # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "expected" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_defaults => init_empty; "$(G.testfile).expected" create => "true", edit_line => init_insert("$(init.expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "content" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_xml => test_create("$(test.content)"); } bundle edit_xml test_create(str) { insert_tree: "$(str)"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/delete_attribute_002.cf0000644000175100017510000000356412243421446026371 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " Nemo"; "expected" string => " Nemo"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "attribute_name" string => "type"; files: "$(G.testfile).actual" create => "true", edit_xml => test_delete("$(test.attribute_name)"); } bundle edit_xml test_delete(str) { delete_attribute: "$(str)" build_xpath => "/Server/Service/Engine/OneFish/TwoFish/RedFish/BlueFish", select_xpath => "/Server/Service/Engine/OneFish"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/insert_text_001.cf0000644000175100017510000000365412243421446025413 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " Hot Potatoes!!! "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "text" string => "Hot Potatoes!!!"; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.text)"); } bundle edit_xml test_insert(str) { insert_text: "$(str)" select_xpath => "/Potatoes/Potato[@name=\'OnePotato\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/set_attribute_001.cf0000644000175100017510000000374512243421446025722 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "attribute_name" string => "topping"; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.attribute_name)"); } bundle edit_xml test_insert(str) { set_attribute: "$(str)" select_xpath => "/Potatoes/Potato[@name=\'OnePotato\']", attribute_value => "brocolli"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/insert_host_example.cf0000644000175100017510000001070412243421446026531 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml - example for inserting a host into a Tomcat configuration file # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " cfe_alias "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "host" string => " cfe_alias "; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.host)"); } bundle edit_xml test_insert(str) { insert_tree: "$(str)" select_xpath => "/Server/Service/Engine"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/11_xml_edits/set_text_001.cf0000644000175100017510000000364612243421446024703 0ustar00a10038a1003800000000000000###################################################################### # # File editing edit_xml # ###################################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " "; "expected" string => " Hot Potatoes!!! "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "text" string => "Hot Potatoes!!!"; files: "$(G.testfile).actual" create => "true", edit_xml => test_insert("$(test.text)"); } bundle edit_xml test_insert(str) { set_text: "$(str)" select_xpath => "/Potatoes/Potato[@name=\'OnePotato\']"; } ####################################################### bundle agent check { methods: "any" usebundle => xml_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/0000755000175100017510000000000012412512360022650 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/204.cf0000644000175100017510000000376112332665147023513 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_trailing works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/selectlinematching.cf0000644000175100017510000000614412412512360027031 0ustar00a10038a1003800000000000000############################################################################## # # Redmine #2778 # 3.5.x: incorrect output of: # "insert_lines promise uses the same select_line_matching anchor [...]" # # This test is loosely modelled on "execresult_multiples.cf" (post-3.5.x). # # The original Redmine 2778 report concerned editing a "sendmail.mc" file. # But in developing this acceptance test, I discovered that some existing # tests in this area also exhibit this behaviour, such as "009.cf". # # This test has two subtests: # o a copy of "009.cf"; # o the "sendmail.mc" edit from the original report. # # The subtests functionally pass but exhibit the incorrect output. # # Our intention is to fail if any of: # o incorrect output is seen (our prime concern) # o subtest itself functionally fails (its problem, not ours) # # David Lee # December 2013 # ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: any:: # Run subtests. Need to be in verbose mode to see the output. # The full verbose output is too big for variable assignment here. # So extract (grep) only potentially interesting lines. "subout_1" string => execresult("$(sys.cf_agent) -Kv -f $(this.promise_filename).sub_1 2>&1 | $(G.egrep) -i 'select_line_matching'", "useshell"); "subout_2" string => execresult("$(sys.cf_agent) -Kv -f $(this.promise_filename).sub_2 2>&1 | $(G.egrep) -i 'select_line_matching'", "useshell"); reports: DEBUG:: "bundle test: this.promise_filename: $(this.promise_filename)"; "bundle test: subtest_1: $(this.promise_filename).sub_1"; "bundle test: subout_1: $(subout_1)"; "bundle test: subtest_2: $(this.promise_filename).sub_2"; "bundle test: subout_2: $(subout_2)"; } ####################################################### bundle agent check { vars: any:: # These patterns spell trouble. "pattern_fail" string => ".*select_line_matching anchor.*"; # Examine output from 'test' to decide whether good or bad. classes: any:: "ok_pattern_1" not => regcmp("$(pattern_fail)", "$(test.subout_1)"); "ok_pattern_2" not => regcmp("$(pattern_fail)", "$(test.subout_2)"); reports: DEBUG:: "Attempted subtest '$(this.promise_filename).sub_1' in verbose mode."; "Significant output of sub_1 was '$(test.subout_1)'."; "Attempted subtest '$(this.promise_filename).sub_2' in verbose mode."; "Significant output of sub_2 was '$(test.subout_2)'."; DEBUG.!ok_pattern_1:: "failing: pattern '$(pattern_fail)' in subtest_1"; DEBUG.!ok_pattern_2:: "failing: pattern '$(pattern_fail)' in subtest_2"; ok_pattern_1.ok_pattern_2:: "$(this.promise_filename) Pass"; !(ok_pattern_1.ok_pattern_2):: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/119.cf0000644000175100017510000000364012332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_embedded", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/multi-files-dirs.cf0000644000175100017510000000420412316547775026400 0ustar00a10038a1003800000000000000####################################################### # # Insert a line into variously named files, in various directories (Issue 888) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "expected", "$(results)" }; "testdirs" slist => { "dirA/", "dirB/", "dirC/" }; "testfiles" slist => { "dirA/testfa", "dirB/testfb", "dirC/testfc" }; files: "$(G.testdir)/$(testdirs)" comment => "Create directory: $(testdirs)."; "$(G.testdir)/$(testfiles)" comment => "Create target file: $(testfiles).", create => "true"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4853" }; files: any:: "$(G.testdir)/.*/testf.*" create => "true", edit_line => myedit; } bundle edit_line myedit { insert_lines: any:: "one two three test"; } ####################################################### bundle agent check { vars: "expect" string => "one two three test"; "results" slist => { "resultA", "resultB", "resultC" }; "resultA" string => readfile( "$(G.testdir)/dirA/testfa", "33"); "resultB" string => readfile( "$(G.testdir)/dirB/testfb", "33"); "resultC" string => readfile( "$(G.testdir)/dirC/testfc", "33"); classes: "ok_A" expression => strcmp("$(expect)", "$(resultA)"); "ok_B" expression => strcmp("$(expect)", "$(resultB)"); "ok_C" expression => strcmp("$(expect)", "$(resultC)"); "ok" and => { "ok_A", "ok_B", "ok_C" }; reports: DEBUG:: "expected: '$(expect)'"; "results:"; "resultA: '$(resultA)'"; "resultB: '$(resultB)'"; "resultC: '$(resultC)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/0000755000175100017510000000000012316547775024614 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-mixed-eol.txt.mustache0000644000175100017510000000015412316547775032736 0ustar00a10038a1003800000000000000alpha Inserted line beta {{#classes.any}} Inserted block Block line 1 Block line 2 {{/classes.any}} charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-mixed-eol.txt.expected0000644000175100017510000000012112316547775032720 0ustar00a10038a1003800000000000000alpha Inserted line beta Inserted block Block line 1 Block line 2 charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-lf.txt.cftemplate0000644000175100017510000000016012316547775031764 0ustar00a10038a1003800000000000000alpha Inserted line beta [%CFEngine BEGIN %] Inserted block Block line 1 Block line 2 [%CFEngine END %] charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/.gitattributes0000644000175100017510000000001012316547775027476 0ustar00a10038a1003800000000000000* -text cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-crlf.txt.cftemplate0000644000175100017510000000017112316547775032313 0ustar00a10038a1003800000000000000alpha Inserted line beta [%CFEngine BEGIN %] Inserted block Block line 1 Block line 2 [%CFEngine END %] charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-mixed-eol.txt0000644000175100017510000000002412316547775031122 0ustar00a10038a1003800000000000000alpha beta charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/insert_file.txt0000644000175100017510000000005212316547775027655 0ustar00a10038a1003800000000000000Inserted block Block line 1 Block line 2 file-with-mixed-eol.txt.cftemplate0000644000175100017510000000016012316547775033167 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_dataalpha Inserted line beta [%CFEngine BEGIN %] Inserted block Block line 1 Block line 2 [%CFEngine END %] charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-crlf.txt0000644000175100017510000000002612316547775030167 0ustar00a10038a1003800000000000000alpha beta charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-crlf.txt.expected0000644000175100017510000000012112316547775031763 0ustar00a10038a1003800000000000000alpha Inserted line beta Inserted block Block line 1 Block line 2 charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-lf.txt.expected0000644000175100017510000000011212316547775031436 0ustar00a10038a1003800000000000000alpha Inserted line beta Inserted block Block line 1 Block line 2 charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-lf.txt0000644000175100017510000000002312316547775027637 0ustar00a10038a1003800000000000000alpha beta charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-crlf.txt.mustache0000644000175100017510000000016512316547775032003 0ustar00a10038a1003800000000000000alpha Inserted line beta {{#classes.any}} Inserted block Block line 1 Block line 2 {{/classes.any}} charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf_data/file-with-lf.txt.mustache0000644000175100017510000000015412316547775031454 0ustar00a10038a1003800000000000000alpha Inserted line beta {{#classes.any}} Inserted block Block line 1 Block line 2 {{/classes.any}} charlie cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/nothing_to_repeat_error.cf.sub0000644000175100017510000000125312352022221030667 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { build_linux_limits_conf }; } bundle agent build_linux_limits_conf { vars: "limits[glob-dash-nofile]" string => "* - nofile 30000", policy => "free"; "limits[app-soft-nproc]" string => "app soft nproc 16357", policy => "free"; "values" slist => getvalues("limits"); files: "$(G.testfile)" create => "true", edit_line => insert("@(build_linux_limits_conf.values)"), edit_defaults => empty; } bundle edit_line insert(str) { insert_lines: "$(str)"; } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf-in-cftemplate.cf0000644000175100017510000000456212316547775026672 0ustar00a10038a1003800000000000000############################################################################## # Test that CRLF is handled correctly on Windows. ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { meta: "test_skip_unsupported" string => "!windows"; vars: "datadir" string => "$(this.promise_dirname)/crlf_data"; "filelist" slist => { "file-with-lf.txt", "file-with-crlf.txt", "file-with-mixed-eol.txt" }; files: "$(G.testdir)/." create => "yes"; "$(G.testdir)/$(filelist)" copy_from => copy_file("$(filelist)"); } body copy_from copy_file(file) { source => "$(datadir)/$(file)"; } ####################################################### bundle agent test { files: "$(G.testdir)/$(init.filelist)" edit_template => "$(init.datadir)/$(init.filelist).cftemplate", template_method => "cfengine"; } ####################################################### bundle agent check { vars: "ok_classes" slist => { "diff_ok_file_with_lf_txt", "diff_ok_file_with_crlf_txt", "diff_ok_file_with_mixed_eol_txt", "size_ok_file_with_lf_txt", "size_ok_file_with_crlf_txt", "size_ok_file_with_mixed_eol_txt" }; "classes_set" slist => classesmatching("(diff|size)_ok.*"); classes: "diff_ok_$(init.filelist)" expression => returnszero( "$(G.diff) $(G.testdir)/$(init.filelist) $(init.datadir)/$(init.filelist).expected >$(G.dev_null) 2>&1", "useshell"); "size_ok_$(init.filelist)" expression => strcmp(filestat("$(G.testdir)/$(init.filelist)", "size"), filestat("$(init.datadir)/$(init.filelist).expected", "size")); "ok" and => { @(ok_classes) }; reports: DEBUG.!ok:: "Classes expected: $(ok_classes)"; "Classes actually set: $(classes_set)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/namespaced_edit_line_bundle.cf0000644000175100017510000000241412332665147030645 0ustar00a10038a1003800000000000000####################################################### # # Call an edit_line bundle from another namespace # ####################################################### body common control { inputs => { "../../default.cf.sub", "namespaced_edit_line_bundle.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert, edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "Hello"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_defaults => init_empty, edit_line => testing_namespace:simple_insert; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/205.cf0000644000175100017510000000367012332665147023513 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/105.cf0000644000175100017510000000361112332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/117.cf0000644000175100017510000000361512332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/017.cf0000644000175100017510000000201512400110676023470 0ustar00a10038a1003800000000000000####################################################### # # Try to insert lines from a file that is really a directory. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "aix", meta => { "redmine6336" }; files: "$(G.testfile)" edit_line => insert_dir, create => "true"; } bundle edit_line insert_dir { insert_lines: "$(G.testroot)" insert_type => "file", classes => if_notkept("ok"); } ####################################################### bundle agent check { reports: DEBUG:: "This should only pass if inserting lines from a directory fails"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/insertion-order-reversal.cf0000644000175100017510000000342312332665147030145 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines, insuring they are not printed in reverse order (Issue 809) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Three potatos Four END"; "insert" string => "BEGIN Five potato Six potato Seven potatoe More! END"; "expected" string => "BEGIN Five potato Six potato Seven potatoe More! END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(str) { delete_lines: ".*"; insert_lines: "$(str)" insert_type => "preserve_block", location => start; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/112.cf0000644000175100017510000000365712332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_trailing works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/007.cf0000644000175100017510000000414512332665147023511 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines at the end of a fully bounded # region, before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " big potatoes BEGIN One potato Two potato Two potatos Four END small potatoes"; "expected" string => " big potatoes BEGIN One potato Two potato Three potatoe Two potatos Four END small potatoes"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" select_region => test_region, location => test_before_last(".*potato.*"); } body select_region test_region { select_start => "BEGIN"; select_end => "END"; } body location test_before_last(line) { before_after => "before"; first_last => "last"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/015.cf0000644000175100017510000000362012332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "insert" string => " One potato Two potato Three potatoe Spuds spuds spuds Four"; "expected" string => "BEGIN One potato Two potato Two potatos Four END Three potatoe Spuds spuds spuds"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", insert_select => test_insert_exclude("Three"); } body insert_select test_insert_exclude(r) { insert_if_not_match_from_list => { "$(r)" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/107.cf0000644000175100017510000000361212332665147023510 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_trailing", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/011.cf0000644000175100017510000000354312332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "expected" string => "BEGIN One potato Two potato Three potatoe Two potatos Four END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" location => test_before_last(".*potato.*"); } body location test_before_last(line) { before_after => "before"; first_last => "last"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/206.cf0000644000175100017510000000367012332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/217.cf0000644000175100017510000000373212332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/114.cf0000644000175100017510000000371012332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_embedded works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/215.cf0000644000175100017510000000366512332665147023520 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy ignore_trailing # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/103.cf0000644000175100017510000000366012332665147023507 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_trailing works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/004.cf0000644000175100017510000000415112332665147023503 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines at the end of a fully bounded # region, before the first instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " big potatoes BEGIN One potato Two potato Two potatos Four END small potatoes"; "expected" string => " big potatoes BEGIN Three potatoe One potato Two potato Two potatos Four END small potatoes"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" select_region => test_region, location => test_before_first(".*potato.*"); } body select_region test_region { select_start => "BEGIN"; select_end => "END"; } body location test_before_first(line) { before_after => "before"; first_last => "first"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/203.cf0000644000175100017510000000373712332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_trailing works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/222.cf0000644000175100017510000000374412332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_embedded works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/edit_line_bundle_called_from_namespace.cf0000644000175100017510000000244012332665147033027 0ustar00a10038a1003800000000000000####################################################### # # Call an edit_line bundle from another namespace # ####################################################### body common control { inputs => { "../../default.cf.sub", "edit_line_bundle_called_from_namespace.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert, edit_defaults => init_empty; } bundle edit_line init_insert { insert_lines: "Hello"; } bundle edit_line simple_insert(line) { insert_lines: "$(line)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { methods: "jump" usebundle => testing_namespace:namespaced_test("$(G.testfile).actual"); } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/block_insert_order.cf0000644000175100017510000000263112332665147027052 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy ignore_trailing # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_insert, edit_defaults => init_empty; } bundle edit_line init_insert { insert_lines: "line1 line2"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => test_insert; } bundle edit_line test_insert { delete_lines: ".*"; insert_lines: "line1 line2" insert_type => "preserve_block", location => start; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 edit_line_bundle_called_from_namespace.cf.sub0000644000175100017510000000054012332665147033537 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/09_insert_linesbody file control { namespace => "testing_namespace"; } bundle agent namespaced_test(file) { files: "$(file)" create => "true", edit_defaults => default:init_empty, classes => default:scoped_classes_generic("bundle", "edit"), edit_line => default:simple_insert("Hello"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/102.cf0000644000175100017510000000361012332665147023501 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that exact match works when given a # not-exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/nothing_to_repeat_error.cf0000644000175100017510000000135512352022221030102 0ustar00a10038a1003800000000000000####################################################### # # catch "nothing to repeat" error in file editing # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent check { methods: "" usebundle => dcs_passif_output("", ".*nothing to repeat.*", "$(sys.cf_agent) -KI -f $(this.promise_filename).sub | $(G.grep) nofile", $(this.promise_filename)); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/016.cf0000644000175100017510000000360212332665147023506 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "insert" string => " One potato Two potato Three potatoe Spuds spuds spuds Four"; "expected" string => "BEGIN One potato Two potato Two potatos Four END Spuds spuds spuds"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", insert_select => test_insert_exclude(".*Three.*"); } body insert_select test_insert_exclude(r) { insert_if_not_match_from_list => { "$(r)" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/216.cf0000644000175100017510000000366412332665147023520 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy ignore_leading # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf-in-edit_line.cf0000644000175100017510000000523412316547775026477 0ustar00a10038a1003800000000000000############################################################################## # Test that CRLF is handled correctly on Windows. ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { meta: "test_skip_unsupported" string => "!windows"; vars: "datadir" string => "$(this.promise_dirname)/crlf_data"; "filelist" slist => { "file-with-lf.txt", "file-with-crlf.txt", "file-with-mixed-eol.txt" }; files: "$(G.testdir)/." create => "yes"; "$(G.testdir)/$(filelist)" copy_from => copy_file("$(filelist)"); } body copy_from copy_file(file) { source => "$(datadir)/$(file)"; } ####################################################### bundle agent test { files: "$(G.testdir)/$(init.filelist)" edit_line => insert_line; } bundle edit_line insert_line { insert_lines: "Inserted line" select_region => second_line; "Inserted block Block line 1 Block line 2" select_region => third_line; } body select_region second_line { select_start => "alpha"; select_end => "beta"; } body select_region third_line { select_start => "beta"; select_end => "charlie"; } ####################################################### bundle agent check { vars: "ok_classes" slist => { "diff_ok_file_with_lf_txt", "diff_ok_file_with_crlf_txt", "diff_ok_file_with_mixed_eol_txt", "size_ok_file_with_lf_txt", "size_ok_file_with_crlf_txt", "size_ok_file_with_mixed_eol_txt" }; "classes_set" slist => classesmatching("(diff|size)_ok.*"); classes: "diff_ok_$(init.filelist)" expression => returnszero( "$(G.diff) $(G.testdir)/$(init.filelist) $(init.datadir)/$(init.filelist).expected >$(G.dev_null) 2>&1", "useshell"); "size_ok_$(init.filelist)" expression => strcmp(filestat("$(G.testdir)/$(init.filelist)", "size"), filestat("$(init.datadir)/$(init.filelist).expected", "size")); "ok" and => { @(ok_classes) }; reports: DEBUG.!ok:: "Classes expected: $(ok_classes)"; "Classes actually set: $(classes_set)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/008.cf0000644000175100017510000000354712332665147023517 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the first instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "expected" string => "BEGIN Three potatoe One potato Two potato Two potatos Four END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" location => test_before_first(".*potato.*"); } body location test_before_first(line) { before_after => "before"; first_last => "first"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/104.cf0000644000175100017510000000370212332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_trailing works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ###################################################### # bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/selectlinematching.cf.sub_20000644000175100017510000000362012332665147030053 0ustar00a10038a1003800000000000000####################################################### # # Redmine 2778: # # A reduced form of the generating case. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "dnl # dnl define(`SMART_HOST', `smtp.your.provider')dnl dnl #"; "expected" string => "dnl # dnl define(`SMART_HOST', `smtp.your.provider')dnl define(`SMART_HOST', `mail1.$m')dnl define(`MAIL_HUB', `mail1.$m')dnl dnl #"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "hostname" string => "mail1.$m"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(hostname)"); } bundle edit_line test_insert(h) { insert_lines: # These sendmail "define" lines comprise a cfengine multi-line string. "define(`SMART_HOST', `$(h)')dnl define(`MAIL_HUB', `$(h)')dnl" location => location_sendmail_mc; } body location location_sendmail_mc { select_line_matching => "^dnl.*SMART_HOST.*"; before_after => "after"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/109.cf0000644000175100017510000000416312332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines with preserve_block "after" and check convergence # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "START"; "expected" string => "START 1 x2x xx3xx x4x 5 x6x xx7xx xxx8xxx xxxx9xxxx xxxxx10xxxx xxxxxx11xxxxx xxxxxxx12xxxxxx xxxxxxxx13xxxxxxx xxxxxxxxx14xxxxxxxx xxxxxxxxx15xxxxxxxxx xxx16xx xxx17xx xxx18xx xxx19xx xxx20xx xxxxxxxxx21xxxxxxx"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: " 1 x2x xx3xx x4x 5 x6x xx7xx xxx8xxx xxxx9xxxx xxxxx10xxxx xxxxxx11xxxxx xxxxxxx12xxxxxx xxxxxxxx13xxxxxxx xxxxxxxxx14xxxxxxxx xxxxxxxxx15xxxxxxxxx xxx16xx xxx17xx xxx18xx xxx19xx xxx20xx xxxxxxxxx21xxxxxxx" location => prepend, insert_type => "preserve_block"; } body location prepend { before_after => "after"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/207.cf0000644000175100017510000000367112332665147023516 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_trailing", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/303.cf0000644000175100017510000000454212332665147023511 0ustar00a10038a1003800000000000000######################################################## # # ISSUE 1023 # ######################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ######################################################## bundle agent init { vars: "actual1qaz" string => ""; "actual2qaz" string => ""; "actual3qaz" string => ""; "expected1qaz" string => "AAAA"; "expected2qaz" string => "AAAA"; "expected3qaz" string => "AAAA"; "files" slist => { "actual1qaz", "expected1qaz", "actual2qaz", "expected2qaz", "actual3qaz", "expected3qaz" }; files: "$(G.testfile).actual1qaz" touch => "true"; "$(G.testfile).actual2qaz" touch => "true"; "$(G.testfile).actual3qaz" touch => "true"; "$(G.testfile).expected1qaz" touch => "true", edit_line => init_insert("$(expected1qaz)"); "$(G.testfile).expected2qaz" touch => "true", edit_line => init_insert("$(expected1qaz)"); "$(G.testfile).expected3qaz" touch => "true", edit_line => init_insert("$(expected1qaz)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine5120" }; files: "$(G.testfile).(actual)?\dq.*" pathtype => "regex", edit_line => example_edit_line; } bundle edit_line example_edit_line { insert_lines: "AAAA"; } bundle agent check { methods: "first" usebundle => dcs_check_diff("$(G.testfile).actual1qaz", "$(G.testfile).expected1qaz", "$(this.promise_filename)"); "second" usebundle => dcs_check_diff("$(G.testfile).actual2qaz", "$(G.testfile).expected2qaz", "$(this.promise_filename)"); "third" usebundle => dcs_check_diff("$(G.testfile).actual3qaz", "$(G.testfile).expected3qaz", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/116.cf0000644000175100017510000000360512332665147023512 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy ignore_leading # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/201.cf0000644000175100017510000000362212332665147023504 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that exact match works when given an # exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/213.cf0000644000175100017510000000374512332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_embedded works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/302.cf0000644000175100017510000000325112332665147023504 0ustar00a10038a1003800000000000000####################################################### # # Test non matching end selector in region matches # EOF # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "actual" string => "[quux] bar "; "expected" string => "[quux] bar foo "; "files" slist => { "actual", "expected" }; files: "$(G.testfile).$(files)" create => "true", edit_line => init_insert("$(init.$(files))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => example_edit_line; } bundle edit_line example_edit_line { insert_lines: "foo" select_region => example_select, location => example_location; } body select_region example_select { select_start => "\[quux\]"; select_end => "\[.*\]"; } body location example_location { select_line_matching => "bar"; before_after => "after"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf-in-mustache.cf0000644000175100017510000000456012316547775026355 0ustar00a10038a1003800000000000000############################################################################## # Test that CRLF is handled correctly on Windows. ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { meta: "test_skip_unsupported" string => "!windows"; vars: "datadir" string => "$(this.promise_dirname)/crlf_data"; "filelist" slist => { "file-with-lf.txt", "file-with-crlf.txt", "file-with-mixed-eol.txt" }; files: "$(G.testdir)/." create => "yes"; "$(G.testdir)/$(filelist)" copy_from => copy_file("$(filelist)"); } body copy_from copy_file(file) { source => "$(datadir)/$(file)"; } ####################################################### bundle agent test { files: "$(G.testdir)/$(init.filelist)" edit_template => "$(init.datadir)/$(init.filelist).mustache", template_method => "mustache"; } ####################################################### bundle agent check { vars: "ok_classes" slist => { "diff_ok_file_with_lf_txt", "diff_ok_file_with_crlf_txt", "diff_ok_file_with_mixed_eol_txt", "size_ok_file_with_lf_txt", "size_ok_file_with_crlf_txt", "size_ok_file_with_mixed_eol_txt" }; "classes_set" slist => classesmatching("(diff|size)_ok.*"); classes: "diff_ok_$(init.filelist)" expression => returnszero( "$(G.diff) $(G.testdir)/$(init.filelist) $(init.datadir)/$(init.filelist).expected >$(G.dev_null) 2>&1", "useshell"); "size_ok_$(init.filelist)" expression => strcmp(filestat("$(G.testdir)/$(init.filelist)", "size"), filestat("$(init.datadir)/$(init.filelist).expected", "size")); "ok" and => { @(ok_classes) }; reports: DEBUG.!ok:: "Classes expected: $(ok_classes)"; "Classes actually set: $(classes_set)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/013.cf0000644000175100017510000000335712332665147023512 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "insert" string => " One potato Two potato Three potatoe Spuds spuds spuds Four"; "expected" string => "BEGIN One potato Two potato Two potatos Four END Three potatoe Spuds spuds spuds"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" insert_type => "file"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/014.cf0000644000175100017510000000360612332665147023510 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "insert" string => " One potato Two potato Three potatoe Spuds spuds spuds Four"; "expected" string => "BEGIN One potato Two potato Two potatos Four END Three potatoe Spuds spuds spuds"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" insert_type => "file", insert_select => test_insert_exclude("Xhree"); } body insert_select test_insert_exclude(r) { insert_if_not_match_from_list => { "$(r)" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/block_insert_duplicate.cf0000644000175100017510000000340512400110676027675 0ustar00a10038a1003800000000000000####################################################### # # Insert lines at the top of file a multi-line header, # verify that insertion is convergent - Redmine #1525 # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "header" string => "############### ### This file is managed by CFEngine ### Do not update it manually, oh no ### do not ###############"; files: "$(G.testfile).expected" create => "true", edit_line => insert_header; commands: !windows:: "$(G.echo)" args => "\"${init.header}\" > \"$(G.testfile).actual\"", contain => in_shell; windows:: # newlines in shell are not handled properly on Windows... "$(G.printf)" args => '"###############\n### This file is managed by CFEngine\n### Do not update it manually, oh no\n### do not\n###############\n" > "$(G.testfile).actual"', contain => in_shell; } ####################################################### bundle agent test { files: "$(G.testfile).actual" create => "true", edit_line => insert_header; } bundle edit_line insert_header { insert_lines: "${init.header}" location => start, insert_type => "preserve_block"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/212.cf0000644000175100017510000000373612332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_trailing works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/003.cf0000644000175100017510000000335712332665147023511 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines at the end of a partially bounded region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Four END"; "expected" string => "BEGIN One potato Two potato Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" select_region => test_region; } body select_region test_region { select_start => "BEGIN"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/300.cf0000644000175100017510000000737512332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Test insertion of newlines (Issue 555) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "template", "expected" }; "template" string => "## # Sendmail Alias File # @(#)B11.23_LRaliases $Revision: 1.1.212.1 $ $Date: 99/09/13 15:13:16 $ # # Mail to an alias in this file will be sent to the users, programs, or # files designated following the colon. # Aliases defined in this file will NOT be expanded in headers from # mailx(1), but WILL be visible over networks and in headers from # rmail(1). # # >>>>>>>>>> The program \"/usr/sbin/newaliases\" must be run after # >> NOTE >> this file is updated, or else any changes will not be # >>>>>>>>>> visible to sendmail. ## # Alias for mailer daemon MAILER-DAEMON : root # RFC 822 requires that every host have a mail address \"postmaster\" postmaster : root # Aliases to handle mail to msgs and news nobody : /dev/null # System Admistration aliases operator : root uucp : root daemon : root # Ftp maintainer. ftp-bugs : root # Local aliases root : dcpds.sysadmin@dcpds.cpms.osd.mil,:include:/etc/mail/aliases.root oracle : dcpds.dba@dcpds.cpms.osd.mil exinfac : dcpds.exits@dcpds.cpms.osd.mil applmgr : dcpds.dba@dcpds.cpms.osd.mil"; "expected" string => "## # Sendmail Alias File # @(#)B11.23_LRaliases $Revision: 1.1.212.1 $ $Date: 99/09/13 15:13:16 $ # # Mail to an alias in this file will be sent to the users, programs, or # files designated following the colon. # Aliases defined in this file will NOT be expanded in headers from # mailx(1), but WILL be visible over networks and in headers from # rmail(1). # # >>>>>>>>>> The program \"/usr/sbin/newaliases\" must be run after # >> NOTE >> this file is updated, or else any changes will not be # >>>>>>>>>> visible to sendmail. ## # Alias for mailer daemon MAILER-DAEMON : root # RFC 822 requires that every host have a mail address \"postmaster\" postmaster : root # Aliases to handle mail to msgs and news nobody : /dev/null # System Admistration aliases operator : root uucp : root daemon : root # Ftp maintainer. ftp-bugs : root # Local aliases root : dcpds.sysadmin@dcpds.cpms.osd.mil,:include:/etc/mail/aliases.root oracle : dcpds.dba@dcpds.cpms.osd.mil exinfac : dcpds.exits@dcpds.cpms.osd.mil applmgr : dcpds.dba@dcpds.cpms.osd.mil stgmgmt : :include:/etc/mail/aliases.stgmgmt"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "MailAliases" slist => { "stgmgmt : :include:/etc/mail/aliases.stgmgmt" }; files: "$(G.testfile).actual" edit_line => copy_and_append_lines("$(G.testfile).template", "@(this.MailAliases)"), edit_defaults => empty, create => "true"; } bundle edit_line copy_and_append_lines(file,lines) { insert_lines: "$(file)" insert_type => "file"; "$(lines)" insert_type => "string"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/selectlinematching.cf.sub_10000644000175100017510000000373212332665147030056 0ustar00a10038a1003800000000000000####################################################### # # Redmine #2778 # This subtest should be identical to "009.cf" with the exception of # these comment lines. # ####################################################### # # Insert a number of lines after the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "expected" string => "BEGIN One potato Two potato Two potatos Three potatoe Four END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" location => test_after_last(".*potato.*"); } body location test_after_last(line) { before_after => "after"; first_last => "last"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/005.cf0000644000175100017510000000414112332665147023503 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines at the end of a fully bounded # region, after the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " big potatoes BEGIN One potato Two potato Two potatos Four END small potatoes"; "expected" string => " big potatoes BEGIN One potato Two potato Two potatos Three potatoe Four END small potatoes"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" select_region => test_region, location => test_after_last(".*potato.*"); } body select_region test_region { select_start => "BEGIN"; select_end => "END"; } body location test_after_last(line) { before_after => "after"; first_last => "last"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/006.cf0000644000175100017510000000414512332665147023510 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines at the end of a fully bounded # region, after the first instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => " big potatoes BEGIN One potato Two potato Two potatos Four END small potatoes"; "expected" string => " big potatoes BEGIN One potato Three potatoe Two potato Two potatos Four END small potatoes"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" select_region => test_region, location => test_after_first(".*potato.*"); } body select_region test_region { select_start => "BEGIN"; select_end => "END"; } body location test_after_first(line) { before_after => "after"; first_last => "first"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/009.cf0000644000175100017510000000353712332665147023517 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines after the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "expected" string => "BEGIN One potato Two potato Two potatos Three potatoe Four END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" location => test_after_last(".*potato.*"); } body location test_after_last(line) { before_after => "after"; first_last => "last"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/namespaced_edit_line_bundle.cf.sub0000644000175100017510000000025212316547775031443 0ustar00a10038a1003800000000000000body file control { namespace => "testing_namespace"; } bundle edit_line simple_insert { insert_lines: "Hello"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/002.cf0000644000175100017510000000340612332665147023503 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines at the end of a fully bounded region # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Four END"; "expected" string => "BEGIN One potato Two potato Four Three potatoe END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" select_region => test_region; } body select_region test_region { select_start => "BEGIN"; select_end => "END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/staging/0000755000175100017510000000000012332665147024321 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/staging/220.x.cf0000644000175100017510000000360712332665147025412 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "exact_match", "ignore_embedded", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/staging/120.x.cf0000644000175100017510000000355212332665147025410 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "exact_match", "ignore_embedded", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/staging/304.cf.namespaced.sub0000644000175100017510000000050312236160673030023 0ustar00a10038a1003800000000000000body file control { namespace => "cfdc_yumclient"; } bundle agent config(file, i) { vars: "data[var$(i)]" string => "value$(i)"; files: "$(file)" handle => "ensure_present", edit_defaults => default:init_empty, edit_line => default:set_variable_values("cfdc_yumclient:config.data"); } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/staging/304.cf0000644000175100017510000000233312332665147025142 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub", "../../../../masterfiles/libraries/cfengine_stdlib.cf", "304.cf.namespaced.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ######################################################## bundle agent init { vars: "expected" slist => { "var1=value1" }; "files" slist => { "actual", "expected" }; files: "$(G.testfile).actual" touch => "true"; "$(G.testfile).expected" touch => "true", edit_defaults => init_empty, edit_line => init_insert("$(expected)"); } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } bundle agent test { methods: "call" usebundle => cfdc_yumclient:config("$(G.testfile).actual", "2"); "call" usebundle => cfdc_yumclient:config("$(G.testfile).actual", "1"); } bundle agent check { methods: "first" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/218.cf0000644000175100017510000000375012332665147023516 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/208.cf0000644000175100017510000000364412332665147023517 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading", "ignore_trailing", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/122.cf0000644000175100017510000000366512332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_embedded works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/202.cf0000644000175100017510000000366712332665147023516 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that exact match works when given a # not-exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/115.cf0000644000175100017510000000365312332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy ignore_trailing # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/021.cf0000644000175100017510000000310712332665147023502 0ustar00a10038a1003800000000000000####################################################### # # Test idempotency of preserve_block # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_expected, edit_defaults => init_empty; files: "$(G.testfile).actual" create => "true", edit_line => init_file, edit_defaults => init_empty; } ####### bundle edit_line init_file { insert_lines: "auto eth0.1190 iface eth0.1190 inet manual up ifconfig eth0.1190 up" insert_type => "preserve_block"; } ####### bundle edit_line init_expected { insert_lines: "auto eth0.1190 iface eth0.1190 inet manual up ifconfig eth0.1190 up" insert_type => "preserve_block"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: # Do the same again to test idempotency of preserve_block "$(G.testfile).actual" edit_line => init_expected; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).expected", "$(G.testfile).actual", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/001.cf0000644000175100017510000000317412332665147023504 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Four END"; "expected" string => "BEGIN One potato Two potato Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "BEGIN$(const.n)$(str)$(const.n)END"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/113.cf0000644000175100017510000000366612332665147023516 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_embedded works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/019.cf0000644000175100017510000000371412332665147023515 0ustar00a10038a1003800000000000000####################################################### # # Files read in as templates, check class handling # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_expected, edit_defaults => init_empty; files: "$(G.testfile).template" create => "true", edit_line => init_template, edit_defaults => init_empty; } ####### bundle edit_line init_template { insert_lines: "[%CFEngine BEGIN %] WARNING No unauthorized logins. All logins are recorded. Property of Example.com [%CFEngine END %] [%CFEngine nosuchclass:: %] manager: Mr. White phone: 555-555-5555 [%CFEngine fishy:: %] manager: Mr. Black phone: 555-555-4444 [%CFEngine any:: %] AAAAAAAA " insert_type => "preserve_all_lines"; } ####### bundle edit_line init_expected { insert_lines: "WARNING No unauthorized logins. All logins are recorded. Property of Example.com manager: Mr. Black phone: 555-555-4444 AAAAAAAA " insert_type => "preserve_block"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { classes: "fishy" expression => "any"; files: "$(G.testfile).actual" create => "true", edit_template => "$(G.testfile).template"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).expected", "$(G.testfile).actual", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/crlf-in-edit_line-insert-file.cf0000644000175100017510000000526212316547775030717 0ustar00a10038a1003800000000000000############################################################################## # Test that CRLF is handled correctly on Windows. ############################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { meta: "test_skip_unsupported" string => "!windows"; vars: "datadir" string => "$(this.promise_dirname)/crlf_data"; "filelist" slist => { "file-with-lf.txt", "file-with-crlf.txt", "file-with-mixed-eol.txt" }; files: "$(G.testdir)/." create => "yes"; "$(G.testdir)/$(filelist)" copy_from => copy_file("$(filelist)"); } body copy_from copy_file(file) { source => "$(datadir)/$(file)"; } ####################################################### bundle agent test { files: "$(G.testdir)/$(init.filelist)" edit_line => insert_line; } bundle edit_line insert_line { insert_lines: "Inserted line" select_region => second_line; "$(init.datadir)/insert_file.txt" insert_type => "file", select_region => third_line; } body select_region second_line { select_start => "alpha"; select_end => "beta"; } body select_region third_line { select_start => "beta"; select_end => "charlie"; } ####################################################### bundle agent check { vars: "ok_classes" slist => { "diff_ok_file_with_lf_txt", "diff_ok_file_with_crlf_txt", "diff_ok_file_with_mixed_eol_txt", "size_ok_file_with_lf_txt", "size_ok_file_with_crlf_txt", "size_ok_file_with_mixed_eol_txt" }; "classes_set" slist => classesmatching("(diff|size)_ok.*"); classes: "diff_ok_$(init.filelist)" expression => returnszero( "$(G.diff) $(G.testdir)/$(init.filelist) $(init.datadir)/$(init.filelist).expected >$(G.dev_null) 2>&1", "useshell"); "size_ok_$(init.filelist)" expression => strcmp(filestat("$(G.testdir)/$(init.filelist)", "size"), filestat("$(init.datadir)/$(init.filelist).expected", "size")); "ok" and => { @(ok_classes) }; reports: DEBUG.!ok:: "Classes expected: $(ok_classes)"; "Classes actually set: $(classes_set)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/121.cf0000644000175100017510000000360512332665147023506 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy ignore_embedded # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/118.cf0000644000175100017510000000367112332665147023517 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/108.cf0000644000175100017510000000356512332665147023520 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading", "ignore_trailing", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/214.cf0000644000175100017510000000376712332665147023522 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_embedded works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_leading", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/221.cf0000644000175100017510000000366412332665147023514 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy ignore_embedded # works when given a close-enough exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/010.cf0000644000175100017510000000354312332665147023504 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines after the first instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "expected" string => "BEGIN One potato Three potatoe Two potato Two potatos Four END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "tstr" string => " One potato Two potato Three potatoe Four"; files: "$(G.testfile).actual" create => "true", edit_line => test_insert("$(test.tstr)"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" location => test_after_first(".*potato.*"); } body location test_after_first(line) { before_after => "after"; first_last => "first"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/106.cf0000644000175100017510000000361112332665147023506 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that pairs of whitespace_policy work # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "ignore_leading", "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/301.cf0000644000175100017510000000261112332665147023502 0ustar00a10038a1003800000000000000####################################################### # # Test that specifying whitespace_policy escapes meta-characters (Issue 644) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "expected" string => "*foobar*"; files: "$(G.testfile).expected" create => "true", edit_line => init_insert("$(init.expected)"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => set_value_rev, create => "true"; } bundle edit_line set_value_rev { insert_lines: "*foobar*" whitespace_policy => { "ignore_embedded" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/219.cf0000644000175100017510000000410612332665147023513 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a file, verify that whitespace_policy other than # ignore_leading works when given a not-close-enough match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe Leading embedded and trailing spaces "; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(filename) { insert_lines: "$(filename)" insert_type => "file", whitespace_policy => { "ignore_embedded", "ignore_trailing" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff_expected("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)", "yes"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/012.cf0000644000175100017510000000366012332665147023506 0ustar00a10038a1003800000000000000####################################################### # # Insert a number of lines before the last instance of a line # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected", "insert" }; "actual" string => "BEGIN One potato Two potato Two potatos Four END"; "insert" string => " One potato Two potato Three potatoe Spuds spuds spuds Four"; "expected" string => "BEGIN One potato Two potato Three potatoe Spuds spuds spuds Two potatos Four END"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(G.testfile).insert"); } bundle edit_line test_insert(str) { insert_lines: "$(str)" insert_type => "file", location => test_before_last(".*potato.*"); } body location test_before_last(line) { before_after => "before"; first_last => "last"; select_line_matching => "$(line)"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/020.cf0000644000175100017510000000356112332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Files read in as templates, check variable expansion # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile).expected" create => "true", edit_line => init_expected, edit_defaults => init_empty; files: "$(G.testfile).template" create => "true", edit_line => init_template, edit_defaults => init_empty; } ####### bundle edit_line init_template { insert_lines: "BEGIN $(const.dollar)(test.scalar) CCCCCCCC CCCCCCCC CCCCCCCC DDDDDDDD [%CFEngine BEGIN %] $(const.dollar)(test.list) [%CFEngine END %] " insert_type => "preserve_all_lines"; } ####### bundle edit_line init_expected { insert_lines: "BEGIN One upon a time... CCCCCCCC CCCCCCCC CCCCCCCC DDDDDDDD Many times Upon a star " insert_type => "preserve_all_lines"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { vars: "scalar" string => "One upon a time..."; "list" slist => { "Many times", "Upon a star" }; classes: "fishy" expression => "any"; files: "$(G.testfile).actual" create => "true", edit_template => "$(G.testfile).template"; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).expected", "$(G.testfile).actual", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/09_insert_lines/101.cf0000644000175100017510000000354312332665147023505 0ustar00a10038a1003800000000000000####################################################### # # Insert lines from a variable, verify that exact match works when given an # exact match # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "states" slist => { "actual", "expected" }; "actual" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END"; "insert" string => " One potato Two potato Three potatoe Leading embedded and trailing spaces Four"; "expected" string => "BEGIN One potato Two potato Two potatos Leading embedded and trailing spaces Four END Three potatoe"; files: "$(G.testfile).$(states)" create => "true", edit_line => init_insert("$(init.$(states))"), edit_defaults => init_empty; } bundle edit_line init_insert(str) { insert_lines: "$(str)"; } body edit_defaults init_empty { empty_file_before_editing => "true"; } ####################################################### bundle agent test { files: "$(G.testfile).actual" edit_line => test_insert("$(init.insert)"); } bundle edit_line test_insert(lines) { insert_lines: "$(lines)" whitespace_policy => { "exact_match" }; } ####################################################### bundle agent check { methods: "any" usebundle => dcs_check_diff("$(G.testfile).actual", "$(G.testfile).expected", "$(this.promise_filename)"); } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/10_links/0000755000175100017510000000000012352022221021255 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/10_links/002-namespaced_links.cf.sub0000644000175100017510000000033412236160673026175 0ustar00a10038a1003800000000000000body file control { namespace => "testing_links"; } bundle agent namespaced_test { files: "$(G.testdir)/subdir/mylink" link_from => default:ln_s("$(G.testdir)/sourcefile"), action => default:warn_only; } cfengine-3.6.2/tests/acceptance/10_files/10_links/edit_linked_file.cf0000644000175100017510000000316412316547775025077 0ustar00a10038a1003800000000000000# Test that editing a symlink does not mangle it body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testdir)/file_dir/file" create => "true", edit_line => edit_init; "$(G.testdir)/link_dir/." create => "true"; "$(G.testdir)/link_dir/link" link_from => link_init; } bundle edit_line edit_init { insert_lines: "Initial line"; } body link_from link_init { link_type => "symlink"; source => "../file_dir/file"; } bundle agent test { meta: "test_skip_unsupported" string => "windows"; files: "$(G.testdir)/link_dir/link" edit_line => edit_test; } bundle edit_line edit_test { insert_lines: "Added line"; } bundle agent check { classes: "link_ok" expression => islink("$(G.testdir)/link_dir/link"); "file_ok" not => islink("$(G.testdir)/file_dir/file"); "link_line_one_ok" expression => regline("Initial line", "$(G.testdir)/link_dir/link"); "file_line_one_ok" expression => regline("Initial line", "$(G.testdir)/file_dir/file"); "link_line_two_ok" expression => regline("Added line", "$(G.testdir)/link_dir/link"); "file_line_two_ok" expression => regline("Added line", "$(G.testdir)/file_dir/file"); "ok" and => { "link_ok", "file_ok", "link_line_one_ok", "file_line_one_ok", "link_line_two_ok", "file_line_two_ok" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/10_links/002.cf0000644000175100017510000000210412352022221022065 0ustar00a10038a1003800000000000000####################################################### # # Check that action and link_from bodies are accessible from outside # the current namespace. # ####################################################### body common control { inputs => { "../../default.cf.sub", "002-namespaced_links.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: } ####################################################### bundle agent test { methods: "run" usebundle => testing_links:namespaced_test(); } body link_from ln_s(x) { link_type => "symlink"; source => "$(x)"; when_no_source => "force"; } ####################################################### bundle agent check { classes: "subdir_created" expression => fileexists("$(G.testdir)/subdir"); reports: !subdir_created:: "$(this.promise_filename) Pass"; subdir_created:: "$(this.promise_filename) Fail"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/10_links/001.cf0000644000175100017510000000222312352022221022066 0ustar00a10038a1003800000000000000####################################################### # # Subdirectories shall not be created when action is # warn. Related to bug #926. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: } ####################################################### bundle agent test { files: "$(G.testdir)/subdir/mylink" link_from => ln_s("$(G.testdir)/sourcefile"), action => test_warn_only; } body action test_warn_only { action_policy => "warn"; } body link_from ln_s(x) { link_type => "symlink"; source => "$(x)"; when_no_source => "force"; } ####################################################### bundle agent check { classes: "subdir_created" expression => fileexists("$(G.testdir)/subdir"); reports: !subdir_created:: "$(this.promise_filename) Pass"; subdir_created:: "$(this.promise_filename) Fail"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/13_file_dir/0000755000175100017510000000000012412221023021713 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/13_file_dir/001.cf0000644000175100017510000000410612412221023022526 0ustar00a10038a1003800000000000000####################################################### # # Acceptance test for issue #4070 # Ensure that cfengine creates a # file that has the same name as a pre-existing # directory without consuming 100% cpu and crashing # This test does what it says in 4070 - it creates # a directory e.g. /tmp/backup/my_dir # It then causes cfengine to create a file with an # identical name i.e. /tmp/backup/my_dir # The names above are simplified so as not to cause # confusion. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { ####################################### #Clean up test directory before testing ####################################### files: "$(G.testdir)/." depth_search => recurse("inf"), delete => tidy, file_select => all, classes => if_ok("dir_purged"); commands: dir_purged:: "$(G.mkdir) -p" args => "$(G.testdir)/backup/_tmp_TEST_cfengine_test"; } bundle edit_line test_insert(str) { insert_lines: "$(sys.date)"; } ####################################################### bundle agent test { files: agent_ran:: "$(G.testdir)/test" edit_line => test_insert("inserted text"), classes => if_ok("file_edited"); commands: "$(sys.cf_agent)" args => "-f $(this.promise_filename).sub -K", classes => if_ok("agent_ran"); file_edited:: "$(sys.cf_agent)" args => "-f $(this.promise_filename).sub -K -D SECOND_RUN", classes => classes_generic("agent_ran_test"), contain => test_timeout; } body contain test_timeout { exec_timeout => "30"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testdir)/SECOND_RUN"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/13_file_dir/001.cf.sub0000644000175100017510000000204012352022221023313 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "create_test_file" }; inputs => { "../../default.cf.sub" }; } body agent control { default_repository => "$(G.testdir)/backup"; } bundle agent create_test_file { files: "$(G.testdir)/test" create => "true", edit_line => append_if_no_line("username:x:1:3:gcos:/home/dir:/bin/false"); "$(G.testdir)/test" changes => diff; SECOND_RUN:: "$(G.testdir)/SECOND_RUN" create => "true"; } body changes diff { hash => "sha256"; report_changes => "content"; report_diffs => "true"; update_hashes => "yes"; } cfengine-3.6.2/tests/acceptance/10_files/01_create/0000755000175100017510000000000012352022221021400 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/01_create/copy_and_purge.cf0000644000175100017510000000432212243421446024724 0ustar00a10038a1003800000000000000####################################################### # # Redmine #3429: copy and purge files and directories should purge empty directories too # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { } ####################################################### bundle agent init { methods: "1" usebundle => init1; "2" usebundle => init2; } bundle agent init1 { files: "$(G.testfile)" delete => init_delete; } bundle agent init2 { files: "$(G.testfile)/source/1/2/3/." create => "true"; "$(G.testfile)/dest/1/2/should-be-removed/3/." create => "true"; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)/dest/." create => "true", depth_search => test_recurse("inf"), action => test_immediate, copy_from => test_sync("$(G.testfile)/source"); } body depth_search test_recurse(d) { depth => "$(d)"; xdev => "true"; } body action test_immediate { ifelapsed => "0"; } body copy_from test_sync(from) { source => "$(from)"; purge => "true"; preserve => "false"; type_check => "false"; compare => "digest"; } ####################################################### bundle agent check { classes: "ok_copy" expression => fileexists("$(G.testfile)/dest/1/2/3"); "ok_purge" not => fileexists("$(G.testfile)/dest/1/2/should-be-removed"); "bad_copy" not => fileexists("$(G.testfile)/dest/1/2/3"); "bad_purge" expression => fileexists("$(G.testfile)/dest/1/2/should-be-removed"); "ok" and => { ok_copy, ok_purge }; reports: DEBUG:: "The copy worked" ifvarclass => "ok_copy"; "The purge worked" ifvarclass => "ok_purge"; "The copy failed" ifvarclass => "bad_copy"; "The purge failed" ifvarclass => "bad_purge"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/007.cf0000644000175100017510000000315612316547775022257 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check owners/mode # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0644"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)); } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/004.cf0000644000175100017510000000342012332665147022236 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check initial permissions (strange mode) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "01010"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; } ####################################################### bundle agent check { vars: !freebsd.!solaris.!windows:: "expect[modeoct]" string => "[0-9]+$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); # # OS X refuses to open(2) file you have no permissions for (which is required for safe_chmod), # so this test is temporarily disabled there. # reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok|darwin:: "$(this.promise_filename) Pass"; not_ok&!darwin:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/008.cf0000644000175100017510000000326512316547775022261 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check owners/mode, different order - assumption, this is run # by root (see notes below) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0644"; files: "$(G.testfile)" create => "true", perms => test_perms($(mode)); } body perms test_perms(m) { mode => "$(m)"; owners => { "0" }; groups => { "0" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/003.cf0000644000175100017510000000311312316547775022244 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check initial permissions (odd mode) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0146"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/perms-mode.cf0000644000175100017510000000447612352022221023775 0ustar00a10038a1003800000000000000####################################################### # # Redmine #4791: body perms mode # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent test { vars: freebsd|solaris:: "modes" slist => { "1", "333", "100", "200", "777" }; !freebsd.!solaris:: "modes" slist => { "1", "333", "100", "200", "777", "1111", "1010", "13400", "22222" }; files: "$(G.testdir)/$(modes)" create => "true", perms => test_mode($(modes)); } body perms test_mode(m) { mode => "$(m)"; } bundle agent check { vars: "modes" slist => { @(test.modes) }; windows:: "win_r" string => "100444"; "win_w" string => "100666"; "expected" data => parsejson(' { "1": "$(win_r)", "333": "$(win_w)", "100": "$(win_r)", "200": "$(win_w)", "777": "$(win_w)", "1111": "$(win_r)", "1010": "$(win_r)", "13400": "$(win_r)", "22222": "$(win_r)", }'); freebsd|solaris:: "expected" data => parsejson(' { "1": "100001", "333": "100333", "100": "100100", "200": "100200", "777": "100777", }'); !freebsd.!solaris.!windows:: "expected" data => parsejson(' { "1": "100001", "333": "100333", "100": "100100", "200": "100200", "777": "100777", "1111": "101111", "1010": "101010", "13400": "103400", "22222": "102222", }'); any:: "actual[$(modes)]" string => filestat("$(G.testdir)/$(modes)", "modeoct"); classes: "ok_$(modes)" expression => strcmp("$(expected[$(modes)])", "$(actual[$(modes)])"); freebsd|solaris:: "ok" and => { "ok_1", "ok_333", "ok_100", "ok_200", "ok_777" }; !freebsd.!solaris:: "ok" and => { "ok_1", "ok_333", "ok_100", "ok_200", "ok_777", "ok_1111", "ok_1010", "ok_13400", "ok_22222" }; reports: DEBUG:: "Permission $(modes) worked, got $(expected[$(modes)])" ifvarclass => "ok_$(modes)"; "Permission $(modes) failed, expected $(expected[$(modes)]) != actual $(actual[$(modes)])" ifvarclass => "!ok_$(modes)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/005.cf0000644000175100017510000000340512316547775022252 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check initial permissions (strange setgid mode) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "02001"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "[0-9]+$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); # # OS X refuses to open(2) file you have no permissions for (which is required for safe_chmod), # so this test is temporarily disabled there. # reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok|darwin:: "$(this.promise_filename) Pass"; not_ok&!darwin:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/006.cf0000644000175100017510000000313512316547775022253 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check initial permissions (strange setuid mode) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "04777"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; } ####################################################### bundle agent check { vars: !windows:: "expect[modeoct]" string => "[0-9]+$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/009.cf0000644000175100017510000000371112316547775022256 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check owners/mode, different order - assumption, this is run # by root (see notes below) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0644"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; # In the POSIX model, one cannot create a file for another user, one can only # create a file as you, and then change owners. This test file will be created # by root, but then changed to sys - and thus the promise to be owned by sys # is kept. owners => { "3", "1" }; groups => { "3", "1" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/directory_with_trailing_slash.cf0000644000175100017510000000312012316547775030062 0ustar00a10038a1003800000000000000####################################################### # # Redmine#3905: Create a directory, set permissions using a trailing slash # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "mode" string => "751"; methods: "1" usebundle => test1; # create the directory "1" usebundle => test2($(mode)); # promise the directory with a trailing slash } bundle agent test1 { files: "$(G.testfile)/." create => "true", perms => test_perms("700"); } bundle agent test2(mode) { files: "$(G.testfile)/" perms => test_perms($(mode)); } body perms test_perms(m) { mode => "$(m)"; } ####################################################### bundle agent check { vars: "result" string => filestat($(G.testfile), "permoct"); classes: "ok" expression => strcmp($(test.mode), "$(result)"); reports: DEBUG:: "expected: '$(test.mode)'"; "got: '$(result)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/002.cf0000644000175100017510000000312312316547775022244 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check initial permissions (predictable mode) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0641"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/001.cf0000644000175100017510000000274212316547775022251 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check defaults # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" create => "true"; } ####################################################### bundle agent check { vars: # We want default 0600, 1 link, zero size !windows:: "expect[permoct]" string => "600"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/01_create/010.cf0000644000175100017510000000317212316547775022247 0ustar00a10038a1003800000000000000####################################################### # # Create a file, check owner/group (single choice) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" delete => init_delete; } body delete init_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent test { vars: "mode" int => "0644"; files: "$(G.testfile)" create => "true", perms => test_perms; } body perms test_perms { mode => "$(test.mode)"; owners => { "3" }; groups => { "3" }; } ####################################################### bundle agent check { vars: !windows:: "expect[permoct]" string => "$(test.mode)"; any:: "expect[nlink]" string => "1"; "expect[uid]" string => "\d+"; "expect[gid]" string => "\d+"; "expect[size]" string => "0"; "fields" slist => getindices("expect"); "result[$(fields)]" string => filestat("$(G.testfile)", "$(fields)"); classes: "not_ok" not => regcmp("$(expect[$(fields)])", "$(result[$(fields)])"); reports: DEBUG:: "expected: $(fields) = '$(expect[$(fields)])'"; "got: $(fields) = '$(result[$(fields)])'"; !not_ok:: "$(this.promise_filename) Pass"; not_ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/0000755000175100017510000000000012316547775021266 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/04_match/not_selected_dirs_are_skipped.cf0000644000175100017510000000461612316547775027646 0ustar00a10038a1003800000000000000######################################################################## # # Make sure that a directory is skipped when body_select does not match # it, even when depth_search is off. # ######################################################################## body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### body perms perms1 { mode => "732"; } body depth_search recurse_nobasedir(x) { depth => "$(x)"; include_basedir => "false"; } body delete del { rmdirs => "true"; } body file_select by_name(names) { leaf_name => { @(names) }; file_result => "leaf_name"; } bundle agent init { files: # Create a directory and some files in there "$(G.testroot)/srcdir/." create => "true"; "$(G.testroot)/srcdir/testfile1" create => "true"; "$(G.testroot)/srcdir/testfile2" create => "true"; # The destination should already exist and have specific # permissions, so that it's excluded by the body files_select later "$(G.testroot)/destdir/." perms => perms1, create => "true"; # Make sure all of its contents are cleaned up "$(G.testroot)/destdir" depth_search => recurse_nobasedir("inf"), file_select => by_name(".*"), delete => del; } ####################################################### body file_select test_select { # Select will fail because the dir is mode 732 search_mode => { "444" }; file_result => "mode"; } body link_from ln_s_children(x) { link_type => "symlink"; link_children => "true"; source => "$(x)"; } bundle agent test { # We promise that if destdir has specific permissions, then it must # contain links to all children from srcdir. files: "$(G.testroot)/destdir" file_select => test_select, link_from => ln_s_children("$(G.testroot)/srcdir"); } ####################################################### bundle agent check { # Since body select fails, the files in target directory should *not* # be created classes: "files_created" and => { fileexists("$(G.testroot)/destdir/testfile1"), fileexists("$(G.testroot)/destdir/testfile2") }; reports: !files_created:: "$(this.promise_filename) Pass"; files_created:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/10_files/04_match/004.cf0000644000175100017510000000306612243421446022071 0ustar00a10038a1003800000000000000####################################################### # # Test exec_program on file_select (issue 294) - test negative match on existing file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "find_this" string => "bibbetygargle"; files: "$(G.testfile)" create => "true", edit_line => init_data; } bundle edit_line init_data { insert_lines: "Gabba gabba hey!"; "yibbity $(find_this) bletch"; "torchecol bum adder"; } ####################################################### bundle agent test { vars: linux:: "prefix" string => ""; freebsd:: "prefix" string => "/usr"; !(linux|freebsd):: "prefix" string => "FIX ME"; files: "$(G.testroot)" file_select => test_hunt("$(prefix)"), delete => test_delete; } body file_select test_hunt(prefix) { exec_program => "$(G.grep) XX$(init.find_this)XX $(this.promiser)"; file_result => "exec_program"; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" expression => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/directory_can_not_readlink.cf.sub0000644000175100017510000000173612243421446027736 0ustar00a10038a1003800000000000000####################################################### # # Find a directory when expecting a symlink # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { symlinks }; version => "1.0"; } ####################################################### bundle agent symlinks { vars: "checkdir" string => "$(G.testdir)/should-not-show-up-in-output"; classes: "checkdir_exists" expression => fileexists($(checkdir)); files: "$(checkdir)" handle => "delete_checkdir_link", comment => "Delete checkdir symlink", file_select => select_link("/home"), delete => nodir, pathtype => "literal"; reports: checkdir_exists:: "CHECKPOINT"; } body file_select select_link(name) { file_types => { "symlink" }; issymlinkto => { "$(name)$" }; file_result => "issymlinkto"; } body delete nodir { rmdirs => "false"; } cfengine-3.6.2/tests/acceptance/10_files/04_match/008.cf0000644000175100017510000000234312243421446022072 0ustar00a10038a1003800000000000000####################################################### # # Delete a file in a nonexistant directory. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "1"; } ####################################################### bundle agent test { vars: "agent" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO 2>&1", "useshell"); } ####################################################### bundle agent check { classes: "chdir" expression => regcmp(".*chdir.*", $(test.agent)); "checkpoint" expression => regcmp(".*CHECKPOINT.*", $(test.agent)); "ok" and => { "!chdir", "checkpoint" }; reports: DEBUG:: "This should only pass if $(this.promise_filename).sub does not output anything about failing to chdir"; "Output from $(this.promise_filename).sub: $(test.agent)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/directory_can_not_readlink.cf0000644000175100017510000000305212316547775027156 0ustar00a10038a1003800000000000000####################################################### # # Delete a file in a nonexistant directory. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; cache_system_functions => "false"; } ####################################################### bundle agent init { vars: "checkdir" string => "$(G.testdir)/should-not-show-up-in-output"; files: "$(checkdir)/." create => "true"; } ####################################################### bundle agent test { vars: "agent" string => execresult("$(sys.cf_agent) -Kf $(this.promise_filename).sub -D AUTO 2>&1", "useshell"); } ####################################################### bundle agent check { classes: "checkpoint_fail" not => regcmp(".*CHECKPOINT.*", $(test.agent)); "fail" or => { checkpoint_fail, regcmp(".*Unable to read link.*", $(test.agent)), regcmp(".*$(init.checkdir).*", $(test.agent)) }; reports: DEBUG:: "This should only pass if $(this.promise_filename).sub does not output anything about failing to readlink"; "Output from $(this.promise_filename).sub: $(test.agent)"; DEBUG.checkpoint_fail:: "The secondary policy in $(this.promise_filename).sub did not checkpoint correctly"; !fail:: "$(this.promise_filename) Pass"; fail:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/008.cf.sub0000644000175100017510000000074312243421446022664 0ustar00a10038a1003800000000000000####################################################### # # Delete a file in a nonexistant directory. # ####################################################### body common control { bundlesequence => { "delete" }; version => "1.0"; } ####################################################### bundle agent delete { files: "/abc/nofile" delete => test_delete; reports: "CHECKPOINT"; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } cfengine-3.6.2/tests/acceptance/10_files/04_match/kept_promise.cf0000644000175100017510000000335112243421446024264 0ustar00a10038a1003800000000000000####################################################### # # Check that already inserted lines trigger promise # kept. # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { vars: "array[1]" string => "one"; "array[2]" string => "two"; "array[3]" string => "three"; files: "$(G.testfile)" create => "true", edit_line => init_edit; } bundle agent test { files: "$(G.testfile)" create => "true", edit_line => test_edit; } bundle edit_line init_edit { vars: "index" slist => getindices("init.array"); insert_lines: "${test.array[${index}]}"; } bundle edit_line test_edit { vars: "index" slist => getindices("init.array"); insert_lines: "${test.array[${index}]}" classes => kept_if_else("line_${index}_kept", "line_${index}_added", "line_${index}_failed"); } bundle agent check { classes: "ok" and => { "line_1_kept", "line_2_kept", "line_3_kept" }; reports: DEBUG.!line_1_kept:: "Line 1 promise should have been kept, but was not."; DEBUG.!line_2_kept:: "Line 2 promise should have been kept, but was not."; DEBUG.!line_3_kept:: "Line 3 promise should have been kept, but was not."; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } body classes kept_if_else(kept, yes, no) { promise_kept => { "${kept}" }; promise_repaired => { "${yes}" }; repair_failed => { "${no}" }; repair_denied => { "${no}" }; repair_timeout => { "${no}" }; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/staging/0000755000175100017510000000000012243421446022703 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/10_files/04_match/staging/007.cf0000644000175100017510000000257412243421446023533 0ustar00a10038a1003800000000000000####################################################### # # Test exec_program on file_select (issue 294) - test negative match on existing file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "find_this" string => "bibbetygargle"; files: "$(G.testfile)" create => "true", edit_line => init_data; } bundle edit_line init_data { insert_lines: "Gabba gabba hey!"; "yibbity $(find_this) bletch"; "torchecol bum adder"; } ####################################################### bundle agent test { files: "/tmp" file_select => test_hunt, delete => test_delete; } body file_select test_hunt { exec_regex => "$(test.find_this)"; # Partial regex shouldn't match exec_program => "/bin/cat $(this.promiser)"; file_result => "exec_program.exec_regex"; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/staging/003.cf0000644000175100017510000000275312243421446023526 0ustar00a10038a1003800000000000000####################################################### # # Test exec_program on file_select (issue 294) - test positive match on existing file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "find_this" string => "bibbetygargle"; files: "$(G.testfile)" create => "true", edit_line => init_data; } bundle edit_line init_data { insert_lines: "Gabba gabba hey!"; "yibbity $(find_this) bletch"; "torchecol bum adder"; } ####################################################### bundle agent test { vars: linux:: "prefix" string => ""; freebsd:: "prefix" string => "/usr"; !(linux|freebsd):: "prefix" string => "FIX ME"; files: "/tmp" file_select => test_hunt("$(prefix)"), delete => test_delete; } body file_select test_hunt(prefix) { exec_program => "$(G.grep) $(init.find_this) $(this.promiser)"; file_result => "exec_program"; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/staging/005.cf0000644000175100017510000000254012243421446023522 0ustar00a10038a1003800000000000000####################################################### # # Test exec_program on file_select (issue 294) - test positive match on existing file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "find_this" string => "bibbetygargle"; files: "$(G.testfile)" create => "true", edit_line => init_data; } bundle edit_line init_data { insert_lines: "Gabba gabba hey!"; "yibbity $(find_this) bletch"; "torchecol bum adder"; } ####################################################### bundle agent test { files: "/tmp" file_select => test_hunt, delete => test_delete; } body file_select test_hunt { exec_regex => ".*$(test.find_this).*"; exec_program => "/bin/cat $(this.promiser)"; file_result => "exec_program.exec_regex"; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/staging/006.cf0000644000175100017510000000254412243421446023527 0ustar00a10038a1003800000000000000####################################################### # # Test exec_program on file_select (issue 294) - test negative match on existing file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "find_this" string => "bibbetygargle"; files: "$(G.testfile)" create => "true", edit_line => init_data; } bundle edit_line init_data { insert_lines: "Gabba gabba hey!"; "yibbity $(find_this) bletch"; "torchecol bum adder"; } ####################################################### bundle agent test { files: "/tmp" file_select => test_hunt, delete => test_delete; } body file_select test_hunt { exec_regex => ".*XX$(test.find_this)XX.*"; exec_program => "/bin/cat $(this.promiser)"; file_result => "exec_program.exec_regex"; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/staging/002.cf0000644000175100017510000000165612243421446023526 0ustar00a10038a1003800000000000000####################################################### # # Create a file and delete it - hoping that it matches (issue 365) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testfile)" create => "true"; } ####################################################### bundle agent test { files: "/tmp/TEST\.cfengine" delete => test_delete; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/match_scope.cf0000644000175100017510000000233612243421446024052 0ustar00a10038a1003800000000000000####################################################### # # Check that $(match.1) works # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "testfile" string => concat("$(G.testdir)", "/dummy_file"); files: "$(testfile)" create => "true"; reports: DEBUG:: "Creating file $(testfile)"; } ####################################################### bundle agent test { vars: "foo" string => "foo"; files: "$(G.testdir)/([^_]*)_(.*)" delete => test_delete, classes => test_classes; } body classes test_classes { promise_repaired => { "$(match.1)", "$(match.2)" }; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" and => { "dummy", "file" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/10_files/04_match/001.cf0000644000175100017510000000173712243421446022071 0ustar00a10038a1003800000000000000####################################################### # # Create a file and delete it - hoping that it matches (issue 365) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true"; } ####################################################### bundle agent test { files: "$(G.testfile)" delete => test_delete; } body delete test_delete { dirlinks => "delete"; rmdirs => "true"; } ####################################################### bundle agent check { classes: "ok" not => fileexists("$(G.testfile)"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 27 cfengine-3.6.2/tests/acceptance/dummy_etc/0000755000175100017510000000000012316547775020253 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/dummy_etc/shadow0000644000175100017510000000162612316547775021470 0ustar00a10038a1003800000000000000root:!:15797:0:99999:7::: daemon:*:15797:0:99999:7::: bin:*:15797:0:99999:7::: sys:*:15797:0:99999:7::: sync:*:15797:0:99999:7::: games:*:15797:0:99999:7::: man:*:15797:0:99999:7::: lp:*:15797:0:99999:7::: mail:*:15797:0:99999:7::: news:*:15797:0:99999:7::: uucp:*:15797:0:99999:7::: proxy:*:15797:0:99999:7::: www-data:*:15797:0:99999:7::: backup:*:15797:0:99999:7::: list:*:15797:0:99999:7::: irc:*:15797:0:99999:7::: gnats:*:15797:0:99999:7::: nobody:*:15797:0:99999:7::: libuuid:!:15797:0:99999:7::: syslog:*:15797:0:99999:7::: messagebus:*:15797:0:99999:7::: colord:*:15797:0:99999:7::: lightdm:*:15797:0:99999:7::: whoopsie:*:15797:0:99999:7::: avahi-autoipd:*:15797:0:99999:7::: avahi:*:15797:0:99999:7::: usbmux:*:15797:0:99999:7::: kernoops:*:15797:0:99999:7::: pulse:*:15797:0:99999:7::: rtkit:*:15797:0:99999:7::: saned:*:15797:0:99999:7::: speech-dispatcher:!:15797:0:99999:7::: hplip:*:15797:0:99999:7::: cfengine-3.6.2/tests/acceptance/dummy_etc/passwd0000644000175100017510000000311112316547775021473 0ustar00a10038a1003800000000000000root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh proxy:x:13:13:proxy:/bin:/bin/sh www-data:x:33:33:www-data:/var/www:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh list:x:38:38:Mailing List Manager:/var/list:/bin/sh irc:x:39:39:ircd:/var/run/ircd:/bin/sh gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh nobody:x:65534:65534:nobody:/nonexistent:/bin/sh libuuid:x:100:101::/var/lib/libuuid:/bin/sh syslog:x:101:103::/home/syslog:/bin/false messagebus:x:102:105::/var/run/dbus:/bin/false colord:x:103:108:colord colour management daemon,,,:/var/lib/colord:/bin/false lightdm:x:104:111:Light Display Manager:/var/lib/lightdm:/bin/false whoopsie:x:105:114::/nonexistent:/bin/false avahi-autoipd:x:106:117:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false avahi:x:107:118:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false usbmux:x:108:46:usbmux daemon,,,:/home/usbmux:/bin/false kernoops:x:109:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false pulse:x:110:119:PulseAudio daemon,,,:/var/run/pulse:/bin/false rtkit:x:111:122:RealtimeKit,,,:/proc:/bin/false saned:x:112:123::/home/saned:/bin/false speech-dispatcher:x:113:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/sh hplip:x:114:7:HPLIP system user,,,:/var/run/hplip:/bin/false cfengine-3.6.2/tests/acceptance/dummy_etc/group0000644000175100017510000000146512316547775021340 0ustar00a10038a1003800000000000000root:x:0: daemon:x:1: bin:x:2: sys:x:3: adm:x:4: tty:x:5: disk:x:6: lp:x:7: mail:x:8: news:x:9: uucp:x:10: man:x:12: proxy:x:13: kmem:x:15: dialout:x:20: fax:x:21: voice:x:22: cdrom:x:24: floppy:x:25: tape:x:26: sudo:x:27: audio:x:29:pulse dip:x:30: www-data:x:33: backup:x:34: operator:x:37: list:x:38: irc:x:39: src:x:40: gnats:x:41: shadow:x:42: utmp:x:43: video:x:44: sasl:x:45: plugdev:x:46: staff:x:50: games:x:60: users:x:100: nogroup:x:65534: libuuid:x:101: crontab:x:102: syslog:x:103: fuse:x:104: messagebus:x:105: bluetooth:x:106: scanner:x:107: colord:x:108: lpadmin:x:109: ssl-cert:x:110: lightdm:x:111: nopasswdlogin:x:112: netdev:x:113: whoopsie:x:114: mlocate:x:115: ssh:x:116: avahi-autoipd:x:117: avahi:x:118: pulse:x:119: pulse-access:x:120: utempter:x:121: rtkit:x:122: saned:x:123: sambashare:x:124: cfengine-3.6.2/tests/acceptance/dummy_etc/null0000644000175100017510000000000012316547775021136 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/dummy_etc/motd0000644000175100017510000000004412316547775021137 0ustar00a10038a1003800000000000000Welcome to the CFEngine Test Suite! cfengine-3.6.2/tests/acceptance/Makefile.am0000644000175100017510000000366112411001073020273 0ustar00a10038a1003800000000000000AM_CPPFLAGS = $(ENTERPRISE_CFLAGS) \ -I$(top_srcdir)/libpromises \ -I$(top_srcdir)/libutils \ -I$(top_srcdir)/libcfnet \ $(OPENSSL_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) noinst_PROGRAMS = noinst_LTLIBRARIES = libmock_package_manager.la libmock_package_manager_la_SOURCES = mock_package_manager.c libmock_package_manager_la_LIBADD = ../../libpromises/libpromises.la if !BUILTIN_EXTENSIONS noinst_PROGRAMS += mock_package_manager mock_package_manager_SOURCES = mock_package_manager_LDADD = libmock_package_manager.la endif # !BUILTIN_EXTENSIONS if HAVE_LIBXML2 noinst_PROGRAMS += xml-c14nize xml_c14nize_CPPFLAGS = \ -I$(top_srcdir)/libpromises \ -I$(srcdir)/../../libutils \ $(LIBXML2_CPPFLAGS) xml_c14nize_CFLAGS = $(LIBXML2_CFLAGS) xml_c14nize_LDFLAGS = $(LIBXML2_LDFLAGS) xml_c14nize_LDADD = ../../libutils/libutils.la \ $(LIBXML2_LIBS) endif EXTRA_DIST = default.cf.sub dcs.cf.sub plucked.cf.sub testall dummy_etc TESTS = testall TESTS_ENVIRONMENT = env \ AGENT=`pwd`/../../cf-agent/cf-agent \ CF_PROMISES=`pwd`/../../cf-promises/cf-promises \ CF_SERVERD=`pwd`/../../cf-serverd/cf-serverd \ CF_KEY=`pwd`/../../cf-key/cf-key \ MOCK_PACKAGE_MANAGER=`pwd`/mock_package_manager if !HAVE_LIBXML2 TESTS_ENVIRONMENT += LIBXML2_TESTS=0 endif dist-hook: cd $(srcdir); tar -c -f - [0-9]* | tar -x -C $(abspath $(distdir)) -f - chmod -R go-w $(distdir) CLEANFILES = *.gcno *.gcda pluck: echo '### This is an auto-generated file, see Makefile.am and `make pluck` ###' > plucked.cf.sub ../../contrib/cf-locate/cf-locate -f -p '( if_|warn_only|INI_section|kept_successful_command|edit_line|set_user_field|set_variable_values\(|edit_field|set_line_based|location|replace_with|_cp|_dcp|empty|shell|immediate|perms| m\b|recurse|tidy| all|classes_generic| start|always|^value|edit_field line|insert_lines|(link|copy)from| file_mustache| (file|dir)_(copy|tidy|sync|make|empty|link|hardlink))' ../../../masterfiles/lib/3.6 >> plucked.cf.sub cfengine-3.6.2/tests/acceptance/05_processes/0000755000175100017510000000000012411001073020543 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/05_processes/01_matching/0000755000175100017510000000000012412221023022635 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/05_processes/01_matching/204.cf0000644000175100017510000000246112411001073023457 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, more complex matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: ".*" process_select => test_select_high_users, classes => test_set_class("found", "not_found"); } body classes test_set_class(t,f) { promise_kept => { "$(t)" }; promise_repaired => { "$(t)" }; repair_failed => { "$(f)" }; } body process_select test_select_high_users { ttime_range => irange(0, accumulated(9,0,0,0,0,0)); # Anything process_result => "!ttime"; # Nothing } ####################################################### bundle agent check { classes: "ok" expression => "found.!not_found"; # Nothing found is "kept" reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/004.cf0000644000175100017510000000215712412221023023457 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6340" }; processes: "\bcf-agent\b" process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(1,"inf"); } ####################################################### bundle agent check { classes: "ok" expression => "found.!not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/203.cf0000644000175100017510000000242212411001073023453 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, more complex matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: ".*" process_select => test_select_high_users, classes => test_set_class("found", "not_found"); } body classes test_set_class(t,f) { promise_kept => { "$(t)" }; promise_repaired => { "$(t)" }; repair_failed => { "$(f)" }; } body process_select test_select_high_users { ttime_range => irange(0, accumulated(9,0,0,0,0,0)); # Anything process_result => "ttime"; # Everything } ####################################################### bundle agent check { classes: "ok" expression => "found.!not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/201.cf0000644000175100017510000000254412412221023023456 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, more complex matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6343" }; processes: ".*" process_count => test_range, process_select => test_select_high_users; } body process_count test_range { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(0,0); } body process_select test_select_high_users { ttime_range => irange(0, accumulated(9,0,0,0,0,0)); # Anything process_result => "ttime"; # Everything } ####################################################### bundle agent check { classes: "ok" expression => "!found.not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/003.cf0000644000175100017510000000204112411001073023446 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does not exist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: "There-is-NoPrOCess-with-this-name" process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(1,"inf"); } ####################################################### bundle agent check { classes: "ok" expression => "!found.not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/100.cf0000644000175100017510000000216312412221023023451 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, partial name # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6342" }; processes: "-agent" process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(0,0); } ####################################################### bundle agent check { classes: "ok" expression => "!found.not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/005.cf0000644000175100017510000000203512411001073023453 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does not exist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: "There-is-NoPrOCess-with-this-name" process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(0,0); } ####################################################### bundle agent check { classes: "ok" expression => "found.!not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/006.cf0000644000175100017510000000215312412221023023455 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6341" }; processes: "\bcf-agent\b" process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(0,0); } ####################################################### bundle agent check { classes: "ok" expression => "!found.not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/002.cf0000644000175100017510000000157212411001073023455 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process exists # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { processes: "\bcf-agent\b" restart_class => "not_ok"; classes: "ok" not => "not_ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/staging/0000755000175100017510000000000012411001073024271 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/05_processes/01_matching/staging/103.cf0000644000175100017510000000207412411001073025111 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, partial name fails # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: # Issue 362 "There-is-NoPrOCess-with-this-name" restart_class => "restart", process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange("0","0"); } ####################################################### bundle agent check { classes: "ok" expression => "restart.found.found.!not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/202.cf0000644000175100017510000000255312412221023023457 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, more complex matches # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4747" }; processes: ".*" process_count => test_range, process_select => test_select_high_users; } body process_count test_range { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(0,0); } body process_select test_select_high_users { ttime_range => irange(0, accumulated(9,0,0,0,0,0)); # Anything process_result => "!ttime"; # Nothing } ####################################################### bundle agent check { classes: "ok" expression => "found.!not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/001.cf0000644000175100017510000000155312411001073023453 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does not exist # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { processes: "There-is-NoPrOCess-with-this-name" restart_class => "ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/05_processes/01_matching/101.cf0000644000175100017510000000173612411001073023457 0ustar00a10038a1003800000000000000####################################################### # # Set a class if a process does exist, partial name fails # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { processes: "cf-agent$" process_count => test_no_such; } body process_count test_no_such { in_range_define => { "found" }; out_of_range_define => { "not_found" }; match_range => irange(0,0); } ####################################################### bundle agent check { classes: "ok" expression => "found.!not_found"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 30 cfengine-3.6.2/tests/acceptance/15_control/0000755000175100017510000000000012243421446020233 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/15_control/02_agent/0000755000175100017510000000000012332665147021641 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/15_control/02_agent/009.x.cf0000644000175100017510000000036012236160673022725 0ustar00a10038a1003800000000000000body common control { bundlesequence => { test }; } bundle common g { classes: "foo" and => { "any" }; } body agent control { abortclasses => { "foo" }; } bundle agent test { reports: foo:: "Aborting class defined"; }cfengine-3.6.2/tests/acceptance/15_control/02_agent/109.x.cf0000644000175100017510000000167212332665147022740 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - should abort in same agent bundle, regex # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; "quitquit" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/abortclasses_from_common_bundle.x.cf0000644000175100017510000000165112316547775031045 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses regexp - should abort in preliminary common bundle # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle common test { classes: "quitquit" expression => "any"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) FAIL"; !ok:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/006.x.cf0000644000175100017510000000171012243421446022716 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - should abort in preliminary agent bundle # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/023.cf0000644000175100017510000000204512243421446022451 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - control case 3, no abort # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quit" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Validate no submatch, reverse } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/abortclasses_even_without_classes.x.cf0000644000175100017510000000123612243421446031416 0ustar00a10038a1003800000000000000body common control { bundlesequence => { init, test }; } body agent control { abortclasses => { "foo", "bar", "foobar" }; } bundle agent init { reports: "Defining class indirectly foo" classes => always("foo"); "Defining class indirectly bar" classes => always("bar"); "Defining class indirectly foobar" classes => always("foobar"); } bundle agent test { reports: foo:: "Aborting class defined"; } body classes always(x) { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; repair_failed => { "$(x)" }; repair_denied => { "$(x)" }; repair_timeout => { "$(x)" }; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/005.x.cf0000644000175100017510000000200012332665147022715 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - should abort in common bundle, regex # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quit.*" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/008.x.cf0000644000175100017510000000166512243421446022731 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - should abort in same agent bundle # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; "quitquit" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/003.cf0000644000175100017510000000203112243421446022442 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - control case 3, no abort # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quit" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Validate no submatch, reverse } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/031.cf0000644000175100017510000000161512243421446022452 0ustar00a10038a1003800000000000000####################################################### # # Test addclasses # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { addclasses => { "ok" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Prevent reports from running reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/002.cf0000644000175100017510000000203612243421446022446 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - control case 2, no abort # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit", "quitquit.*" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quit" expression => "any"; # Validate no submatch } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/002.x.cf0000644000175100017510000000172112243421446022714 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses regexp - should abort in preliminary agent bundle # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) FAIL"; !ok:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/003.x.cf0000644000175100017510000000167612243421446022726 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses regexp - should abort in same agent bundle # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; "quitquit" expression => "any"; reports: ok:: "$(this.promise_filename) FAIL"; !ok:: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/022.cf0000644000175100017510000000174012243421446022451 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - control case 2, no abort # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quitquit", "quitquit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; "quit" expression => "any"; # Validate no submatch reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/staging/0000755000175100017510000000000012332665147023275 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/15_control/02_agent/staging/024.x.cf0000644000175100017510000000210612243421446024352 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - expect failure regex, ok should not be defined # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quit.*" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Should abort bundle "ok" expression => "any"; # Should not be defined } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/staging/027.x.cf0000644000175100017510000000210212243421446024351 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - expect failure, ok should not be defined # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quitquit" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Should abort bundle "ok" expression => "any"; # Should not be defined } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/staging/025.x.cf0000644000175100017510000000214312243421446024354 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - expect failure, report doesn't execute # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quitquit" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; # Globally set, but should still fail } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Prevent reports from running reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/staging/026.x.cf0000644000175100017510000000215012243421446024353 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - expect failure, regex, report doesn't execute # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quit.*" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; # Globally set, but should still fail } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; # Prevent reports from running reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/004.x.cf0000644000175100017510000000177312243421446022725 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - should abort in common bundle # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit" }; } bundle common g { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/021.cf0000644000175100017510000000164012243421446022447 0ustar00a10038a1003800000000000000####################################################### # # Test abortbundleclasses - control case 1, no abort # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortbundleclasses => { "quitquit", "quitquit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/001.cf0000644000175100017510000000162012243421446022443 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - control case 1, no abort # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quitquit", "quit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/02_agent/007.x.cf0000644000175100017510000000171512332665147022733 0ustar00a10038a1003800000000000000####################################################### # # Test abortclasses - should abort in preliminary agent bundle, regex # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } body agent control { abortclasses => { "quit.*" }; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; classes: "quitquit" expression => "any"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/0000755000175100017510000000000012411001073022006 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/15_control/01_common/011.x.cf0000644000175100017510000000152012243421446023102 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_inputs - control case # ####################################################### body common control { inputs => { "../../default.cf.sub", "missing" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/007.cf0000644000175100017510000000160212243421446022642 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles, expect to pass, methods # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_bundles => "on"; } ####################################################### # # bundle agent init # { # vars: # "dummy" string => "dummy"; # } # ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/dynamic.sub0000644000175100017510000000002712316547775024200 0ustar00a10038a1003800000000000000bundle agent dummy { } cfengine-3.6.2/tests/acceptance/15_control/01_common/004.cf0000644000175100017510000000165512332665147022656 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles, expect to pass, order independant # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "missing", default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_bundles => "on"; # Order should not matter! } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/001.x.cf0000644000175100017510000000152112243421446023102 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles - control case # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "missing", default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/inputs_directory.cf0000644000175100017510000000063112316547775025762 0ustar00a10038a1003800000000000000# Redmine#4683: ensure directories and missing files don't abort when # ignore_missing_inputs is set body common control { ignore_missing_inputs => "true"; inputs => { "/x.cf", "/", "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent init { } bundle agent test { } bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/inputs_from_readstringlist.cf.sub0000644000175100017510000000013212316547775030623 0ustar00a10038a1003800000000000000bundle common info { classes: "included_info_global_class" expression => "any"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/inputs_from_readstringlist.cf0000644000175100017510000000266112316547775030044 0ustar00a10038a1003800000000000000# Redmine#4683: dynamic inputs should work from readstringlist body common control { inputs => { "../../default.cf.sub", @(runlist.inputs) }; bundlesequence => { prep_runlist, runlist, default("$(this.promise_filename)") }; } # workaround: reading the data has to be separate from... bundle common prep_runlist { vars: "generated_inputs" string => "$(this.promise_filename).txt"; "inputs_pre" slist => readstringlist($(generated_inputs), "\s*#[^\n]*", "\n", 99999, 9999999); reports: EXTRA:: "$(this.bundle) reading inputs from file $(generated_inputs)"; } # ...the usage of the data bundle common runlist { vars: "inputs" slist => maplist("$(this.promise_dirname)/$(this)", "prep_runlist.inputs_pre"); reports: EXTRA:: "$(this.bundle) got inputs '$(inputs)'"; } bundle agent init { } bundle agent test { } bundle agent check { classes: "ok" and => { "included_info_global_class" }; reports: DEBUG.!included_info_global_class:: "BAD: The global class from the included file was not defined"; EXTRA.included_info_global_class:: "Good: The global class from the included file was defined"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/missing_inputs_directory.x.cf0000644000175100017510000000161612316547775027765 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_inputs with a directory - explicit failure expected # ####################################################### body common control { inputs => { "../../default.cf.sub", "/" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_inputs => "off"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/013.cf0000644000175100017510000000156712243421446022651 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_inputs, expect to pass # ####################################################### body common control { ignore_missing_inputs => "on"; inputs => { "../../default.cf.sub", "missing" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/014.cf0000644000175100017510000000165312332665147022655 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_inputs, expect to pass, order independant # ####################################################### body common control { inputs => { "../../default.cf.sub", "missing" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_inputs => "on"; # Order should not matter! } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/003.cf0000644000175100017510000000157112243421446022643 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles, expect to pass # ####################################################### body common control { ignore_missing_bundles => "on"; inputs => { "../../default.cf.sub" }; bundlesequence => { "missing", default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/002.x.cf0000644000175100017510000000160512243421446023106 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles - explicit failure expected # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "missing", default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_bundles => "off"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/022.cf0000644000175100017510000000173412332665147022654 0ustar00a10038a1003800000000000000####################################################### # # Test domain - expect it to set the $(sys.domain) variable # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; domain => "puppetlabs.com"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => strcmp("$(sys.domain)", "puppetlabs.com"); reports: DEBUG:: "Expected $(sys.domain) to be puppetlabs.com"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/staging/0000755000175100017510000000000012332665147023466 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/15_control/01_common/staging/006.x.cf0000644000175100017510000000161712243421446024551 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles - explicit failure expected, methods # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_bundles => "off"; } ####################################################### # # bundle agent init # { # vars: # "dummy" string => "dummy"; # } # ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/staging/005.x.cf0000644000175100017510000000153312243421446024545 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_bundles - control case, methods # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### # # bundle agent init # { # vars: # "dummy" string => "dummy"; # } # ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/inputs_from_readstringlist.cf.txt0000644000175100017510000000004212316547775030651 0ustar00a10038a1003800000000000000inputs_from_readstringlist.cf.sub cfengine-3.6.2/tests/acceptance/15_control/01_common/021.cf0000644000175100017510000000152412332665147022650 0ustar00a10038a1003800000000000000####################################################### # # Test domain # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; domain => "puppetlabs.com"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "puppetlabs_com"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/012.x.cf0000644000175100017510000000160312243421446023105 0ustar00a10038a1003800000000000000####################################################### # # Test ignore_missing_inputs - explicit failure expected # ####################################################### body common control { inputs => { "../../default.cf.sub", "missing" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; ignore_missing_inputs => "off"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "dummy" string => "dummy"; classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/15_control/01_common/inputs_from_json.cf0000644000175100017510000000105712316547775025755 0ustar00a10038a1003800000000000000# Redmine#4683: dynamic inputs should work from a data container body common control { #ignore_missing_inputs => "true"; inputs => { "../../default.cf.sub", "$(config.myfile)" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle common config { vars: "c" data => parsejson('{ "file": "dynamic.sub" }'); "myfile" string => "$(c[file])"; reports: DEBUG:: "myfile $(myfile)"; } bundle agent init { } bundle agent test { } bundle agent check { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/15_control/file/0000755000175100017510000000000012316547775021171 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/15_control/file/file_inputs.sub20000644000175100017510000000007012316547775024304 0ustar00a10038a1003800000000000000bundle agent check { reports: "$(init.file) Pass"; } cfengine-3.6.2/tests/acceptance/15_control/file/file_inputs.sub10000644000175100017510000000046512316547775024313 0ustar00a10038a1003800000000000000bundle common sub1 { vars: # this is the same file twice, which should be OK with hash checks "inputs" slist => { "$(this.promise_dirname)/file_inputs.sub2", "$(this.promise_dirname)/./file_inputs.sub2" }; } body file control { inputs => { @(sub1.inputs) }; } cfengine-3.6.2/tests/acceptance/15_control/file/file_inputs.cf0000644000175100017510000000053612316547775024030 0ustar00a10038a1003800000000000000body common control { ignore_missing_bundles => "yes"; inputs => { "../../default.cf.sub" }; bundlesequence => { "missing", default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "file" string => "$(this.promise_filename)"; } bundle agent test { } body file control { inputs => { "file_inputs.sub1" }; } cfengine-3.6.2/tests/acceptance/18_examples/0000755000175100017510000000000012411001073020357 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/18_examples/ouputs/0000755000175100017510000000000012411001073021716 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/18_examples/ouputs/check_outputs.cf0000644000175100017510000000463512411001073025120 0ustar00a10038a1003800000000000000####################################################### # # Check the example outputs # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } ####################################################### bundle agent init { vars: "basedir" string => "../../examples"; "checker" string => "$(basedir)/remake_outputs.pl"; "all_examples" slist => findfiles("$(basedir)/*.cf"); commands: # we need to avoid the cf-key messages "$(sys.cf_key)"; reports: DEBUG_LOTS:: "$(this.bundle): will consider example $(all_examples)"; } ####################################################### bundle agent test { meta: # It's unrealistic to keep this test perfectly stable on all non-Linux platforms. # It would require examples that quickly get very cluttered. "test_skip_unsupported" string => "!linux"; vars: "examples" slist => { @(init.all_examples) }; "canon[$(examples)]" string => canonify($(examples)); classes: "has_output_block_$(canon[$(examples)])" expression => regline(".*example_output.*", $(examples)); methods: "$(examples)" usebundle => test_example($(examples)), ifvarclass => "has_output_block_$(canon[$(examples)])"; reports: DEBUG:: "$(this.bundle): found example with output $(examples)" ifvarclass => "has_output_block_$(canon[$(examples)])"; } bundle agent test_example(file) { vars: "cfile" string => canonify($(file)); "checker" string => "$(G.perl) $(init.checker) --cfagent=$(sys.cf_agent) --workdir=$(G.testdir) -c"; classes: "failure_$(cfile)" not => returnszero("$(checker) $(file)", "noshell"), scope => "namespace"; methods: "with verbose" usebundle => verbose_output("$(checker) -v $(file)"), ifvarclass => "failure_$(cfile)"; reports: "$(this.bundle): checker '$(checker) $(file)' returned error" ifvarclass => "failure_$(cfile)"; DEBUG:: "$(this.bundle): ran checker '$(checker) $(file)'"; } bundle agent verbose_output(runme) { commands: "$(runme)"; } ####################################################### bundle agent check { classes: "ok" not => classmatch("failure.*"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/dcs.cf.sub0000644000175100017510000006032312412512360020117 0ustar00a10038a1003800000000000000######################################################################## # Acceptance test framework. # # See README for details about writing test cases. ######################################################################## bundle common G { vars: windows:: "cwd" string => execresult("C:\windows\system32\cmd.exe /C cd", "noshell"); # Use for redirection, not as a real file. "dev_null" string => "nul"; "exeext" slist => { ".exe", ".bat" }; !windows:: "cwd" string => execresult("/bin/pwd 2>/dev/null || /usr/bin/pwd", "useshell"); # Use for redirection, not as a real file. "dev_null" string => "/dev/null"; "exeext" string => ""; any:: # General commands. "cmds" slist => { "date", "diff", "cat", "colordiff", "echo", "egrep", "env", "false", "grep", "gzip", "hexdump", "ln", "ls", "mkdir", "mock_package_manager", "od", "perl", "printf", "ps", "psexec", "pwd", "rm", "sed", "seq", "sleep", "sort", "tee", "touch", "true", "wc", }; # Special cases. "make_cmds" slist => { "gmake", "make" }; any:: "paths[tests]" string => "$(this.promise_dirname)"; solaris:: "paths[usr_xpg4_bin]" string => "/usr/xpg4/bin"; "paths[usr_ucb_sparcv7]" string => "/usr/ucb/sparcv7"; "paths[opt_csw_bin]" string => "/opt/csw/bin"; !windows:: "paths[bin]" string => "/bin"; "paths[usr_bin]" string => "/usr/bin"; "paths[usr_local_bin]" string => "/usr/local/bin"; "paths[usr_contrib_bin]" string => "/usr/contrib/bin"; windows:: "paths[mingw_msys_1_0_bin]" string => "c:\\mingw\\msys\\1.0\\bin"; "paths[msys_1_0_bin]" string => "c:\\msys\\1.0\\bin"; "paths[msys_bin]" string => "c:\\msys\\bin"; "paths[pstools]" string => "c:\\PSTools"; "paths[strawberry_perl_bin]" string => "c:\\strawberry\\perl\\bin"; "paths[tool_wrappers]" string => "$(this.promise_dirname)\\tool_wrappers"; any:: "paths_indices" slist => getindices("paths"); classes: # General commands. "$(paths_indices)_$(cmds)$(exeext)" expression => fileexists("$(paths[$(paths_indices)])$(const.dirsep)$(cmds)$(exeext)"); "has_$(cmds)" expression => fileexists("$(paths[$(paths_indices)])$(const.dirsep)$(cmds)$(exeext)"), scope => "namespace"; # Special cases. "$(paths_indices)_$(make_cmds)$(exeext)" expression => fileexists("$(paths[$(paths_indices)])$(const.dirsep)$(make_cmds)$(exeext)"); "has_make" expression => fileexists("$(paths[$(paths_indices)])$(const.dirsep)$(make_cmds)$(exeext)"), scope => "namespace"; "want_color" expression => strcmp(getenv("CFENGINE_COLOR", 4k), "1"); "have_colordiff" expression => fileexists($(colordiff)); vars: # General commands. "$(cmds)" string => "$(paths[$(paths_indices)])$(const.dirsep)$(cmds)$(exeext)", ifvarclass => canonify("$(paths_indices)_$(cmds)$(exeext)"); # Special cases. # gmake has higher priority, so should come last. "make" string => "$(paths[$(paths_indices)])$(const.dirsep)make$(exeext)", ifvarclass => canonify("$(paths_indices)_make$(exeext)"); "make" string => "$(paths[$(paths_indices)])$(const.dirsep)gmake$(exeext)", ifvarclass => canonify("$(paths_indices)_gmake$(exeext)"); want_color.have_colordiff:: "diff_maybecolor" string => $(colordiff); !want_color|!have_colordiff:: "diff_maybecolor" string => $(diff); classes: "temp_declared" not => strcmp(getenv("TEMP", "65536"), ""); vars: "etc" string => "$(this.promise_dirname)$(const.dirsep)dummy_etc"; "etc_motd" string => "$(this.promise_dirname)$(const.dirsep)dummy_etc$(const.dirsep)motd"; "etc_passwd" string => "$(this.promise_dirname)$(const.dirsep)dummy_etc$(const.dirsep)passwd"; "etc_shadow" string => "$(this.promise_dirname)$(const.dirsep)dummy_etc$(const.dirsep)shadow"; "etc_group" string => "$(this.promise_dirname)$(const.dirsep)dummy_etc$(const.dirsep)group"; # Use instead of /dev/null when you need a real empty file to open. "etc_null" string => "$(this.promise_dirname)$(const.dirsep)dummy_etc$(const.dirsep)null"; temp_declared:: "testroot" string => getenv("TEMP", "65535"); "testdir" string => concat(getenv("TEMP", "65535"), "$(const.dirsep)TEST.cfengine"); "testfile" string => concat(getenv("TEMP", "65535"), "$(const.dirsep)TEST.cfengine"); !temp_declared:: "testroot" string => "$(const.dirsep)tmp"; "testdir" string => "$(const.dirsep)tmp$(const.dirsep)TEST.cfengine"; "testfile" string => "$(const.dirsep)tmp$(const.dirsep)TEST.cfengine"; } bundle common dcs_strings { vars: "multiline_potatoes" string => "BEGIN One potato Two potato Three potatoes Four END"; "multiline_potatoes_lesser" string => "BEGIN One potato Three potatoes Four END"; } bundle common paths_init(filename) { classes: "filename_absolute" expression => regcmp("/.*", "$(filename)"); } bundle common paths_absolute(filename) { vars: filename_absolute:: "input_file" string => "$(filename)"; !filename_absolute:: "input_file" string => "$(G.cwd)/$(filename)"; } bundle agent default(filename) { classes: "have_test_run_$(bundles)" expression => "any"; vars: "tests" slist => { "default:init", "default:test", "default:check" }; "bundles" slist => bundlesmatching("default:(init|test|check)"); methods: "any" usebundle => test_precheck; proceed_with_test:: "any" usebundle => test_run("$(filename)"), inherit => "true"; reports: EXTRA.verbose_mode:: "$(this.bundle): found runnable bundle $(bundles)"; } bundle agent test_run(filename) { vars: methods: "any" usebundle => paths_init("$(filename)"); "any" usebundle => paths_absolute("$(filename)"); AUTO:: "any" usebundle => "$(default.tests)", ifvarclass => canonify("have_test_run_$(default.tests)"); reports: !AUTO:: "# You must either specify '-D AUTO' or run the following commands:"; "cf-agent -f .$(const.dirsep)$(filename) -b $(tests)"; } bundle agent test_precheck { vars: "test_skip_unsupported" slist => variablesmatching(".*_meta\.test_skip_unsupported"); "test_skip_needs_work" slist => variablesmatching(".*_meta\.test_skip_needs_work"); "test_suppress_fail" slist => variablesmatching(".*_meta\.test_suppress_fail"); "test_suppress_fail_metatags" slist => getvariablemetatags("$(test_suppress_fail)"); "test_suppress_fail_redmine" slist => filter("redmine.*", "test_suppress_fail_metatags", "true", "false", 1); classes: "test_skip_unsupported_set" expression => some(".*", "test_skip_unsupported"); "test_skip_needs_work_set" expression => some(".*", "test_skip_needs_work"); "test_suppress_fail_set" expression => some(".*", "test_suppress_fail"); "test_suppress_fail_redmine_set" expression => some(".*", "test_suppress_fail_redmine"); "test_skip_unsupported_match" and => { "test_skip_unsupported_set", "$($(test_skip_unsupported))" }; "test_skip_needs_work_match" and => { "test_skip_needs_work_set", "$($(test_skip_needs_work))" }; "test_suppress_fail_match" and => { "test_suppress_fail_set", "$($(test_suppress_fail))" }; "proceed_with_test" and => { "!test_skip_unsupported_match", "!test_skip_needs_work_match" }, scope => "namespace"; reports: test_skip_unsupported_match:: "$(this.promise_filename) Skip/unsupported"; test_skip_needs_work_match:: "$(this.promise_filename) Skip/needs_work"; test_suppress_fail_match.test_suppress_fail_redmine_set:: "$(this.promise_filename) XFAIL/$(test_suppress_fail_redmine)"; test_suppress_fail_match.!test_suppress_fail_redmine_set:: "$(this.promise_filename) FAIL/no_redmine_number"; } ####################################################### bundle agent dcs_sort(infile, outfile) { commands: # Enforce byte sort order with LC_ALL. "$(G.env) LC_ALL=C $(G.sort) $(infile) > $(outfile)" contain => in_shell; } bundle agent dcs_check_diff(file1, file2, test) { methods: "any" usebundle => dcs_check_diff_expected($(file1), $(file2), $(test), "no"); } bundle agent dcs_if_diff(file1, file2, pass_class, fail_class) { methods: "any" usebundle => dcs_if_diff_expected($(file1), $(file2), "no", $(pass_class), $(fail_class)); } bundle agent sorted_check_diff(file1, file2, test) { methods: "any" usebundle => dcs_sort("$(file1)", "$(file1).sort"); "any" usebundle => dcs_sort("$(file2)", "$(file2).sort"); "any" usebundle => dcs_check_diff_expected("$(file1).sort", "$(file2).sort", $(test), "no"); } bundle agent xml_check_diff(file1, file2, test, expected_difference) { vars: DEBUG.check_ready.!no_difference:: "file1r" string => execresult("$(G.cwd)/xml-c14nize $(file1)", "noshell"); "file2r" string => execresult("$(G.cwd)/xml-c14nize $(file2)", "noshell"); DEBUG.check_ready.!no_difference.has_hexdump:: "file1h" string => execresult("$(G.hexdump) -C $(file1)", "useshell"); "file2h" string => execresult("$(G.hexdump) -C $(file2)", "useshell"); DEBUG.check_ready.!no_difference.!has_hexdump:: "file1h" string => execresult("$(G.od) -c $(file1)", "useshell"); "file2h" string => execresult("$(G.od) -c $(file2)", "useshell"); DEBUG.check_ready.!no_difference.has_unified_diff:: "diffu" string => execresult("$(G.diff_maybecolor) -u $(file2) $(file1) 2>$(G.dev_null)", "useshell"); DEBUG.check_ready.!no_difference.!has_unified_diff:: "diffu" string => execresult("$(G.diff_maybecolor) -c $(file2) $(file1) 2>$(G.dev_null)", "useshell"); classes: "has_unified_diff" expression => returnszero( "$(G.diff_maybecolor) -u $(G.etc_null) $(G.etc_null) >$(G.dev_null) 2>&1", "useshell"); c14n_files_created:: "no_difference" expression => returnszero( "$(G.diff_maybecolor) $(G.testfile).default-xml-check-diff-1 $(G.testfile).default-xml-check-diff-2 >$(G.dev_null) 2>&1", "useshell"); "expected_difference" expression => strcmp("$(expected_difference)", "yes"); "check_ready" expression => "any"; commands: "$(G.cwd)/xml-c14nize $(file1) > $(G.testfile).default-xml-check-diff-1" contain => in_shell; "$(G.cwd)/xml-c14nize $(file2) > $(G.testfile).default-xml-check-diff-2" contain => in_shell, classes => if_ok("c14n_files_created"); reports: check_ready.no_difference.!expected_difference:: "$(test) Pass"; check_ready.!no_difference.expected_difference:: "$(test) Pass"; check_ready.!no_difference.!expected_difference:: "$(test) FAIL"; check_ready.no_difference.expected_difference:: "$(test) FAIL"; DEBUG.check_ready.!no_difference.!expected_difference:: "$(file1) and $(file2) differ:"; "$(file1): <$(file1r)>"; "$(file2): <$(file2r)>"; "dump $(file1): $(file1h)"; "dump $(file2): $(file2h)"; "$(diffu)"; DEBUG.check_ready.no_difference.expected_difference:: "Contents of $(file1) and $(file) is the same."; } bundle agent dcs_report_generic_classes(x) { vars: "choices" slist => { "repaired", "failed", "denied", "timeout", "kept" }; reports: DEBUG:: "class '$(x)_$(choices)' was defined" ifvarclass => '$(x)_$(choices)'; "class '$(x)_$(choices)' was NOT defined" ifvarclass => '!$(x)_$(choices)'; } bundle agent dcs_generic_classes_to_string(x) { vars: "choices" slist => { "repaired", "failed", "denied", "timeout", "kept" }; "s[$(choices)]" string => "$(x)_$(choices)", ifvarclass => '$(x)_$(choices)'; "found_unsorted" slist => getvalues(s); "found" slist => sort(found_unsorted, "lex"); "found_str" string => format("%S", found); reports: "$(found_str)" bundle_return_value_index => "str"; } # These set/clear global classes, so they can be tested in another bundle body classes dcs_all_classes(prefix) { promise_kept => { "$(prefix)_promise_kept" }; promise_repaired => { "$(prefix)_promise_repaired" }; repair_failed => { "$(prefix)_repair_failed" }; repair_denied => { "$(prefix)_repair_denied" }; repair_timeout => { "$(prefix)_repair_timeout" }; cancel_kept => { "$(prefix)_cancel_kept" }; cancel_repaired => { "$(prefix)_cancel_repaired" }; cancel_notkept => { "$(prefix)_cancel_notkept" }; } bundle agent dcs_all_negative_classes(prefix) { # These must be global classes so they can be tested in another bundle # We set them here, so they can be (possibly) cleared later classes: "$(prefix)_cancel_kept" expression => "any", scope => "namespace"; "$(prefix)_cancel_repaired" expression => "any", scope => "namespace"; "$(prefix)_cancel_notkept" expression => "any", scope => "namespace"; } bundle agent dcs_all_classes_to_string(prefix) { vars: "classes_all" slist => classesmatching("$(prefix)_.*(kept|notkept|failed|denied|repaired|timeout)"); "classes" slist => sort(classes_all, "lex"); "found_str" string => format("%S", classes); reports: "$(found_str)" bundle_return_value_index => "str"; } bundle agent dcs_check_diff_expected(file1, file2, test, expected_difference) { methods: "any" usebundle => dcs_if_diff_expected($(file1), $(file2), $(expected_difference), "dcs_check_diff_expected_pass_class", "dcs_check_diff_expected_fail_class"); reports: dcs_check_diff_expected_pass_class:: "$(test) Pass"; dcs_check_diff_expected_fail_class:: "$(test) FAIL"; } bundle agent dcs_if_diff_expected(file1, file2, expected_difference, pass_class, fail_class) { vars: DEBUG.check_ready.!no_difference:: "file1r" string => readfile("$(file1)", "4096"); "file2r" string => readfile("$(file2)", "4096"); (EXTRA|DEBUG_HEXDUMP).check_ready.!no_difference.has_hexdump:: "file1h" string => execresult("$(G.hexdump) -C $(file1)", "useshell"); "file2h" string => execresult("$(G.hexdump) -C $(file2)", "useshell"); (EXTRA|DEBUG_HEXDUMP).check_ready.!no_difference.!has_hexdump:: "file1h" string => execresult("$(G.od) -c $(file1)", "useshell"); "file2h" string => execresult("$(G.od) -c $(file2)", "useshell"); DEBUG.check_ready.!no_difference.has_unified_diff:: "diffu" string => execresult("$(G.diff_maybecolor) -u $(file2) $(file1) 2>$(G.dev_null)", "useshell"); DEBUG.check_ready.!no_difference.!has_unified_diff:: "diffu" string => execresult("$(G.diff_maybecolor) -c $(file2) $(file1) 2>$(G.dev_null)", "useshell"); classes: "has_unified_diff" expression => returnszero( "$(G.diff_maybecolor) -u $(G.etc_null) $(G.etc_null) >$(G.dev_null) 2>&1", "useshell"); "no_difference" expression => returnszero( "$(G.diff_maybecolor) $(file1) $(file2) >$(G.dev_null) 2>&1", "useshell"); "expected_difference" expression => strcmp("$(expected_difference)", "yes"); "check_ready" expression => "any"; check_ready.no_difference.!expected_difference:: "$(pass_class)" expression => "any", scope => "namespace"; check_ready.!no_difference.expected_difference:: "$(pass_class)" expression => "any", scope => "namespace"; check_ready.!no_difference.!expected_difference:: "$(fail_class)" expression => "any", scope => "namespace"; check_ready.no_difference.expected_difference:: "$(fail_class)" expression => "any", scope => "namespace"; reports: DEBUG.check_ready.!no_difference.!expected_difference:: "FILES DIFFER BUT SHOULD BE THE SAME"; "CONTENTS OF $(file1): $(file1r)"; "CONTENTS OF $(file2): $(file2r)"; "$(diffu)"; (DEBUG_HEXDUMP|EXTRA).check_ready.!no_difference.!expected_difference:: "hexdump $(file1): $(file1h)"; "hexdump $(file2): $(file2h)"; DEBUG.check_ready.no_difference.expected_difference:: "Contents of $(file1) and $(file) are the same but should differ."; EXTRA:: "Diff command: $(G.diff_maybecolor) -u $(file2) $(file1) 2>$(G.dev_null)"; } bundle agent dcs_sleep(t) { commands: "$(G.perl) -e 'sleep $(t)'"; reports: EXTRA:: "Sleeping $(t) seconds"; } ####################################################### # Uses rm -rf instead of selecting and deleting files to avoid side-effects in # tests due to problems in file deleletion promises. bundle agent dcs_fini(file) { commands: "$(G.rm) -rf $(file)*" contain => dcs_useshell; "$(G.rm) -rf $(sys.workdir)/state/cf_state.*" contain => dcs_useshell; reports: EXTRA:: "$(this.bundle): deleting $(file) with $(G.rm) -rf"; } bundle agent dcs_copyfile(from, to) { files: "$(to)" create => "true", copy_from => dcs_sync($(from)); reports: EXTRA:: "$(this.bundle): copying file $(from) to $(to)"; } body copy_from dcs_sync(f) { source => "$(f)"; purge => "true"; preserve => "false"; type_check => "false"; compare => "digest"; } body contain dcs_useshell { useshell => "true"; chdir => "/"; } bundle agent dcs_runagent(args) { commands: debug_mode:: "$(sys.cf_agent) -Kdf $(args)"; verbose_mode:: "$(sys.cf_agent) -Kvf $(args)"; inform_mode:: "$(sys.cf_agent) -KIf $(args)"; !debug_mode.!verbose_mode.!inform_mode:: "$(sys.cf_agent) -Kf $(args)"; } ####################################################### # Test based on whether two strings are the same bundle agent dcs_check_strcmp(strA, strB, test, expected_difference) { classes: "equal" expression => strcmp($(strA), $(strB)); "expected_difference" or => { strcmp($(expected_difference), "yes"), strcmp($(expected_difference), "true") }; "__passif" xor => { "equal", "expected_difference" }; reports: EXTRA|!__passif:: "$(this.bundle): STRING A: '$(strA)'"; "$(this.bundle): STRING B: '$(strB)'"; __passif:: "$(test) Pass"; !__passif:: "$(test) FAIL"; } ####################################################### # Test based on whether a string matches a regular expression bundle agent dcs_check_regcmp(regex, thestring, test, expected_mismatch) { classes: "matched" expression => regcmp($(regex), $(thestring)); "expected_mismatch" or => { strcmp($(expected_mismatch), "yes"), strcmp($(expected_mismatch), "true") }; "__passif" xor => { "equal", "expected_mismatch" }; reports: EXTRA|!__passif:: "$(this.bundle): REGEX: '$(regex)'"; "$(this.bundle): STRING TO MATCH: '$(thestring)'"; __passif:: "$(test) Pass"; !__passif:: "$(test) FAIL"; } ####################################################### # Pass the test if class bundle agent dcs_passif(classname, test) { reports: "$(test) Pass" ifvarclass => $(classname); "$(test) FAIL" ifvarclass => not($(classname)); EXTRA:: "$(this.bundle): passing based on class '$(classname)'" ifvarclass => $(classname); DEBUG:: "$(this.bundle): failing based on class '$(classname)'" ifvarclass => not($(classname)); } bundle agent dcs_pass(test) { reports: "$(test) Pass"; EXTRA:: "$(this.bundle): Explicitly passing..."; } bundle agent dcs_fail(test) { reports: "$(test) FAIL"; EXTRA:: "$(this.bundle): Explicitly failing..."; } bundle agent dcs_wait(test, seconds) { reports: "$(test) Wait/$(seconds)"; EXTRA:: "$(this.bundle): Explicitly waiting $(seconds) seconds..."; } bundle agent dcs_passif_fileexists(file, test) { classes: "__passif" expression => fileexists($(file)); methods: "" usebundle => dcs_passif("__passif", $(test)), inherit => "true"; reports: DEBUG.!__passif:: "$(this.bundle): $(file) did not exist!"; EXTRA.__passif:: "$(this.bundle): $(file) exists."; } bundle agent dcs_passif_file_absent(file, test) { classes: "__passif" not => fileexists($(file)); methods: "" usebundle => dcs_passif("__passif", $(test)), inherit => "true"; reports: DEBUG.__passif:: "$(this.bundle): $(file) did not exist."; EXTRA.!__passif:: "$(this.bundle): $(file) exists!"; } bundle agent dcs_passif_expected(expected, not_expected, test) { vars: "ex" slist => splitstring($(expected), ",", 1000); "notex" slist => splitstring($(not_expected), ",", 1000); "e[$(ex)]" string => $(ex); "e[$(notex)]" string => "!$(notex)"; "classes" slist => getvalues(e); classes: "__passif" and => { @(classes) }; methods: "" usebundle => dcs_passif("__passif", $(test)), inherit => "true"; reports: DEBUG:: "$(this.bundle): bad: $(ex) was NOT defined" ifvarclass => "!$(ex)"; "$(this.bundle): bad: $(notex) WAS defined" ifvarclass => "$(notex)"; EXTRA:: "$(this.bundle): good: $(ex) WAS defined" ifvarclass => "$(ex)"; "$(this.bundle): good: $(notex) was NOT defined" ifvarclass => "!$(notex)"; } ####################################################### bundle agent dcs_passif_output(wanted, unwanted, command, test) { vars: "subout" string => execresult($(command), "useshell"); classes: "__passif_output_unwanted" expression => regcmp($(unwanted), $(subout)); "__passif_output_wanted" expression => regcmp($(wanted), $(subout)); methods: "" usebundle => dcs_passif_expected("__passif_output_wanted", # expected "__passif_output_unwanted", # not expected $(test)), inherit => "true"; reports: DEBUG:: "$(this.bundle): bad: $(wanted) was NOT found in the output of $(command)" ifvarclass => "!__passif_output_wanted"; "$(this.bundle): bad: $(unwanted) WAS found in the output of $(command)" ifvarclass => "__passif_output_unwanted"; EXTRA:: "$(this.bundle): good: $(wanted) WAS found in the output of $(command)" ifvarclass => "__passif_output_wanted"; "$(this.bundle): good: $(unwanted) was NOT found in the output of $(command)" ifvarclass => "!__passif_output_unwanted"; DEBUG:: "$(this.bundle): the output of command '$(command)' was: $(subout)"; } bundle agent dcs_passif_output1(wanted, command, test) { methods: "" usebundle => dcs_passif_output($(wanted), # expected "^(unlikely data){400}$", # not expected $(command), $(test)), inherit => "true"; } cfengine-3.6.2/tests/acceptance/testall0000755000175100017510000006212012411032262017634 0ustar00a10038a1003800000000000000#!/bin/sh # # Copyright (C) CFEngine AS # # This file is part of CFEngine 3 - written and maintained by CFEngine AS. # # 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; version 3. # # 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 # # To the extent this program is licensed as part of the Enterprise # versions of CFEngine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # # Detect and replace non-POSIX shell # try_exec() { type "$1" > /dev/null 2>&1 && exec "$@" } unset foo (: ${foo%%bar}) 2> /dev/null T1="$?" if test "$T1" != 0; then try_exec /usr/xpg4/bin/sh "$0" "$@" echo "No compatible shell script interpreter found." echo "Please find a POSIX shell for your system." exit 42 fi # # Explicitly use POSIX tools if needed # if [ -f /usr/xpg4/bin/grep ]; then PATH=/usr/xpg4/bin:$PATH export PATH fi # # Unset environment variables which might break runinng acceptance tests # GREP_OPTIONS= export GREP_OPTIONS # # Defaults (overridden by command-line arguments) # LOG=test.log SUMMARY=summary.log XML=test.xml XMLTMP=xml.tmp WHOAMI=/c/Windows/System32/whoami.exe BASE_WORKDIR="$(pwd)/workdir" QUIET= TIMED_TESTS=${TIMED_TESTS:-1} CRASHING_TESTS=${CRASHING_TESTS:-1} STAGING_TESTS=${STAGING_TESTS:-0} NETWORK_TESTS=${NETWORK_TESTS:-1} UNSAFE_TESTS=${UNSAFE_TESTS:-0} LIBXML2_TESTS=${LIBXML2_TESTS:-1} NO_CLEAN=0 BASECLASSES="AUTO" EXTRACLASSES="DEBUG" VALGRIND_OPTS="--leak-check=full --show-reachable=yes --suppressions=valgrind-suppressions" # Use TEST_INDEX for indexing a poor man's array. Basically the subscript is # just appended to the variable name. TEST_INDEX=0 TEST_TIMED_INDEX=0 #TESTS_TIMED_=0 #TESTS_TIMEOUT_=0 #TESTS_PASSES_=0 TESTS_COUNT=0 TESTS_NORMAL_COUNT=0 TESTS_TIMED_COUNT=0 TESTS_TIMED_REMAINING=0 case "$OSTYPE" in msys) if "$WHOAMI" -priv | grep SeTakeOwnershipPrivilege > /dev/null; then # Don't use elevate if we already have the privileges. It is slower and # pops up a flashing window for every single test. DEFAULT_GAINROOT= else DEFAULT_GAINROOT="`dirname $0`/tool_wrappers/elevate.sh" fi # Use hardlinks on Windows. Using symbolic links will work, but Msys creates a # real copy, which eats disk space very quickly when you multiply with the number # of tests. LN_CMD="ln -f" ;; *) DEFAULT_GAINROOT=fakeroot LN_CMD="ln -sf" ;; esac GAINROOT=${GAINROOT:-$DEFAULT_GAINROOT} PASSED_TESTS=0 FAILED_TESTS=0 SUPPRESSED_FAILURES=0 SKIPPED_TESTS=0 # # Many older platforms don't support date +%s, so check for compatibility # and find Perl for the unix_seconds() routine below. (Mantis #1254) # HAVE_DATE_PCT_S= date +%s | grep %s >/dev/null 2>&1 if [ $? -ne 0 ] ; then HAVE_DATE_PCT_S=1 fi PERL=`which perl 2>/dev/null` # color! if [ "${CFENGINE_COLOR}" = "1" ]; then COLOR_SUCCESS="\\033[1;32m" COLOR_FAILURE="\\033[1;31m" COLOR_WARNING="\\033[1;33m" COLOR_NORMAL="\\033[0;39m" else COLOR_SUCCESS= COLOR_FAILURE= COLOR_WARNING= COLOR_NORMAL= fi # # Obtain UNIX time(), using date +%s, Perl, or POSIX-compatible approach. # unix_seconds() { if [ "$HAVE_DATE_PCT_S" ]; then date +%s return 0 fi if [ "$PERL" ]; then $PERL -e 'print time() . "\n"' 2>/dev/null if [ $? -eq 0 ] ; then return 0 fi fi # Last resort if Perl fails - the extended cpio interchange format has # the file modification timestamp in columns 48-59, in octal. : > $BASE_WORKDIR/x echo "ibase=8;$(pax -wx cpio $BASE_WORKDIR/$$.seconds | cut -c 48-59)" | bc 2>/dev/null rm $BASE_WORKDIR/x } # echo # echo === Test environment: === # echo AGENT=$AGENT # echo CF_PROMISES=$CF_PROMISES # echo CF_SERVERD=$CF_SERVERD # echo CF_KEY=$CF_KEY # echo ========================= # echo usage() { echo "testall [-h|--help] [-q|--quiet] [--gainroot=] [--agent=] [--cfpromises=] [--cfserverd=] [--cfkey=] [--bindir=] [--staging] [--unsafe] [--no-network] [--gdb] [--printlog] [ ...]" echo echo "If no test is given, all standard tests are run:" echo " Tests with names of form .cf are expected to run succesfully" echo " Tests with names of form .x.cf are expected to crash" echo "Set ${COLOR_SUCCESS}CFENGINE_COLOR=1${COLOR_NORMAL} to get ANSI color markers where appropriate." echo echo "If arguments are given, those are executed as tests" echo echo " -h" echo " --help prints usage" echo " -q" echo " --quiet makes script much quieter" echo " --gainroot= forces use of command to gain root privileges," echo " otherwise fakeroot is used. Use --gainroot=env to make this" echo " option a no-op (e.g. you're running inside fakeroot already)" echo " --agent provides a way to specify non-default cf-agent location," echo " and defaults to $DEFAGENT." echo " --baseclasses provides a way to override the default cf-agent classes," echo " and defaults to ${BASECLASSES}. Also can use --bc" echo " --extraclasses provides a way to append to the default cf-agent classes," echo " and defaults to ${EXTRACLASSES}. Also can use --ec" echo " --cfpromises provides a way to specify non-default cf-promises location," echo " and defaults to $DEFCF_PROMISES." echo " --cfserverd provides a way to specify non-default cf-serverd location," echo " and defaults to $DEFCF_SERVERD." echo " --cfkey provides a way to specify non-default cf-key location," echo " and defaults to $DEFCF_KEY." echo " --bindir specifies the directory containing all the binaries." echo " Mutually exclusive with --agent and --cf* arguments." echo " --libtool specify non-default libtool location (only needed for --gdb)." echo " defaults to $DEFLIBTOOL." echo " --staging enable tests in staging directories. They are not expected to pass." echo " --unsafe enable tests in unsafe directories. WARNING! These tests modify the" echo " system they're running on and can DAMAGE YOUR SYSTEM! DO NOT use" echo " this option without a backup." echo " If you use this option you should also use --gainroot=sudo," echo " otherwise you will get incorrect results." echo " --no-network disable tests in network directories." echo " --no-libxml2 disable tests involving xml file editing." echo " --no-crashing disable tests that are expected to crash (for use with valgrind)." echo " --no-timed disable timed tests that may introduce wait times." echo " --printlog print the full test.log output immediately. Override with $PRINTLOG" echo " --gdb Run test under GDB" echo " --valgrind Run test under Valgrind" echo " --callgrind Run test under valgrind --tool=callgrind" echo " --no-clean does not clean workdir after test finishes" echo " (by default it gets cleaned only if test passed)." } # Takes the following arguments: # 1. Agent - The agent to execute. # 2. Test - The test to execute. # 3. Pass number - [Optional] The current pass number. Used by timed tests. # 4. Timeout variable - [Optional] The name of the variable to put the next # timeout into. Used by timed tests. runtest() { # Clear local variables unset AGENT TEST EXPECTED_CRASH SKIP SKIPREASON RESULT RESULT_MSG TEST_START_TIME FLATNAME WORKDIR OUTFILE AGENT="$1" TEST="$2" PASS_NUM="$3" NEXT_TIMEOUT_VAR="$4" if [ -z "$QUIET" ]; then printf "$TEST " fi if echo "$TEST" | fgrep -e .x.cf > /dev/null; then EXPECTED_CRASH=1 else EXPECTED_CRASH= fi if [ "x$CRASHING_TESTS" = "x0" ] && [ "x$EXPECTED_CRASH" = "x1" ]; then SKIP=1 SKIPREASON="${COLOR_WARNING}Crashing tests are disabled${COLOR_NORMAL}" elif [ "x$STAGING_TESTS" = "x0" ] && echo "$TEST" | grep '/staging/' > /dev/null; then SKIP=1 SKIPREASON="${COLOR_WARNING}Staging tests are disabled${COLOR_NORMAL}" elif [ "x$UNSAFE_TESTS" != "x1" ] && echo "$TEST" | grep '/unsafe/' > /dev/null; then SKIP=1 SKIPREASON="${COLOR_WARNING}Unsafe tests are disabled${COLOR_NORMAL}" elif [ "x$NETWORK_TESTS" = "x0" ] && echo "$TEST" | grep '/network/' > /dev/null; then SKIP=1 SKIPREASON="${COLOR_WARNING}Network-dependent tests are disabled${COLOR_NORMAL}" elif [ "x$LIBXML2_TESTS" = "x0" ] && echo "$TEST" | grep '/11_xml_edits/' > /dev/null; then SKIP=1 SKIPREASON="XML file editing tests are disabled" else SKIP= SKIPREASON= fi ( echo ---------------------------------------------------------------------- echo "$TEST"${EXPECTED_CRASH:+ \(expected to crash\)}${SKIPREASON:+ \($SKIPREASON\)} echo ---------------------------------------------------------------------- ) >> "$LOG" TEST_START_TIME=$(unix_seconds) if [ -n "$NEXT_TIMEOUT_VAR" ]; then eval $NEXT_TIMEOUT_VAR= fi if [ -n "$SKIP" ]; then TEST_END_TIME=$TEST_START_TIME RESULT=Skip RESULT_MSG="${COLOR_WARNING}Skipped ($SKIPREASON)${COLOR_NORMAL}" else FLATNAME="$(echo "$TEST" | sed 's,[./],_,g')" # Prepare workdir WORKDIR="$BASE_WORKDIR/$FLATNAME" OUTFILE=$WORKDIR/test.log if [ -z "$PASS_NUM" ] || [ "$PASS_NUM" -eq 1 ]; then # Don't reset workdir if this is a subsequent pass. $GAINROOT rm -rf "$WORKDIR" mkdir -p "$WORKDIR/bin" "$WORKDIR/tmp" chmod ugo+rwxt "$WORKDIR/tmp" if [ -n "$BINDIR" ]; then # Copy everything, because Windows depends on DLLs. $LN_CMD "$BINDIR"/* "$WORKDIR/bin" else $LN_CMD "$AGENT" "$WORKDIR/bin" $LN_CMD "$CF_PROMISES" "$WORKDIR/bin" $LN_CMD "$CF_SERVERD" "$WORKDIR/bin" $LN_CMD "$CF_KEY" "$WORKDIR/bin" fi fi if uname | grep MINGW > /dev/null; then PLATFORM_WORKDIR="$(echo $WORKDIR | sed -e 's%^/\([a-cA-Z]\)/%\1:/%' | sed -e 's%/%\\%g')" DS="\\" else PLATFORM_WORKDIR="$WORKDIR" DS="/" fi echo "#!/bin/sh CFENGINE_TEST_OVERRIDE_WORKDIR=\"$PLATFORM_WORKDIR\" TEMP=\"$PLATFORM_WORKDIR${DS}tmp\" CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR=\"$CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR\" export CFENGINE_TEST_OVERRIDE_WORKDIR TEMP CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR " > "$WORKDIR/runtest" if [ "$GDB" = 1 ]; then if grep libtool < "$AGENT" > /dev/null; then printf "\"$LIBTOOL\" --mode=execute " >> "$WORKDIR/runtest" fi printf "gdb --args " >> "$WORKDIR/runtest" fi if [ -n "$USE_VALGRIND" ] && [ x"$EXPECTED_CRASH" = "x" ]; then if grep libtool < "$AGENT" > /dev/null; then printf "\"$LIBTOOL\" --mode=execute " >> "$WORKDIR/runtest" fi printf "valgrind ${VALGRIND_OPTS} \"$AGENT\" $VERBOSE -Kf \"$TEST\" -D ${PASS_NUM:+test_pass_$PASS_NUM,}${BASECLASSES},${EXTRACLASSES} 2>&1\n" >> "$WORKDIR/runtest" else printf "\"$AGENT\" $VERBOSE -Kf \"$TEST\" -D ${PASS_NUM:+test_pass_$PASS_NUM,}${BASECLASSES},${EXTRACLASSES}\n" >> "$WORKDIR/runtest" fi chmod +x "$WORKDIR/runtest" if [ "$GDB" = 1 ]; then $GAINROOT "$WORKDIR/runtest" else eval $GAINROOT "$WORKDIR/runtest" >$OUTFILE 2>&1 fi RETVAL=$? cat $OUTFILE >> "$LOG" echo >> "$LOG" echo "Return code is $RETVAL." >> "$LOG" TEST_END_TIME=$(unix_seconds) RESULT_MSG= if [ -z "$EXPECTED_CRASH" ] && [ $RETVAL -ne 0 ]; then RESULT=FAIL elif [ -z "$EXPECTED_CRASH" ]; then # We need to be careful when matching test outcomes. Because of convergence # passes, a test may output FAIL before it outputs Pass; in this case the # latter trumps the former. Also be careful when matching an XFAIL; the # test should not be allowed to output any other outcome in the same run, # except for FAIL. # Some states are output by dcs.cf.sub, therefore check for both TEST # prefix and dcs.cf.sub prefix. ESCAPED_TEST="$(echo "($TEST|dcs.cf.sub)" | sed -e 's/\./\\./g')" if egrep -e "R: .*$ESCAPED_TEST XFAIL" $OUTFILE > /dev/null; then # Check for other test case outcomes than fail. Should not happen. if egrep -e "R: .*$ESCAPED_TEST " $OUTFILE | egrep -v -e "R: .*$ESCAPED_TEST X?FAIL" > /dev/null; then RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (Tried to suppress nonexistent failure)${COLOR_NORMAL}" else REDMINE="$(egrep -e "R: .*$ESCAPED_TEST XFAIL" $OUTFILE | sed -e "s,.*XFAIL/redmine\([0-9][0-9]*\).*,\1,")" RESULT=XFAIL RESULT_MSG="${COLOR_WARNING}FAIL (Suppressed, Redmine #$REDMINE)${COLOR_NORMAL}" fi elif egrep -e "R: .*$ESCAPED_TEST FAIL/no_redmine_number" $OUTFILE > /dev/null; then RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (Tried to suppress failure, but no Redmine issue number is provided)${COLOR_NORMAL}" elif egrep -e "R: .*$ESCAPED_TEST Wait/[0-9]+" $OUTFILE > /dev/null; then if [ -z "$NEXT_TIMEOUT_VAR" ]; then RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL (Test tried to wait but is not in \"timed\" directory)${COLOR_NORMAL}" else WAIT_TIME=$(egrep -e "R: .*$ESCAPED_TEST Wait/[0-9]+" $OUTFILE | sed -e 's,.*Wait/\([0-9][0-9]*\).*,\1,') eval $NEXT_TIMEOUT_VAR=$(($TEST_END_TIME+$WAIT_TIME)) RESULT=Wait RESULT_MSG="Awaiting ($WAIT_TIME seconds)..." fi elif egrep -e "R: .*$ESCAPED_TEST Pass" $OUTFILE > /dev/null; then RESULT=Pass RESULT_MSG="${COLOR_SUCCESS}Pass${COLOR_NORMAL}" elif egrep -e "R: .*$ESCAPED_TEST Skip/unsupported" $OUTFILE > /dev/null; then RESULT=Skip RESULT_MSG="${COLOR_WARNING}Skipped (No platform support)${COLOR_NORMAL}" elif egrep -e "R: .*$ESCAPED_TEST Skip/needs_work" $OUTFILE > /dev/null; then RESULT=Skip RESULT_MSG="${COLOR_WARNING}Skipped (Test needs work)${COLOR_NORMAL}" else RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAIL${COLOR_NORMAL}" fi else if [ $RETVAL -ne 0 ]; then RESULT=Pass RESULT_MSG="${COLOR_SUCCESS}Pass${COLOR_NORMAL}" else RESULT=FAIL RESULT_MSG="${COLOR_FAILURE}FAILed to crash${COLOR_NORMAL}" fi fi if [ "x$RESULT_MSG" = "x" ]; then RESULT_MSG=$RESULT fi if [ "$RESULT" = "FAIL" ] && [ -e .succeeded/"$FLATNAME" ]; then RESULT_MSG="${COLOR_FAILURE}$RESULT_MSG (UNEXPECTED FAILURE)${COLOR_NORMAL}" fi fi if [ "$RESULT" = "XFAIL" ]; then echo " > "$XMLTMP" echo " classname=\"$TEST $RESULT_MSG\"" >> "$XMLTMP" echo " time=\"$(($TEST_END_TIME - $TEST_START_TIME)) seconds\">" >> "$XMLTMP" elif [ "$RESULT" != Wait ]; then echo " > "$XMLTMP" echo " classname=\"$TEST\"" >> "$XMLTMP" echo " time=\"$(($TEST_END_TIME - $TEST_START_TIME)) seconds\">" >> "$XMLTMP" fi case "$RESULT" in Pass) echo $RESULT $TEST >> "$SUMMARY" PASSED_TESTS=$(($PASSED_TESTS + 1)) mkdir -p '.succeeded' touch .succeeded/"$FLATNAME" ;; FAIL|XFAIL) echo $RESULT $TEST >> "$SUMMARY" ( echo " " cat $OUTFILE | sed -e "s/&/\&/g; s//\>/g; s/'/\"/g" echo " " ) >> "$XMLTMP" FAILED_TESTS=$(($FAILED_TESTS + 1)) if [ "$RESULT" = "XFAIL" ]; then SUPPRESSED_FAILURES=$(($SUPPRESSED_FAILURES + 1)) fi ;; Skip) echo $RESULT $TEST >> "$SUMMARY" ( echo " " echo " " ) >> "$XMLTMP" SKIPPED_TESTS=$(($SKIPPED_TESTS + 1)) ;; esac if [ "$RESULT" != Wait ]; then echo " " >> "$XMLTMP" fi if [ "$RESULT" != "FAIL" -a "$RESULT" != "Wait" -a "$NO_CLEAN" = "0" ]; then $GAINROOT rm -rf "$WORKDIR" fi if [ -z "$QUIET" ]; then echo $RESULT_MSG else if [ "$RESULT" = Pass ]; then printf '.' elif [ "$RESULT" = Skip ]; then printf '-' elif [ "$RESULT" = FAIL ]; then if [ -n "$EXPECTED_CRASH" ]; then printf '!' else printf 'x' fi fi fi ( echo echo ' ==>' "$RESULT_MSG" echo ) >> "$LOG" } ORIG_ARGS= while true; do case "$1" in -h|--help) usage exit;; -q|--quiet) QUIET=1;; --gainroot=*) GAINROOT=${1#--gainroot=};; --valgrind) USE_VALGRIND=1;; --callgrind) USE_VALGRIND=1; VALGRIND_OPTS="--suppressions=valgrind-suppressions --tool=callgrind";; --staging) STAGING_TESTS=1;; --unsafe) UNSAFE_TESTS=1;; --no-network) NETWORK_TESTS=0;; --no-libxml2) LIBXML2_TESTS=0;; --no-crashing) CRASHING_TESTS=0;; --no-timed) TIMED_TESTS=0;; --agent=*) AGENT=${1#--agent=};; --baseclasses=*) BASECLASSES=${1#--baseclasses=};; --bc=*) BASECLASSES=${1#--bc=};; --extraclasses=*) EXTRACLASSES=${1#--extraclasses=};; --ec=*) EXTRACLASSES=${1#--ec=};; --cfpromises=*) CF_PROMISES=${1#--cfpromises=};; --cfserverd=*) CF_SERVERD=${1#--cfserverd=};; --cfkey=*) CF_KEY=${1#--cfkey=};; --bindir=*) BINDIR=${1#--bindir=};; --libtool=*) LIBTOOL=${1#--libtool=};; --printlog) PRINTLOG=1;; --gdb) GDB=1;; --no-clean) NO_CLEAN=1;; -*) echo "Unknown option: $1" exit 1;; *) break;; esac # Make sure spaces are preserved by escaping them. ORIG_ARGS="$ORIG_ARGS $(echo "$1" | sed -e 's/ /\\ /g')" shift done if [ "$OSTYPE" = "msys" ] && [ "$TESTALL_DO_NOT_RECURSE" != 1 ] && ! "$WHOAMI" -priv | grep SeTakeOwnershipPrivilege > /dev/null; then # On Windows we run the entire test run under GAINROOT, because doing it for # each test is horribly slow. echo "export GAINROOT=" > runtests.sh echo "export TESTALL_DO_NOT_RECURSE=1" >> runtests.sh echo "export VERBOSE='$VERBOSE'" >> runtests.sh echo "$0 $ORIG_ARGS $@ &" >> runtests.sh # Note quote change. We want to keep below variables unexpanded. echo 'trap "kill $!" INT' >> runtests.sh echo 'trap "kill $!" TERM' >> runtests.sh # Traps do not fire during commands, but *do* fire during wait. echo 'wait $!' >> runtests.sh $GAINROOT "./runtests.sh" exit $? fi if [ -n "$AGENT" -o -n "$CF_PROMISES" -o -n "$CF_SERVERD" -o -n "$CF_KEY" ]; then if [ -n "$BINDIR" ]; then echo "--bindir is mutually exclusive with --agent and --cf* arguments" exit 2 fi fi # We assume we're running this script from $objdir, $objdir/tests/acceptance, # or /var/cfengine/tests/acceptance. find_default_binary() { [ -n "$BINDIR" -a -x "$BINDIR/$2" ] && eval $1=\""$BINDIR/$2"\" [ -x "`pwd`/$2/$2" ] && eval $1=\""`pwd`/$2/$2"\" [ -x "`pwd`/../../$2/$2" ] && eval $1=\""`pwd`/../../$2/$2"\" [ -x "`pwd`/../../bin/$2" ] && eval $1=\""`pwd`/../../bin/$2"\" } find_default_binary DEFAGENT cf-agent find_default_binary DEFCF_PROMISES cf-promises find_default_binary DEFCF_SERVERD cf-serverd find_default_binary DEFCF_KEY cf-key [ -x "`pwd`/libtool" ] && DEFLIBTOOL="`pwd`/libtool" [ -x "`pwd`/../../libtool" ] && DEFLIBTOOL="`pwd`/../../libtool" AGENT=${AGENT:-${DEFAGENT}} CF_PROMISES=${CF_PROMISES:-${DEFCF_PROMISES}} CF_SERVERD=${CF_SERVERD:-${DEFCF_SERVERD}} CF_KEY=${CF_KEY:-${DEFCF_KEY}} LIBTOOL=${LIBTOOL:-${DEFLIBTOOL}} if [ ! -x "$AGENT" -o ! -x "$CF_PROMISES" -o ! -x "$CF_SERVERD" -o ! -x "$CF_KEY" ] then echo "ERROR can't find cf-agent or other binary. Are you sure you're running this from OBJDIR or OBJDIR/tests/acceptance? Check '$AGENT', '$CF_PROMISES', '$CF_SERVERD', and '$CF_KEY'" exit 1 fi if [ "$UNSAFE_TESTS" = "1" ]; then if [ "$GAINROOT" = "fakeroot" ]; then echo "Unsafe tests do not play well together with fakeroot. Please use a different" echo "--gainroot (like \"sudo\"), or you will get incorrect results." exit 1 fi # Make sure test dir is accessible to everyone, because unsafe tests may # switch user during the test (users promises do this). DIR="$(cd "$(dirname "$0")"; pwd)" while [ "$DIR" != "/" -a "$DIR" != "" ]; do $GAINROOT chmod go+rx "$DIR" DIR="$(dirname "$DIR")" done fi if [ $# -gt 0 ]; then # We run all specified tests according to the defaults (no unsafe ones). for test in "$@"; do if ! expr "$test" : '[/.]' >/dev/null; then test="./$test" fi if [ -f $test ]; then ADDTESTS="$ADDTESTS${ADDTESTS:+ }$test" elif [ -d $test ]; then ADDTESTS="$ADDTESTS${ADDTESTS:+ }$(find "$test" -name '*.cf' | sort)" else echo "Unable to open test file/directory: $test" fi done else ADDTESTS="$ADDTESTS${ADDTESTS:+ }$(find . -name '*.cf' | sort)" fi for addtest in $ADDTESTS; do if echo "$addtest" | fgrep "/timed/" > /dev/null; then if [ "$TIMED_TESTS" = 1 ]; then eval TESTS_TIMED_$TEST_TIMED_INDEX="$addtest" eval TESTS_TIMEOUT_$TEST_TIMED_INDEX=0 eval TESTS_PASSES_$TEST_TIMED_INDEX=0 TEST_TIMED_INDEX=$(($TEST_TIMED_INDEX+1)) fi else eval TESTS_$TEST_INDEX="$addtest" TEST_INDEX=$(($TEST_INDEX+1)) fi done # # fd 7 is a /dev/null for quiet execution and stdout for default one # if [ -z "$QUIET" ]; then exec 7>&1 else exec 7>/dev/null fi # # Now run the tests # TESTS_NORMAL_COUNT=$TEST_INDEX TESTS_TIMED_COUNT=$TEST_TIMED_INDEX TESTS_COUNT=$(($TESTS_NORMAL_COUNT + $TESTS_TIMED_COUNT)) TESTS_TIMED_REMAINING=$TEST_TIMED_INDEX START_TIME=$(unix_seconds) ( echo ====================================================================== echo Testsuite started at $(date "+%Y-%m-%d %T") echo ---------------------------------------------------------------------- echo Total tests: $TESTS_COUNT echo if [ ${CRASHING_TESTS} -ne 0 ]; then echo CRASHING_TESTS: enabled else echo CRASHING_TESTS: disabled fi if [ ${NETWORK_TESTS} -ne 0 ]; then echo NETWORK_TESTS: enabled else echo NETWORK_TESTS: disabled fi if [ ${STAGING_TESTS} -ne 0 ]; then echo STAGING_TESTS: enabled else echo STAGING_TESTS: disabled fi if [ ${UNSAFE_TESTS} -ne 0 ]; then echo UNSAFE_TESTS: enabled else echo UNSAFE_TESTS: disabled fi if [ ${LIBXML2_TESTS} -ne 0 ]; then echo LIBXML2_TESTS: enabled else echo LIBXML2_TESTS: disabled fi echo ) | tee "$LOG" | tee "$SUMMARY" >&7 ( echo "" echo " "$XML" echo -n "" > "$XMLTMP" check_and_run_timed_tests() { TEST_TIMED_INDEX=0 time=$(unix_seconds) # Run timed tests if any deadlines have expired. while [ $TEST_TIMED_INDEX -lt $TESTS_TIMED_COUNT ]; do eval test=\$TESTS_TIMED_$TEST_TIMED_INDEX eval timeout=\$TESTS_TIMEOUT_$TEST_TIMED_INDEX if [ -n "$timeout" ] && [ "$time" -ge "$timeout" ]; then eval TESTS_PASSES_$TEST_TIMED_INDEX="\$((\$TESTS_PASSES_$TEST_TIMED_INDEX+1))" eval pass=\$TESTS_PASSES_$TEST_TIMED_INDEX runtest "$AGENT" "$test" "$pass" "TESTS_TIMEOUT_$TEST_TIMED_INDEX" eval timeout=\$TESTS_TIMEOUT_$TEST_TIMED_INDEX if [ -z "$timeout" ]; then TESTS_TIMED_REMAINING=$(($TESTS_TIMED_REMAINING - 1)) fi fi TEST_TIMED_INDEX=$(($TEST_TIMED_INDEX+1)) done } TEST_INDEX=0 while [ $TEST_INDEX -lt $TESTS_NORMAL_COUNT -o $TESTS_TIMED_REMAINING -gt 0 ]; do check_and_run_timed_tests # Run normal test. if [ $TEST_INDEX -lt $TESTS_NORMAL_COUNT ]; then eval test=\$TESTS_$TEST_INDEX runtest "$AGENT" "$test" TEST_INDEX=$(($TEST_INDEX+1)) elif [ $TESTS_TIMED_REMAINING -gt 0 ]; then sleep 1 fi done END_TIME=$(unix_seconds) ( echo echo ====================================================================== echo "Testsuite finished at $(date "+%F %T") ($(($END_TIME - $START_TIME)) seconds)" ) | tee -a "$LOG" | tee -a "$SUMMARY" >&7 ( echo echo Passed tests: $PASSED_TESTS echo -n Failed tests: $FAILED_TESTS if [ $SUPPRESSED_FAILURES -gt 0 ]; then echo " ($SUPPRESSED_FAILURES are known and suppressed)" else echo fi echo Skipped tests: $SKIPPED_TESTS echo Total tests: $TESTS_COUNT ) | tee -a "$LOG" | tee -a "$SUMMARY" ( echo " failures=\"$FAILED_TESTS\"" echo " skipped=\"$SKIPPED_TESTS\"" echo " time=\"$(($END_TIME - $START_TIME)) seconds\">" ) >> "$XML" cat "$XMLTMP" >> "$XML" echo "" >> "$XML" if [ -n "$PRINTLOG" ]; then cat "$LOG" fi if [ "$FAILED_TESTS" -gt "$SUPPRESSED_FAILURES" ]; then exit 1 else exit 0 fi cfengine-3.6.2/tests/acceptance/08_commands/0000755000175100017510000000000012353264455020365 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/08_commands/03_shells/0000755000175100017510000000000012316547775022171 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/08_commands/03_shells/tryshell.cf.sub0000644000175100017510000000402012316547775025135 0ustar00a10038a1003800000000000000####################################################### # # Test command useshell parameters # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { "init", "test" }; version => "1.0"; } ####################################################### bundle agent init { vars: "origtestdir" string => dirname("$(this.promise_filename)"); } ####################################################### bundle agent test { classes: "shelltype_noshell" or => { "useshell_noshell", "useshell_false", "useshell_no", "useshell_off" }; "shelltype_useshell" or => { "useshell_useshell", "useshell_true", "useshell_yes", "useshell_on" }; "shelltype_powershell" or => { "useshell_powershell" }; vars: useshell_true:: "shelltype" string => "true"; useshell_false:: "shelltype" string => "false"; useshell_yes:: "shelltype" string => "yes"; useshell_no:: "shelltype" string => "no"; useshell_on:: "shelltype" string => "on"; useshell_off:: "shelltype" string => "off"; useshell_noshell:: "shelltype" string => "noshell"; useshell_useshell:: "shelltype" string => "useshell"; useshell_powershell:: "shelltype" string => "powershell"; shelltype_noshell.windows:: "shellcmd" string => "c:\windows\system32\cmd.exe /C type"; shelltype_noshell.!windows:: "shellcmd" string => "/bin/cat"; shelltype_useshell.windows:: "shellcmd" string => "type"; shelltype_useshell.!windows:: "shellcmd" string => "cat"; shelltype_powershell:: "shellcmd" string => "Get-Content"; classes: "shell_specified" or => { "shelltype_noshell", "shelltype_useshell", "shelltype_powershell" }; commands: shell_specified:: "$(shellcmd) $(init.origtestdir)$(const.dirsep)text.txt" contain => shelltype; reports: !shell_specified:: "No shell type specified!"; } body contain shelltype { useshell => "$(test.shelltype)"; } cfengine-3.6.2/tests/acceptance/08_commands/03_shells/shelltypes.cf0000644000175100017510000000335712316547775024707 0ustar00a10038a1003800000000000000####################################################### # # Test command useshell parameters # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "origtestdir" string => dirname("$(this.promise_filename)"); "shelltypes" slist => { "useshell_true", "useshell_false", "useshell_yes", "useshell_no", "useshell_on", "useshell_off", "useshell_noshell", "useshell_useshell", "useshell_powershell" }; } ####################################################### bundle agent test { classes: "$(init.shelltypes)" expression => regcmp(".*(Succeeded|Powershell is only supported on Windows).*", execresult("$(sys.cf_agent) -D $(init.shelltypes) -Kf $(init.origtestdir)$(const.dirsep)tryshell.cf.sub", "noshell")); "ok" and => { "@(init.shelltypes)" }; vars: ok:: "ok" string => "ok"; reports: DEBUG:: "$(init.shelltypes) test failed" ifvarclass => "!$(init.shelltypes)"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("$(test.ok)", "ok"); reports: DEBUG:: "Tests powershell in commands promises."; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL "; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/03_shells/text.txt0000644000175100017510000000001212236160673023674 0ustar00a10038a1003800000000000000Succeeded cfengine-3.6.2/tests/acceptance/08_commands/02_syntax/0000755000175100017510000000000012236160673022211 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/08_commands/02_syntax/staging/0000755000175100017510000000000012243421446023641 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/08_commands/02_syntax/staging/001.cf0000644000175100017510000000353612243421446024462 0ustar00a10038a1003800000000000000####################################################### # # Test that backslashes are correctly passed to commands (Issue 471) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true", edit_defaults => empty, edit_line => setup_lines; } body edit_defaults empty { empty_file_before_editing => "true"; } bundle edit_line setup_lines { insert_lines: "a test"; "a.test"; "nottest"; } ####################################################### bundle agent test { vars: "all_lines" string => execresult("$(G.egrep) -c '.' $(G.testfile)", "useshell"); "re_lines" string => execresult("$(G.egrep) -c 'a.test' $(G.testfile)", "useshell"); "lit_lines" string => execresult("$(G.egrep) -c 'a\.test' $(G.testfile)", "useshell"); "doubleslash_lit_lines" string => execresult("$(G.egrep) -c 'a\\.test' $(G.testfile)", "useshell"); } ####################################################### bundle agent check { classes: "ok" and => { strcmp("$(test.all_lines)", "3"), strcmp("$(test.re_lines)", "2"), strcmp("$(test.lit_lines)", "1"), strcmp("$(test.doubleslash_lit_lines)", "1") }; reports: DEBUG:: "all_lines: $(test.all_lines) =?= 3"; "re_lines: $(test.re_lines) =?= 2"; "lit_lines: $(test.lit_lines) =?= 1"; "doubleslash_lit_lines: $(test.doubleslash_lit_lines) =?= 1"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/staging/0000755000175100017510000000000012353264455022021 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/08_commands/staging/default_failed_returncodes.cf0000644000175100017510000000274512353264455027710 0ustar00a10038a1003800000000000000body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; } bundle agent test { commands: "/bin/false" classes => scoped_classes_generic("namespace", "default"), comment => "Test that by default non zero commands return promise failure"; "/bin/false" classes => scoped_classes_generic_kept_0("namespace", "specify_kept"), comment => "Test that when specifying kept returncodes that failures are still registered"; } bundle agent check { methods: "report" usebundle => dcs_passif_expected("default_not_kept,specify_kept_not_kept", "", "$(this.promise_filename)") inherit => "true"; } body classes scoped_classes_generic_kept_0(scope, x) { scope => "$(scope)"; promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached" }; repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached" }; kept_returncodes => { "0" }; #repaired_returncodes => { "2" }; #failed_returncodes => { "1" }; } cfengine-3.6.2/tests/acceptance/08_commands/01_modules/0000755000175100017510000000000012404565361022332 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/08_commands/01_modules/set-tags.cf.txt0000644000175100017510000000044612404565361025215 0ustar00a10038a1003800000000000000^context=xyz ^meta=xyz,abc=def,,??what is this?? +myclass =myvar=hello there @mylist={"abc", "def", "ghi"} @myalist={"{{abc}}", " ' def}", "ghi'''"} ^meta=1,2,3 @myblist={'{{a,bc}}', ' " de,f}', 'gh,,i"""'} +mybclass ^meta=a,b,c @myclist={"{{a'bc',,}}", ' ",, d"ef}', "ghi,},'''"} +mycclass cfengine-3.6.2/tests/acceptance/08_commands/01_modules/004.cf.txt0000644000175100017510000000026112404565361023764 0ustar00a10038a1003800000000000000@mylist={"abc", "def", "ghi"} @myalist={"{{abc}}", " ' def}", "ghi'''"} @myblist={'{{a,bc}}', ' " de,f}', 'gh,,i"""'} @myclist={"{{a'bc',,}}", ' ",, d"ef}', "ghi,},'''"} cfengine-3.6.2/tests/acceptance/08_commands/01_modules/set-context.cf0000644000175100017510000000642412353264455025132 0ustar00a10038a1003800000000000000####################################################### # # Test command modules # Redmine#3991: support data containers # ####################################################### body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_name" string => "$(this.promise_filename).txt"; } ####################################################### bundle agent test { commands: "$(G.cat) $(init.script_name)" contain => in_shell, module => "true"; } ####################################################### bundle agent check { vars: "list0" slist => {"abc", "def", "ghi"}; "list1" slist => {"{{abc}}", " ' def}", "ghi'''"}; "list2" slist => {'{{a,bc}}', ' " de,f}', 'gh,,i"""'}; "list3" slist => {"{{a'bc',,}}", ' ",, d"ef}', "ghi,},'''"}; "actual0" string => join(":", "list0"); "actual1" string => join(":", "list1"); "actual2" string => join(":", "list2"); "actual3" string => join(":", "list3"); "joined0" string => join(":", "xyz_123___456.mylist"); "joined1" string => join(":", "xyz_123___456.myalist"); "joined2" string => join(":", "xyz_123___456.myblist"); "joined3" string => join(":", "xyz_123___456.myclist"); "c" slist => { "1", "2", "3", "4", "5", "6" }; "c$(c)" string => format("%S", "xyz_123___456.mycontainer$(c)"); "e1" string => '{"x":[456,789]}'; "e5" string => '["read","some","strings"]'; "e6" string => '{"mix":["match"],"ping":"pong","paddle":true,"nothing":null}'; "hello_contexts" slist => { "xyz_123___456", "_456", "456", "_", "a__456__", "__a__", }; classes: any:: "var0ok" expression => strcmp("${this.joined0}" , "${this.actual0}"); "var1ok" expression => strcmp("${this.joined1}" , "${this.actual1}"); "var2ok" expression => strcmp("${this.joined2}" , "${this.actual2}"); "var3ok" expression => strcmp("${this.joined3}" , "${this.actual3}"); "var4ok" expression => strcmp("hello there" , "${xyz_123___456.myvar}"); "hello_$(hello_contexts)_ok" expression => strcmp("hello there" , "${$(hello_contexts).myvar}"); "ok_c1" expression => strcmp($(e1) , $(c1)); "ok_c2" not => isvariable("c2"); "ok_c3" not => isvariable("c3"); "ok_c4" not => isvariable("c4"); "ok_c5" expression => strcmp($(e5) , $(c5)); "ok_c6" expression => strcmp($(e6) , $(c6)); "ok" and => { "myclass", "var0ok", "var1ok", "var2ok", "var3ok", "var4ok", "hello_xyz_123___456_ok", "hello__456_ok", "hello_456_ok", "hello___ok", "hello_a__456___ok", "hello___a___ok", "ok_c1", "ok_c2", "ok_c3", "ok_c4", "ok_c5", "ok_c6" }; reports: DEBUG:: "container $(c): $(e$(c)) != $(c$(c))" ifvarclass => "!ok_c$(c)"; "context $(hello_contexts) failed" ifvarclass => "!hello_$(hello_contexts)_ok"; EXTRA:: "context $(hello_contexts) worked" ifvarclass => "hello_$(hello_contexts)_ok"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/module-array-indexing.cf0000644000175100017510000000257012332665147027057 0ustar00a10038a1003800000000000000####################################################### # # Zendesk 1312 # Test command modules with given array indices # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "windows"; commands: "$(G.cat) $(this.promise_filename).txt" module => "true"; reports: EXTRA:: "Got foo_idx = $(arrays.foo_idx)"; "Got foo[$(arrays.foo_idx)] = $(arrays.foo[$(arrays.foo_idx)])"; } ####################################################### bundle agent check { vars: "foo_$(arrays.foo_idx)" string => "$(arrays.foo[$(arrays.foo_idx)])"; "merged_foo" data => mergedata("arrays.foo"); "sfoo" string => "foo_a=$(foo_a), foo_b=$(foo_b)"; "actual" string => format("foo = %S, foo_idx = %S, sfoo = %s", merged_foo, "arrays.foo_idx", $(sfoo)); "expected" string => 'foo = {"a":"a_foo","b":"b_foo"}, foo_idx = { "a", "b" }, sfoo = foo_a=a_foo, foo_b=b_foo'; methods: "" usebundle => dcs_check_strcmp($(expected), $(actual), $(this.promise_filename), "no"); } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/long-module-lines.cf0000644000175100017510000001600712316547775026215 0ustar00a10038a1003800000000000000####################################################### # # Test command modules with long lines # Redmine#4170: segfault on long lines # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_name" string => "$(G.cat) $(this.promise_filename).txt"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine1884" }; commands: "$(init.script_name)" module => "true"; } ####################################################### bundle agent check { vars: "scalars" slist => { "x4095", "x4094", "x4093" }; "lists" slist => { "zshort", "z4095" }; "bytes1024" string => "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; "bytes1000" string => "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567"; "expected[x4095]" string => concat($(bytes1024),$(bytes1024),$(bytes1024),$(bytes1000),"89abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789x4095"); "expected[x4094]" string => concat($(bytes1024),$(bytes1024),$(bytes1024),$(bytes1000),"89abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345678x4094"); "expected[x4093]" string => concat($(bytes1024),$(bytes1024),$(bytes1024),$(bytes1000),"89abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567x4093"); "longclass" string => "class678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012"; "expected_length[zshort]" int => "227"; "expected_length[z4095]" int => "293"; "actual_length[$(lists)]" int => length("cat.$(lists)"); "longclass_length" int => string_length($(longclass)); "expected_length[$(scalars)]" int => string_length("$(expected[$(scalars)])"); "actual_length[$(scalars)]" int => string_length("$(cat.$(scalars))"); "tail[$(scalars)]" string => string_tail("$(cat.$(scalars))", 256); classes: "match_$(scalars)" expression => strcmp("$(expected[$(scalars)])", "$(cat.$(scalars))"); "match_length_$(scalars)" expression => strcmp("$(expected_length[$(scalars)])", "$(actual_length[$(scalars)])"); "match_length_$(lists)" expression => strcmp("$(expected_length[$(lists)])", "$(actual_length[$(lists)])"); "ok" and => { "$(longclass)", "match_x4095", "match_length_x4095", "match_x4094", "match_length_x4094", "match_x4093", "match_length_x4093", "match_length_zshort", "match_length_z4095", }; reports: DEBUG:: "tail(256) of $(scalars) = $(tail[$(scalars)])"; "Got the long class, $(longclass_length) bytes" ifvarclass => "$(longclass)"; "Did NOT get the long class, $(longclass_length) bytes" ifvarclass => "!$(longclass)"; "Got the length for list $(lists): $(actual_length[$(lists)])" ifvarclass => "match_length_$(lists)"; "Did NOT get the length for list $(lists): actual $(actual_length[$(lists)]) vs expected $(expected_length[$(lists)])" ifvarclass => "!match_length_$(lists)"; "Got the length for scalar $(scalars): $(actual_length[$(scalars)])" ifvarclass => "match_length_$(scalars)"; "Did NOT get the length for scalar $(scalars): actual $(actual_length[$(scalars)]) vs expected $(expected_length[$(scalars)])" ifvarclass => "!match_length_$(scalars)"; "Got the long $(scalars), actual $(actual_length[$(scalars)]) bytes, actual tail($(scalars), 256) = $(tail[$(scalars)])" ifvarclass => "match_$(scalars)"; "Did NOT get the long $(scalars), actual $(actual_length[$(scalars)]) bytes, actual tail($(scalars), 256) = $(tail[$(scalars)])" ifvarclass => "!match_$(scalars)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/set-tags.cf0000644000175100017510000000722212352022221024357 0ustar00a10038a1003800000000000000####################################################### # # Test the ^meta module protocol extension # ####################################################### body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle common init { vars: "script_name" string => "$(this.promise_filename).txt"; } ####################################################### bundle agent test { commands: "$(G.cat) $(init.script_name)" contain => in_shell, module => "true"; } ####################################################### bundle agent check { vars: "xyzvars" slist => variablesmatching("default:xyz.*"); "list0" slist => {"abc", "def", "ghi"}; "list1" slist => {"{{abc}}", " ' def}", "ghi'''"}; "list2" slist => {'{{a,bc}}', ' " de,f}', 'gh,,i"""'}; "list3" slist => {"{{a'bc',,}}", ' ",, d"ef}', "ghi,},'''"}; "actual0" string => join(":", "list0"); "actual1" string => join(":", "list1"); "actual2" string => join(":", "list2"); "actual3" string => join(":", "list3"); "joined0" string => join(":", "xyz.mylist"); "joined1" string => join(":", "xyz.myalist"); "joined2" string => join(":", "xyz.myblist"); "joined3" string => join(":", "xyz.myclist"); "tags0" slist => getvariablemetatags("xyz.mylist"); "tags1" slist => getvariablemetatags("xyz.myalist"); "tags2" slist => getvariablemetatags("xyz.myblist"); "tags3" slist => getclassmetatags("mycclass"); "jtags0" string => join(",", "tags0"); "jtags1" string => join(",", "tags1"); "jtags2" string => join(",", "tags2"); "jtags3" string => join(",", "tags3"); "etags0" string => "xyz,abc=def,,??what is this??,source=module"; "etags1" string => "xyz,abc=def,,??what is this??,source=module"; "etags2" string => "1,2,3,source=module"; "etags3" string => "a,b,c,source=module"; classes: any:: "var0ok" expression => strcmp("${this.joined0}" , "${this.actual0}"); "var1ok" expression => strcmp("${this.joined1}" , "${this.actual1}"); "var2ok" expression => strcmp("${this.joined2}" , "${this.actual2}"); "var3ok" expression => strcmp("${this.joined3}" , "${this.actual3}"); "var4ok" expression => strcmp("hello there" , "${xyz.myvar}"); "tags0ok" expression => strcmp($(jtags0), $(etags0)); "tags1ok" expression => strcmp($(jtags1), $(etags1)); "tags2ok" expression => strcmp($(jtags2), $(etags2)); "tags3ok" expression => strcmp($(jtags3), $(etags3)); "ok" and => { "myclass", "var0ok", "var1ok", "var2ok", "var3ok", "var4ok", "tags0ok", "tags1ok", "tags2ok", "tags3ok", }; reports: DEBUG:: "xyzvars = $(xyzvars)"; "tags0ok => strcmp('$(jtags0)', '$(etags0)')" ifvarclass => "tags0ok"; "tags1ok => strcmp('$(jtags1)', '$(etags1)')" ifvarclass => "tags1ok"; "tags2ok => strcmp('$(jtags2)', '$(etags2)')" ifvarclass => "tags2ok"; "tags3ok => strcmp('$(jtags3)', '$(etags3)')" ifvarclass => "tags3ok"; "tags0 NOT ok => strcmp('$(jtags0)', '$(etags0)')" ifvarclass => "!tags0ok"; "tags1 NOT ok => strcmp('$(jtags1)', '$(etags1)')" ifvarclass => "!tags1ok"; "tags2 NOT ok => strcmp('$(jtags2)', '$(etags2)')" ifvarclass => "!tags2ok"; "tags3 NOT ok => strcmp('$(jtags3)', '$(etags3)')" ifvarclass => "!tags3ok"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/004.cf0000644000175100017510000000417312352022221023135 0ustar00a10038a1003800000000000000####################################################### # # Test command modules # ####################################################### body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_name" string => "$(this.promise_filename).txt"; } ####################################################### bundle agent test { vars: !windows:: "cat_prefix" string => "cat"; windows:: "cat_prefix" string => "cat_exe"; commands: "$(G.cat) $(init.script_name)" contain => in_shell, module => "true"; } ####################################################### bundle agent check { vars: "list0" slist => {"abc", "def", "ghi"}; "list1" slist => {"{{abc}}", " ' def}", "ghi'''"}; "list2" slist => {'{{a,bc}}', ' " de,f}', 'gh,,i"""'}; "list3" slist => {"{{a'bc',,}}", ' ",, d"ef}', "ghi,},'''"}; "actual0" string => join(":", "list0"); "actual1" string => join(":", "list1"); "actual2" string => join(":", "list2"); "actual3" string => join(":", "list3"); "joined0" string => join(":", "$(test.cat_prefix).mylist"); "joined1" string => join(":", "$(test.cat_prefix).myalist"); "joined2" string => join(":", "$(test.cat_prefix).myblist"); "joined3" string => join(":", "$(test.cat_prefix).myclist"); classes: any:: "var0ok" expression => strcmp("${this.joined0}" , "${this.actual0}"); "var1ok" expression => strcmp("${this.joined1}" , "${this.actual1}"); "var2ok" expression => strcmp("${this.joined2}" , "${this.actual2}"); "var3ok" expression => strcmp("${this.joined3}" , "${this.actual3}"); "ok" and => { "var0ok", "var1ok", "var2ok", "var3ok" }; reports: !DEBUG:: "joined3 = [${this.joined3}] vs actual3 = [${this.actual3}]"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/001.cf.txt0000644000175100017510000000005512404565361023762 0ustar00a10038a1003800000000000000+CLASSTOBEDEFINED -UNDEFINEDCLASS =answer=42 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/module-array-indexing.cf.txt0000644000175100017510000000011612332665147027667 0ustar00a10038a1003800000000000000^context=arrays =foo[a]=a_foo =foo[b]=b_foo @foo_idx={"a","b"} +arrays_loaded cfengine-3.6.2/tests/acceptance/08_commands/01_modules/002.cf.txt0000644000175100017510000000003712404565361023763 0ustar00a10038a1003800000000000000=answer[42]=Yes =answer[41]=No cfengine-3.6.2/tests/acceptance/08_commands/01_modules/003.cf.txt0000644000175100017510000000003112404565361023756 0ustar00a10038a1003800000000000000=myvar[dot.dash-test]=42 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/long-module-lines.cf.txt0000644000175100017510000026671612316547775027051 0ustar00a10038a1003800000000000000+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 +1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 +class678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 -1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 -123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 =x=123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 =x=1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234 =x4095=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789x4095 =x4094=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345678x4094 =x4093=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567x4093 @y={ "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" } @z={ "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890" } @zshort={ "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890" } @z4096={ "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "12" } @z4095={ "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "" } %json=[ "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890", "1234567890" ] cfengine-3.6.2/tests/acceptance/08_commands/01_modules/003.cf0000644000175100017510000000222212352022221023125 0ustar00a10038a1003800000000000000####################################################### # # Test command modules # ####################################################### body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_name" string => "$(this.promise_filename).txt"; } ####################################################### bundle agent test { vars: !windows:: "cat_prefix" string => "cat"; windows:: "cat_prefix" string => "cat_exe"; commands: "$(G.cat) $(init.script_name)" contain => in_shell, module => "true"; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("$($(test.cat_prefix).myvar[dot.dash-test])", "42"); reports: DEBUG:: "${$(test.cat_prefix).myvar[dot.dash-test]} =?= 42"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL "; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/002.cf0000644000175100017510000000241212352022221023125 0ustar00a10038a1003800000000000000####################################################### # # Test setting associative array in module (Issue 714) # ####################################################### body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "script_name" string => "$(this.promise_filename).txt"; } ####################################################### bundle agent test { vars: !windows:: "cat_prefix" string => "cat"; windows:: "cat_prefix" string => "cat_exe"; commands: "$(G.cat) $(init.script_name)" contain => in_shell, module => "true"; } ####################################################### bundle agent check { vars: "generated_indices" slist => getindices("$(test.cat_prefix).answer"); classes: "ok" and => { strcmp("${$(test.cat_prefix).answer[42]}", "Yes"), strcmp("${$(test.cat_prefix).answer[41]}", "No") }; reports: DEBUG:: "${$(test.cat_prefix).answer[${generated_indices}]}"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/001.cf0000644000175100017510000000237312352022221023132 0ustar00a10038a1003800000000000000####################################################### # # Test command modules # ####################################################### body common control { inputs => { "../../default.cf.sub", "../../plucked.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_name" string => "$(this.promise_filename).txt"; } ####################################################### bundle agent test { vars: !windows:: "cat_prefix" string => "cat"; windows:: "cat_prefix" string => "cat_exe"; commands: "$(G.cat) $(init.script_name)" contain => in_shell, module => "true"; } ####################################################### bundle agent check { classes: CLASSTOBEDEFINED.!UNDEFINEDCLASS:: "classok" expression => "any"; any:: "varok" expression => strcmp("${$(test.cat_prefix).answer}", "42"); "ok" and => { "classok", "varok" }; reports: DEBUG:: "${$(test.cat_prefix).answer} =?= 42"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 26 cfengine-3.6.2/tests/acceptance/08_commands/01_modules/set-context.cf.txt0000644000175100017510000000115712404565361025743 0ustar00a10038a1003800000000000000^context=xyz_123___456 +myclass =myvar=hello there @mylist={"abc", "def", "ghi"} @myalist={"{{abc}}", " ' def}", "ghi'''"} @myblist={'{{a,bc}}', ' " de,f}', 'gh,,i"""'} @myclist={"{{a'bc',,}}", ' ",, d"ef}', "ghi,},'''"} %mycontainer1={"x":[456,789]} %mycontainer2={"x":"y" %mycontainer3="long string here" %mycontainer4=null %mycontainer5=["read", "some", "strings"] %mycontainer6={"mix": ["match"], "ping": "pong", "paddle": true, "nothing": null} ^context=_456 =myvar=hello there ^context=456 =myvar=hello there ^context=_ =myvar=hello there ^context=a__456__ =myvar=hello there ^context=__a__ =myvar=hello there cfengine-3.6.2/tests/acceptance/16_cf-serverd/0000755000175100017510000000000012411001073020577 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/0000755000175100017510000000000012412221023022234 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_open_admit_hostnames.srv0000644000175100017510000000133512411001073031242 0ustar00a10038a1003800000000000000# In access_rules, admit "localhost" instead of "127.0.0.1" body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9886"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit_hostnames => { "localhost", "localhost.localdomain" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/simple_copy_from_admit_localhost.cf.sub0000644000175100017510000000435112411001073032135 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises, mtime simple copy localhost # The source server has access_rules admit=>{"localhost"} # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: # localhost_open_hostname # "$(G.testdir)/server1_classic" copy_from => copy_file("9884", "classic"); "$(G.testdir)/server1_latest" copy_from => copy_file("9884", "latest"); # localhost_open_admit_hostnames "$(G.testdir)/server2_classic" copy_from => copy_file("9886", "classic"); # "$(G.testdir)/server2_latest" copy_from => copy_file("9886", "latest"); } ######################################################### body copy_from copy_file(port, protocol_version) { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; portnumber => "$(port)"; protocol_version => "$(protocol_version)"; #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: # "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", # "$(G.testdir)/server1_classic","$(fn[1])"); "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", "$(G.testdir)/server1_latest","$(fn[1])"); "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", "$(G.testdir)/server2_classic","$(fn[1])"); # "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", # "$(G.testdir)/server2_latest","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_closed_hostname.srv0000644000175100017510000000150012411001073030203 0ustar00a10038a1003800000000000000# In access_rules, deny "localhost" instead of "127.0.0.1" body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9885"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { "0.0.0.0/0" }, # admit everyone deny => { "localhost", "localhost.localdomain" }; # deny is stronger than admit } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_same_expand_shortcut.cf.sub0000644000175100017510000000243112411001073033171 0ustar00a10038a1003800000000000000####################################################### # # copy_from compare=>"digest" with server-side shortcut expansion (TLS # protocol only) when file is already there - should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "simple_source"; protocol_version => "latest"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_same.cf.sub0000644000175100017510000000273312411001073027704 0ustar00a10038a1003800000000000000####################################################### # # copy_from compare=>"digest" when file is already there - should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: # "$(G.testdir)/dest_file_classic" # copy_from => copy_src_file("classic"), # classes => if_repaired("repaired_classic"); "$(G.testdir)/dest_file_latest" copy_from => copy_src_file("latest"), classes => if_repaired("repaired_latest"); } ######################################################### body copy_from copy_src_file(protocol_version) { protocol_version => "$(protocol_version)"; source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired_classic.!repaired_latest:: "$(fn[1]) Pass"; repaired_classic|repaired_latest:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_different_expand_shortcut.cf0000644000175100017510000000146612412221023033431 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6406" }; methods: "any" usebundle => file_make("$(G.testdir)/source_file", "Source and Destination are DIFFERENT_A"); "any" usebundle => file_make("$(G.testdir)/destination_file", "Source and Destination are DIFFERENT_B"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_same_expand_ip.cf.sub0000644000175100017510000000245312411001073031732 0ustar00a10038a1003800000000000000####################################################### # # copy_from compare=>"digest" with server-side expansion of IP address # (TLS protocol only) when file is already there - should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/127.0.0.1.txt"; protocol_version => "latest"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/simple_copy_from_deny_localhost.cf.sub0000644000175100017510000000412012411001073031770 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises, mtime simple copy localhost # The source server has access_rules admit=>{"localhost"} # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: # localhost_closed_hostname # "$(G.testdir)/server1_classic" # copy_from => copy_file("9885", "classic"), # classes => if_repaired("repaired1_classic"); "$(G.testdir)/server1_latest" copy_from => copy_file("9885", "latest"), classes => if_repaired("repaired1_latest"); # localhost_closed_deny_hostnames "$(G.testdir)/server2_classic" copy_from => copy_file("9887", "classic"), classes => if_repaired("repaired2_classic"); # "$(G.testdir)/server2_latest" # copy_from => copy_file("9887", "latest"), # classes => if_repaired("repaired2_latest"); } ######################################################### body copy_from copy_file(port, protocol_version) { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; portnumber => "$(port)"; protocol_version => "$(protocol_version)"; #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired1_classic.!repaired1_latest.!repaired2_classic.!repaired2_latest:: "$(fn[1]) Pass"; repaired1_classic|repaired1_latest|repaired2_classic|repaired2_latest:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/README0000644000175100017510000000077312411001073023123 0ustar00a10038a1003800000000000000001 - mtime simple copy, localhost 002 - mtime, newer destination, localhost, should not copy 003 - mtime server copy, localhost, explicit deny connect access, should not copy 004 - mtime server copy, for non-localhost, should copy 005 - mtime server copy, for non-localhost, no connect access, should not copy 006 - mtime server copy, localhost, no file access promise, should not copy 007 - digest server copy, localhost, newer destination, should copy 008 - mtime simple copy, localhost with encryption cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/simple_copy_from_admit_localhost.cf0000644000175100017510000000224212411001073031342 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine6405", "redmine6406" }; methods: # source file "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); # destination files "any" usebundle => dcs_fini("$(G.testdir)/server1_classic"); "any" usebundle => dcs_fini("$(G.testdir)/server1_latest"); "any" usebundle => dcs_fini("$(G.testdir)/server2_classic"); "any" usebundle => dcs_fini("$(G.testdir)/server2_latest"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open_hostname"); "any" usebundle => start_server("localhost_open_admit_hostnames"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open_hostname"); "any" usebundle => stop_server("localhost_open_admit_hostnames"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/010.cf.sub0000644000175100017510000000260712411001073023643 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises # # Tests copy_from encrypted digest verify (SMD5) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("copy_ok"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; copy_backup => "false"; portnumber => "9876"; # localhost_open encrypt => "true"; compare => "digest"; verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { methods: copy_ok:: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !copy_ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_md5_zero_length_file.cf0000644000175100017510000000123112411001073030704 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "freebsd", meta => { "redmine6406" }; methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_empty("$(G.testdir)/source_file"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/003.cf.sub0000644000175100017510000000251512411001073023643 0ustar00a10038a1003800000000000000####################################################### # # mtime server copy, localhost, explicit deny connect access, should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { files: } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; portnumber => "9877"; #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/007.cf0000644000175100017510000000141212412221023023052 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6406" }; methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/011.cf0000644000175100017510000000125312411001073023050 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } copy_from_digest_different_expand_ip_and_shortcut.cf.sub0000644000175100017510000000261012411001073035444 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start####################################################### # # copy_from compare=>"digest" with server-side expansion of IP address # (TLS protocol only) *and* shortcut expansion when file is there but # differs - should copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "expand_ip_source"; protocol_version => "latest"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/127.0.0.1.txt", "$(G.testdir)/destination_file","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_different.cf0000644000175100017510000000155212411001073030133 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/source_file", "Source and Destination are DIFFERENT_A"); "any" usebundle => file_make("$(G.testdir)/dest_file_latest", "Source and Destination are DIFFERENT_B"); "any" usebundle => file_make("$(G.testdir)/dest_file_classic", "Source and Destination are DIFFERENT_C"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_expand_ip_directory.cf0000644000175100017510000000236612411001073030665 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testdir)/127.0.0.1_DIR1/." create => "true"; "$(G.testdir)/127.0.0.1_DIR2/." create => "true"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR1/ADMIT_FILE", "ADMIT_FILE A CONTENTS"); "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR1/DENY_FILE", "DENY_FILE A CONTENTS"); "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR2/ADMIT_FILE", "ADMIT_FILE B CONTENTS"); "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR2/DENY_FILE", "DENY_FILE B CONTENTS"); "any" usebundle => dcs_fini("$(G.testdir)/destination_file1"); "any" usebundle => dcs_fini("$(G.testdir)/destination_file2"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/lan_open.srv0000644000175100017510000000133712411001073024567 0ustar00a10038a1003800000000000000# Deny localhost, admit other interface IPs body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9878"; denyconnects => { "127.0.0.1" }; allowconnects => { @(sys.ip_addresses) }; allowallconnects => { @(sys.ip_addresses) }; trustkeysfrom => { @(sys.ip_addresses) }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { @(sys.ip_addresses) }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_open.srv0000644000175100017510000000304112411001073025777 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9876"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { "127.0.0.1", "::1" }, shortcut => "simple_source"; "$(G.testdir)/$(connection.ip).txt" admit_ips => { "$(connection.ip)" }, shortcut => "expand_ip_source"; # Directory existing only in connection time (not in daemon init # time), after special variables have been expanded. So we need to # specify recursive access by appending trailing slash or slashdot. # Trailing slash "$(G.testdir)/$(connection.ip)_DIR1/" admit_ips => { "$(connection.ip)" }; # Trailing slashdot, should be equivalent to trailing slash "$(G.testdir)/$(connection.ip)_DIR2/." admit_ips => { "$(connection.ip)" }; # Deny access to a file within a recursively admitted directory! "$(G.testdir)/$(connection.ip)_DIR1/DENY_FILE" deny_ips => { "$(connection.ip)" }; "$(G.testdir)/$(connection.ip)_DIR2/DENY_FILE" deny_ips => { "$(connection.ip)" }; } copy_from_expand_ip_admit_directory_deny_file.cf.sub0000644000175100017510000000317112411001073034565 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start####################################################### # # copy_from from within recursively admitted directory that does not # exist during daemon init time, e.g. /path/to/$(connection.ip), # but the file itself is in "deny" list! # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: # Directory admitted in cf-serverd using trailing slash "$(G.testdir)/destination_file1" copy_from => copy_src_file("$(G.testdir)/127.0.0.1_DIR1/DENY_FILE"), classes => if_repaired("repaired1"); # Directory admitted in cf-serverd using trailing slashdot "$(G.testdir)/destination_file2" copy_from => copy_src_file("$(G.testdir)/127.0.0.1_DIR2/DENY_FILE"), classes => if_repaired("repaired2"); } ######################################################### body copy_from copy_src_file(file) { source => "$(file)"; protocol_version => "latest"; servers => { "127.0.0.1" }; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired1.!repaired2:: "$(fn[1]) Pass"; repaired1|repaired2:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_deny_one_directory_with_regex.srv0000644000175100017510000000135712411001073033157 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9882"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testroot)/" admit => { "192.168.*", ".*", "10.*" }, deny => { "127.0*" }; # this matches nothing "$(G.testdir)/" deny => { ".*" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/allow_path1_then_deny_path2_a.cf0000644000175100017510000000226412411001073030420 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { create_directories, default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file1"); "any" usebundle => dcs_fini("$(G.testdir)/destination_file2"); "any" usebundle => file_make("$(G.testroot)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_deny_one_directory"); "any" usebundle => start_server("localhost_deny_one_directory_with_regex"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_deny_one_directory"); "any" usebundle => stop_server("localhost_deny_one_directory_with_regex"); } # For the access rules in cf-serverd to work recursively, the paths must exist and be directories bundle agent create_directories { files: "$(G.testroot)/." create => "true"; "$(G.testdir)/." create => "true"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_expand_ip_directory.cf.sub0000644000175100017510000000333412411001073031451 0ustar00a10038a1003800000000000000####################################################### # # copy_from from within recursively admitted directory that does not # exist during daemon init time, e.g. /path/to/$(connection.ip) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: # Admitted in cf-serverd using trailing slash "$(G.testdir)/destination_file1" copy_from => copy_src_file("$(G.testdir)/127.0.0.1_DIR1/ADMIT_FILE"); # Admitted in cf-serverd using trailing slashdot "$(G.testdir)/destination_file2" copy_from => copy_src_file("$(G.testdir)/127.0.0.1_DIR2/ADMIT_FILE"); } ######################################################### body copy_from copy_src_file(file) { source => "$(file)"; protocol_version => "latest"; servers => { "127.0.0.1" }; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/127.0.0.1_DIR1/ADMIT_FILE", "$(G.testdir)/destination_file1","$(fn[1])"); "any" usebundle => dcs_check_diff("$(G.testdir)/127.0.0.1_DIR2/ADMIT_FILE", "$(G.testdir)/destination_file2","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/004.cf0000644000175100017510000000123712411001073023054 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("lan_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("lan_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/tcp_port_listen_within_range.cf0000644000175100017510000000055712411001073030523 0ustar00a10038a1003800000000000000# # Check the parser enforces standard TCP port ( 1 <= port <= 65535) for: # -cf-serverd listening port # body common control { bundlesequence => { default("$(this.promise_filename)") }; inputs => { "../../default.cf.sub" }; version => "1.0"; } body server control { port => "5308"; } bundle agent test { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_md5_zero_length_file.cf.sub0000644000175100017510000000267612411001073031512 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises # # Tests copy_from digest verify (SMD5) zero-length file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("copy_ok"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; copy_backup => "false"; portnumber => "9876"; # localhost_open encrypt => "false"; compare => "digest"; verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); "empty_ok" and => { strcmp(filesize("$(G.testdir)/destination_file"),"0") }; methods: copy_ok.empty_ok:: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); reports: !copy_ok|!empty_ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/tcp_port_listen_outside_range.x.cf0000644000175100017510000000060112411001073031131 0ustar00a10038a1003800000000000000# # Check the parser enforces standard TCP port ( 1 <= port <= 65535) for: # -cf-serverd listening port # body common control { bundlesequence => { default("$(this.promise_filename)") }; inputs => { "../../default.cf.sub" }; version => "1.0"; } body server control { port => "65536"; } bundle agent test { reports: "$(this.promise_filename) Pass"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_same_expand_ip.cf0000644000175100017510000000132712411001073031141 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/127.0.0.1.txt", "Source and Destination are identical."); "any" usebundle => file_make("$(G.testdir)/destination_file", "Source and Destination are identical."); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/allow_path1_then_deny_path2_a.cf.sub0000644000175100017510000000240612411001073031206 0ustar00a10038a1003800000000000000####################################################### # # We request a path from allowed path, it should succeed # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } ####################################################### body copy_from copy_from_port(port) { source => "$(G.testroot)/source_file"; servers => { "127.0.0.1" }; portnumber => "$(port)"; trustkey => "true"; } bundle agent test { files: "$(G.testroot)/destination_file1" copy_from => copy_from_port("9881"); # localhost_deny_one_directory "$(G.testroot)/destination_file2" copy_from => copy_from_port("9882"); # localhost_deny_one_directory_with_regex } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testroot)/source_file","$(G.testroot)/destination_file1","$(fn[1])"); "any" usebundle => dcs_check_diff("$(G.testroot)/source_file","$(G.testroot)/destination_file2","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_different.cf.sub0000644000175100017510000000322312411001073030720 0ustar00a10038a1003800000000000000####################################################### # # copy_from compare=>"digest" when file is there but differs - should copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: # "$(G.testdir)/dest_file_classic" # copy_from => copy_src_file("classic"), # classes => if_repaired("repaired_classic"); "$(G.testdir)/dest_file_latest" copy_from => copy_src_file("latest"), classes => if_repaired("repaired_latest"); } ######################################################### body copy_from copy_src_file(protocol_version) { protocol_version => "$(protocol_version)"; source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: # "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", # "$(G.testdir)/dest_file_classic","$(fn[1])"); "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", "$(G.testdir)/dest_file_latest","$(fn[1])"); } copy_from_encrypted_md5_zero_length_file.cf.sub0000644000175100017510000000300012411001073033466 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start####################################################### # # Test cf-serverd related promises # # Tests copy_from encrypted digest verify (SMD5) zero-length file # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("copy_ok"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; copy_backup => "false"; portnumber => "9876"; # localhost_open encrypt => "true"; compare => "digest"; verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); "empty_ok" and => { strcmp(filesize("$(G.testdir)/destination_file"),"0") }; methods: copy_ok.empty_ok:: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); reports: !copy_ok|!empty_ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/009.cf.sub0000644000175100017510000000135712411001073023654 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises, mtime simple copy localhost # TODO: implement # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { reports: } ####################################################### bundle agent test { reports: } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: "$(fn[1]) Pass"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/002.cf.sub0000644000175100017510000000241312411001073023637 0ustar00a10038a1003800000000000000####################################################### # # mtime, newer destination, localhost, should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; portnumber => "9876"; # localhost_open #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/008.cf0000644000175100017510000000125312411001073023056 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/006.cf.sub0000644000175100017510000000252412411001073023646 0ustar00a10038a1003800000000000000####################################################### # # mtime server copy, localhost, no file access promise, should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; portnumber => "9876"; # localhost_open #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; #trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } copy_from_digest_same_expand_ip_and_shortcut.cf.sub0000644000175100017510000000247212411001073034431 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start####################################################### # # copy_from compare=>"digest" with server-side expansion of IP address # (TLS protocol only) and shortcut expansion when file is already there # - should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "expand_ip_source"; protocol_version => "latest"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/tcp_port_copy_from_within_range.cf0000644000175100017510000000062512411001073031216 0ustar00a10038a1003800000000000000# # Check the parser enforces standard TCP port ( 1 <= port <= 65535) for: # -copy_from bodies "portnumber" # body common control { bundlesequence => { default("$(this.promise_filename)") }; inputs => { "../../default.cf.sub" }; version => "1.0"; } bundle agent test { reports: "$(this.promise_filename) Pass"; } body copy_from dummy_copy_from { portnumber => "5308"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_noaccess.srv0000644000175100017510000000112412411001073026634 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9880"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: # no access granted } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/allow_path1_then_deny_path2_b.cf0000644000175100017510000000172512411001073030422 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { create_directories, default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "freebsd", meta => { "redmine6406" }; methods: "any" usebundle => generate_key; "any" usebundle => start_server("localhost_deny_one_directory"); "any" usebundle => start_server("localhost_deny_one_directory_with_regex"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_deny_one_directory"); "any" usebundle => stop_server("localhost_deny_one_directory_with_regex"); } # For the access rules in cf-serverd to work recursively, the paths must exist and be directories bundle agent create_directories { files: "$(G.testroot)/." create => "true"; "$(G.testdir)/." create => "true"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_encrypted_md5_zero_length_file.cf0000644000175100017510000000123412412221023032764 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "sunos_5_11", meta => { "redmine6406" }; methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_empty("$(G.testdir)/source_file"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_deny_one_directory.srv0000644000175100017510000000125612411001073030730 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9881"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testroot)/" admit => { "127.0.0.1", "::1" }; "$(G.testdir)/" deny => { "127.0.0.1", "::1" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/011.cf.sub0000644000175100017510000000257512411001073023650 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises # # Tests copy_from digest verify (MD5) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("copy_ok"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; copy_backup => "false"; portnumber => "9876"; # localhost_open encrypt => "false"; compare => "digest"; verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { methods: copy_ok:: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !copy_ok:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_different_expand_ip.cf0000644000175100017510000000133112411001073032155 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/127.0.0.1.txt", "Source and Destination are different_A"); "any" usebundle => file_make("$(G.testdir)/destination_file", "Source and Destination are different_B"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_same_expand_shortcut.cf0000644000175100017510000000132512411001073032402 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/source_file", "Source and Destination are identical."); "any" usebundle => file_make("$(G.testdir)/destination_file", "Source and Destination are identical."); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/003.cf0000644000175100017510000000127312411001073023053 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_deny_connect"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_deny_connect"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/simple_copy_from_deny_localhost.cf0000644000175100017510000000225012411001073031202 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine6405", "redmine6406" }; methods: # source file "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); # destination files "any" usebundle => dcs_fini("$(G.testdir)/server1_classic"); "any" usebundle => dcs_fini("$(G.testdir)/server1_latest"); "any" usebundle => dcs_fini("$(G.testdir)/server2_classic"); "any" usebundle => dcs_fini("$(G.testdir)/server2_latest"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_closed_hostname"); "any" usebundle => start_server("localhost_closed_deny_hostnames"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_closed_hostname"); "any" usebundle => stop_server("localhost_closed_deny_hostnames"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_deny_connect.srv0000644000175100017510000000127212411001073027512 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9877"; denyconnects => { "127.0.0.1" , "::1" }; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { "127.0.0.1", "::1" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/lan_deny_connect.srv0000644000175100017510000000127212411001073026274 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9879"; denyconnects => { @(sys.ip_addresses) }; allowconnects => { @(sys.ip_addresses) }; allowallconnects => { @(sys.ip_addresses) }; trustkeysfrom => { @(sys.ip_addresses) }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { @(sys.ip_addresses) }; } copy_from_digest_same_expand_ip_and_shortcut.cf0000644000175100017510000000132712411001073033637 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/127.0.0.1.txt", "Source and Destination are identical."); "any" usebundle => file_make("$(G.testdir)/destination_file", "Source and Destination are identical."); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/run_with_server.cf.sub0000644000175100017510000000473412411001073026573 0ustar00a10038a1003800000000000000body classes if_failed(x) { repair_failed => { "$(x)" }; } body contain run_under_shell { useshell => "useshell"; } body action in_background { background => "true"; } bundle agent generate_key { commands: "$(sys.cf_key)"; } bundle agent start_server(server_name) { classes: "debug_server" expression => "debug_mode"; vars: "cwd" string => dirname("$(this.promise_filename)"); "dlog" string => "$(sys.workdir)/server-debug.$(server_name).log"; "conf" string => "$(cwd)/$(server_name).srv"; commands: !debug_server.!windows:: "$(sys.cf_serverd) -Kf $(conf)" classes => if_failed("server_failed"); !debug_server.windows:: # Windows cannot daemonize and needs to start in background. "$(sys.cf_serverd) -Kf $(conf)" action => in_background, classes => if_failed("server_failed"); debug_server:: "$(sys.cf_serverd) -Kdf $(conf) > $(dlog) 2>&1" contain => run_under_shell, action => in_background, handle => "run_debug_server", classes => if_failed("server_failed"); debug_server|windows:: # Sleep 3 seconds since cf-serverd takes some time to start in background mode. "$(G.sleep) 3" depends_on => { "run_debug_server" }, contain => run_under_shell; reports: debug_server:: "$(sys.cf_serverd)($(server_name)) was run in debug mode with configuration $(conf). The logs will be in $(dlog)"; } bundle agent run_test(test_name) { classes: "debug_client" expression => "debug_mode"; vars: "dlog" string => "$(sys.workdir)/agent-debug.log"; commands: !debug_client:: "$(sys.cf_agent) -KIf $(test_name) -D DEBUG,AUTO,ok 2>&1 | $(G.tee) $(dlog)" contain => run_under_shell; debug_client:: "$(sys.cf_agent) -Kdf $(test_name) -D DEBUG,AUTO,ok 2>&1 | $(G.tee) $(dlog)" contain => run_under_shell; reports: debug_client:: "$(sys.cf_agent) was run in debug mode with configuration $(test_name). The logs will be in $(dlog)"; } bundle agent stop_server(server_name) { # On some old platforms, "ps" truncates its output, which CFEngine depends on. This can lead to # the test servers not being killed. # On HP-UX you can set the DEFAULT_CMD_LINE_WIDTH inside /etc/default/ps to a higher value, which # controls the maximum line length of "ps". Unfortunately it is not overridable from the # environment. processes: "$(server_name)" signals => { "term", "kill" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_open_with_data_select.srv0000644000175100017510000000157312411001073031372 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9883"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { "127.0.0.1", "::1" }; "delta" resource_type => "query", report_data_select => test_report_filter; } body report_data_select test_report_filter { monitoring_include => { "lala.*", "lalala.*" }; monitoring_exclude => { "lala.*", "lalala.*" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/005.cf0000644000175100017510000000125712411001073023057 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("lan_deny_connect"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("lan_deny_connect"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/006.cf0000644000175100017510000000125312411001073023054 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/009.cf0000644000175100017510000000131512411001073023056 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open_with_data_select"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open_with_data_select"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_open_hostname.srv0000644000175100017510000000132312411001073027676 0ustar00a10038a1003800000000000000# In access_rules, admit "localhost" instead of "127.0.0.1" body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9884"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { "localhost", "localhost.localdomain" }; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/002.cf0000644000175100017510000000166312411001073023055 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); # We generate key in-between the two files on purpose, to # introduce latency and make sure that destination file is newer "any" usebundle => generate_key; "any" usebundle => file_make("$(G.testdir)/destination_file", "This is the source file to copy $(sys.date) - always fresh... more data!"); "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_different_expand_ip.cf.sub0000644000175100017510000000256712411001073032761 0ustar00a10038a1003800000000000000####################################################### # # copy_from compare=>"digest" with server-side expansion of IP address # (TLS protocol only) when file is there but differs - should copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/127.0.0.1.txt"; protocol_version => "latest"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/127.0.0.1.txt", "$(G.testdir)/destination_file","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/008.cf.sub0000644000175100017510000000247312411001073023653 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises, mtime simple copy localhost # # Tests secure copy (SGET) and secure stat (SSYNCH). # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file; } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; portnumber => "9876"; # localhost_open encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); } copy_from_digest_different_expand_shortcut.cf.sub0000644000175100017510000000254312411001073034137 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start####################################################### # # copy_from compare=>"digest" with server-side shortcut expansion (TLS # protocol only) when file is there but differs - should copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "simple_source"; protocol_version => "latest"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; trustkey => "true"; portnumber => "9876"; # localhost_open } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", "$(G.testdir)/destination_file","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/copy_from_digest_same.cf0000644000175100017510000000154712411001073027116 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/source_file", "Source and Destination are identical."); "any" usebundle => file_make("$(G.testdir)/dest_file_latest", "Source and Destination are identical."); "any" usebundle => file_make("$(G.testdir)/dest_file_classic", "Source and Destination are identical."); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } copy_from_expand_ip_admit_directory_deny_file.cf0000644000175100017510000000236612411001073034002 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { files: "$(G.testdir)/127.0.0.1_DIR1/." create => "true"; "$(G.testdir)/127.0.0.1_DIR2/." create => "true"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR1/ADMIT_FILE", "ADMIT_FILE A CONTENTS"); "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR1/DENY_FILE", "DENY_FILE A CONTENTS"); "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR2/ADMIT_FILE", "ADMIT_FILE B CONTENTS"); "any" usebundle => file_make("$(G.testdir)/127.0.0.1_DIR2/DENY_FILE", "DENY_FILE B CONTENTS"); "any" usebundle => dcs_fini("$(G.testdir)/destination_file1"); "any" usebundle => dcs_fini("$(G.testdir)/destination_file2"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/007.cf.sub0000644000175100017510000000250112411001073023642 0ustar00a10038a1003800000000000000####################################################### # # digest server copy, localhost, newer destination, should copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file; } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "digest"; copy_backup => "false"; portnumber => "9876"; # localhost_open #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/001.cf0000644000175100017510000000125312411001073023047 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/001.cf.sub0000644000175100017510000000324112411001073023636 0ustar00a10038a1003800000000000000####################################################### # # Test cf-serverd related promises, mtime simple copy localhost # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/dest_file_classic" copy_from => copy_src_file("classic"); "$(G.testdir)/dest_file_latest" copy_from => copy_src_file("latest"); } ######################################################### body copy_from copy_src_file(protocol_version) { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; compare => "mtime"; copy_backup => "false"; protocol_version => "$(protocol_version)"; portnumber => "9876"; # localhost_open #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", "$(G.testdir)/dest_file_classic","$(fn[1])"); "any" usebundle => dcs_check_diff("$(G.testdir)/source_file", "$(G.testdir)/dest_file_latest","$(fn[1])"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/localhost_closed_deny_hostnames.srv0000644000175100017510000000153012411001073031410 0ustar00a10038a1003800000000000000# In access_rules, deny "localhost" instead of "127.0.0.1" body common control { bundlesequence => { "access_rules" }; inputs => { "../../default.cf.sub" }; } ######################################################### # Server config ######################################################### body server control { port => "9887"; allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "$(G.testdir)/source_file" admit => { "0.0.0.0/0" }, # admit everyone but deny_hostnames => { "localhost", "localhost.localdomain" }; # deny is stronger than admit } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/allow_path1_then_deny_path2_b.cf.sub0000644000175100017510000000241612411001073031210 0ustar00a10038a1003800000000000000####################################################### # # We request a path from disallowed path, it should fail # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { } ####################################################### body copy_from copy_from_port(port) { source => "$(G.testdir)/source_file"; servers => { "127.0.0.1" }; portnumber => "$(port)"; trustkey => "true"; } bundle agent test { files: "$(G.testroot)/destination_file1" copy_from => copy_from_port("9881"), # localhost_deny_one_directory classes => if_repaired("repaired1"); "$(G.testroot)/destination_file2" copy_from => copy_from_port("9882"), # localhost_deny_one_directory_with_regex classes => if_repaired("repaired2"); } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: # Both copies must fail !repaired1.!repaired2:: "$(fn[1]) Pass"; repaired1|repaired2:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/010.cf0000644000175100017510000000142212412221023023045 0ustar00a10038a1003800000000000000# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { meta: "test_suppress_fail" string => "freebsd|sunos_5_11", meta => { "redmine6406" }; methods: "any" usebundle => dcs_fini("$(G.testdir)/destination_file"); "any" usebundle => file_make("$(G.testdir)/source_file", "This is the source file to copy $(sys.date) - always fresh"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/004.cf.sub0000644000175100017510000000261712411001073023647 0ustar00a10038a1003800000000000000####################################################### # # mtime server copy, for non-localhost, should copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; # localhost comes first but will be denied servers => { @(sys.ip_addresses) }; compare => "mtime"; copy_backup => "false"; portnumber => "9878"; # lan_open #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); methods: "any" usebundle => dcs_check_diff("$(G.testdir)/source_file","$(G.testdir)/destination_file","$(fn[1])"); } copy_from_digest_different_expand_ip_and_shortcut.cf0000644000175100017510000000133412411001073034656 0ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start# body common control { inputs => { "../../default.cf.sub", "./run_with_server.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent test { methods: "any" usebundle => file_make("$(G.testdir)/127.0.0.1.txt", "Source and Destination are different_A"); "any" usebundle => file_make("$(G.testdir)/destination_file", "Source and Destination are different_B"); "any" usebundle => generate_key; "any" usebundle => start_server("localhost_open"); "any" usebundle => run_test("$(this.promise_filename).sub"); "any" usebundle => stop_server("localhost_open"); } cfengine-3.6.2/tests/acceptance/16_cf-serverd/01_start/005.cf.sub0000644000175100017510000000262112411001073023643 0ustar00a10038a1003800000000000000####################################################### # # mtime server copy, for non-localhost, no connect access, should not copy # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { files: "$(G.testdir)/destination_file" copy_from => copy_src_file, classes => if_repaired("repaired"); } ######################################################### body copy_from copy_src_file { source => "$(G.testdir)/source_file"; # localhost comes first but will be denied servers => { @(sys.ip_addresses) }; compare => "mtime"; copy_backup => "false"; portnumber => "9879"; # lan_deny_connect #encrypt => "true"; #verify => "true"; #purge => "false"; #type_check => "true"; #force_ipv4 => "true"; trustkey => "true"; } ####################################################### bundle agent check { classes: "dummy" expression => regextract("(.*)\.sub", $(this.promise_filename), "fn"); reports: !repaired:: "$(fn[1]) Pass"; repaired:: "$(fn[1]) FAIL"; } cfengine-3.6.2/tests/acceptance/plucked.cf.sub0000644000175100017510000014215712352022221020776 0ustar00a10038a1003800000000000000### This is an auto-generated file, see Makefile.am and `make pluck` ### body contain in_dir_shell(dir) # @brief run command after switching to directory "dir" with full shell # @param dir directory to change into # # **Example:** # # ```cf3 # commands: # "/bin/pwd | /bin/cat" # contain => in_dir_shell("/tmp"); # ``` { chdir => "$(dir)"; useshell => "true"; # canonical "useshell" but this is backwards-compatible } body contain in_shell # @brief run command in shell # # **Example:** # # ```cf3 # commands: # "/bin/pwd | /bin/cat" # contain => in_shell; # ``` { useshell => "true"; # canonical "useshell" but this is backwards-compatible } body contain in_shell_bg # @brief deprecated # This bundle previously had an invalid background attribute that was caught by # parser strictness enhancements. Backgrounding is handeled by the body action # background attribute. { useshell => "true"; # canonical "useshell" but this is backwards-compatible } body contain in_shell_and_silent # @brief run command in shell and suppress output # # **Example:** # # ```cf3 # commands: # "/bin/pwd | /bin/cat" # contain => in_shell_and_silent, # comment => "Silently run command in shell"; # ``` { useshell => "true"; # canonical "useshell" but this is backwards-compatible no_output => "true"; } body contain in_dir_shell_and_silent(dir) # @brief run command in shell after switching to 'dir' and suppress output # @param dir directory to change into # # **Example:** # # ```cf3 # commands: # "/bin/pwd | /bin/cat" # contain => in_dir_shell_and_silent("/tmp"), # comment => "Silently run command in shell"; # ``` { useshell => "true"; # canonical "useshell" but this is backwards-compatible no_output => "true"; chdir => "$(dir)"; } bundle edit_line create_solaris_admin_file # @brief The following bundle is part of a package setup for solaris # # See unit examples. { insert_lines: "$(solaris_knowledge.admin_nocheck)" comment => "Insert contents of Solaris admin file (automatically install packages)"; } body action if_elapsed(x) # @brief Evaluate the promise every `x` minutes # @param x The time in minutes between promise evaluations { ifelapsed => "$(x)"; expireafter => "$(x)"; } body action if_elapsed_day # @brief Evalute the promise once every 24 hours { ifelapsed => "1440"; # 60 x 24 expireafter => "1400"; } body action warn_only # @brief Warn once an hour if the promise needs to be repaired # # The promise does not get repaired. { action_policy => "warn"; ifelapsed => "60"; } body action immediate # @brief Evaluate the promise at every `cf-agent` execution. { ifelapsed => "0"; } body classes if_repaired(x) # @brief Define class `x` if the promise has been repaired # @param x The name of the class { promise_repaired => { "$(x)" }; } body classes if_else(yes,no) # @brief Define the classes `yes` or `no` depending on promise outcome # @param yes The name of the class that should be defined if the promise is kept or repaired # @param no The name of the class that should be defined if the promise could not be repaired { promise_kept => { "$(yes)" }; promise_repaired => { "$(yes)" }; repair_failed => { "$(no)" }; repair_denied => { "$(no)" }; repair_timeout => { "$(no)" }; } body classes if_notkept(x) # @brief Define the class `x` if the promise is not kept and cannot be repaired. # @param x The name of the class that should be defined { repair_failed => { "$(x)" }; repair_denied => { "$(x)" }; repair_timeout => { "$(x)" }; } body classes if_ok(x) # @brief Define the class `x` if the promise is kept or could be repaired # @param x The name of the class that should be defined { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; } body classes if_ok_cancel(x) # @brief Cancel the class `x` if the promise ks kept or repaired # @param x The name of the class that should be cancelled { cancel_repaired => { "$(x)" }; cancel_kept => { "$(x)" }; } body classes classes_generic(x) # @brief Define `x` prefixed/suffixed with promise outcome # @param x The unique part of the classes to be defined { promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached" }; repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached" }; } body classes scoped_classes_generic(scope, x) # @brief Define `x` prefixed/suffixed with promise outcome # **See also:** `scope` # # @param scope The scope in which the class should be defined # @param x The unique part of the classes to be defined { scope => "$(scope)"; promise_repaired => { "promise_repaired_$(x)", "$(x)_repaired", "$(x)_ok", "$(x)_reached" }; repair_failed => { "repair_failed_$(x)", "$(x)_failed", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; repair_denied => { "repair_denied_$(x)", "$(x)_denied", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; repair_timeout => { "repair_timeout_$(x)", "$(x)_timeout", "$(x)_not_ok", "$(x)_not_kept", "$(x)_not_repaired", "$(x)_reached" }; promise_kept => { "promise_kept_$(x)", "$(x)_kept", "$(x)_ok", "$(x)_not_repaired", "$(x)_reached" }; } body classes always(x) # @brief Define class `x` no matter what the outcome of the promise is # @param x The name of the class to be defined { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; repair_failed => { "$(x)" }; repair_denied => { "$(x)" }; repair_timeout => { "$(x)" }; } body classes kept_successful_command # @brief Set command to "kept" instead of "repaired" if it returns 0 { kept_returncodes => { "0" }; } bundle edit_line insert_lines(lines) # @brief Append `lines` if they don't exist in the file # @param lines The lines to be appended # # **See also:** [`insert_lines`][insert_lines] in # [`edit_line`][bundle edit_line] { insert_lines: "$(lines)" comment => "Append lines if they don't exist"; } bundle edit_line insert_file(templatefile) # @brief Reads the lines from `templatefile` and inserts those into the # file being edited. # @param templatefile The name of the file from which to import lines. { insert_lines: "$(templatefile)" comment => "Insert the template file into the file being edited", insert_type => "file"; } bundle edit_line comment_lines_matching(regex,comment) # @brief Comment lines in the file that matching an [anchored] regex # @param regex Anchored regex that the entire line needs to match # @param comment A string that is prepended to matching lines { replace_patterns: "^($(regex))$" replace_with => comment("$(comment)"), comment => "Search and replace string"; } bundle edit_line uncomment_lines_matching(regex,comment) # @brief Uncomment lines of the file where the regex matches # the entire text after the comment string # @param regex The regex that lines need to match after `comment` # @param comment The prefix of the line that is removed { replace_patterns: "^$(comment)\s?($(regex))$" replace_with => uncomment, comment => "Uncomment lines matching a regular expression"; } bundle edit_line comment_lines_containing(regex,comment) # @brief Comment lines of the file matching a regex # @param regex A regex that a part of the line needs to match # @param comment A string that is prepended to matching lines { replace_patterns: "^((?!$(comment)).*$(regex).*)$" replace_with => comment("$(comment)"), comment => "Comment out lines in a file"; } bundle edit_line uncomment_lines_containing(regex,comment) # @brief Uncomment lines of the file where the regex matches # parts of the text after the comment string # @param regex The regex that lines need to match after `comment` # @param comment The prefix of the line that is removed { replace_patterns: "^$(comment)\s?(.*$(regex).*)$" replace_with => uncomment, comment => "Uncomment a line containing a fragment"; } bundle edit_line delete_lines_matching(regex) # @brief Delete lines matching a regular expression # @param regex The regular expression that the lines need to match { delete_lines: "$(regex)" comment => "Delete lines matching regular expressions"; } bundle edit_line warn_lines_matching(regex) # @brief Warn about lines matching a regular expression # @param regex The regular expression that the lines need to match { delete_lines: "$(regex)" comment => "Warn about lines in a file", action => warn_only; } bundle edit_line prepend_if_no_line(string) # @brief Prepend `string` if it doesn't exist in the file # @param string The string to be prepended # # **See also:** [`insert_lines`][insert_lines] in # [`edit_line`][bundle edit_line] { insert_lines: "$(string)" location => start, comment => "Prepend a line to the file if it doesn't already exist"; } bundle edit_line append_if_no_line(str) # @ignore # This duplicates the insert_lines bundle { insert_lines: "$(str)" comment => "Append a line to the file if it doesn't already exist"; } bundle edit_line append_if_no_lines(list) # @ignore # This duplicates the insert_lines bundle { insert_lines: "$(list)" comment => "Append lines to the file if they don't already exist"; } bundle edit_line replace_line_end(start,end) # @brief Give lines starting with `start` the ending given in `end` # # Whitespaces will be left unmodified. For example, # `replace_line_end("ftp", "2121/tcp")` would replace # # `"ftp 21/tcp"` # # with # # `"ftp 2121/tcp"` # # @param start The string lines have to start with # @param end The string lines should end with { field_edits: "\s*$(start)\s.*" comment => "Replace lines with $(this.start) and $(this.end)", edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","set"); } bundle edit_line append_to_line_end(start,end) # @brief Append `end` to any lines beginning with `start` # # `end` will be appended to all lines starting with `start` and not # already ending with `end`. Whitespaces will be left unmodified. # # For example, `append_to_line_end("kernel", "vga=791")` would replace # `kernel /boot/vmlinuz root=/dev/sda7` # # with # # `kernel /boot/vmlinuz root=/dev/sda7 vga=791` # # **WARNING**: Be careful not to have multiple promises matching the same line, which would result in the line growing indefinitely. # # @param start pattern to match lines of interest # @param end string to append to matched lines # # **Example:** # # ```cf3 # files: # "/tmp/boot-options" edit_line => append_to_line_end("kernel", "vga=791"); # ``` # { field_edits: "\s*$(start)\s.*" comment => "Append lines with $(this.start) and $(this.end)", edit_field => line("(^|\s)$(start)\s*", "2", "$(end)","append"); } bundle edit_line regex_replace(find,replace) # @brief Find exactly a regular expression and replace exactly the match with a string. # You can think of this like a PCRE powered sed. # @param find The regular expression # @param replace The replacement string { replace_patterns: "$(find)" replace_with => value("$(replace)"), comment => "Search and replace string"; } bundle edit_line resolvconf(search,list) # @brief Adds search domains and name servers to the system # resolver configuration. # # Use this bundle to modify `resolv.conf`. Existing entries for # `search` and `nameserver` are replaced. # # @param search The search domains with space # @param list An slist of nameserver addresses { delete_lines: "search.*" comment => "Reset search lines from resolver"; "nameserver.*" comment => "Reset nameservers in resolver"; insert_lines: "search $(search)" comment => "Add search domains to resolver"; "nameserver $(list)" comment => "Add name servers to resolver"; } bundle edit_line resolvconf_o(search,list,options) # @brief Adds search domains, name servers and options to the system # resolver configuration. # # Use this bundle to modify `resolv.conf`. Existing entries for # `search`, `nameserver` and `options` are replaced. # # @param search The search domains with space # @param list An slist of nameserver addresses # @param options is an slist of variables to modify the resolver { delete_lines: "search.*" comment => "Reset search lines from resolver"; "nameserver.*" comment => "Reset nameservers in resolver"; "options.*" comment => "Reset options in resolver"; insert_lines: "search $(search)" comment => "Add search domains to resolver"; "nameserver $(list)" comment => "Add name servers to resolver"; "options $(options)" comment => "Add options to resolver"; } bundle edit_line manage_variable_values_ini(tab, sectionName) # @brief Sets the RHS of configuration items in the file of the form # `LHS=RHS` # # If the line is commented out with `#`, it gets uncommented first. # Adds a new line if none exists. # Removes any variable value pairs not defined for the ini section. # # @param tab An associative array containing `tab[sectionName][LHS]="RHS"`. # The value is not changed when the `RHS` is "dontchange" # @param sectionName The section in the file within which values should be # modified # # **See also:** `set_variable_values_ini()` { vars: "index" slist => getindices("$(tab)[$(sectionName)]"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); classes: "edit_$(cindex[$(index)])" not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"), comment => "Create conditions to make changes"; field_edits: # If the line is there, but commented out, first uncomment it "#+\s*$(index)\s*=.*" select_region => INI_section("$(sectionName)"), edit_field => col("=","1","$(index)","set"), ifvarclass => "edit_$(cindex[$(index)])"; # match a line starting like the key something "$(index)\s*=.*" edit_field => col("=","2","$($(tab)[$(sectionName)][$(index)])","set"), select_region => INI_section("$(sectionName)"), classes => if_ok("manage_variable_values_ini_not_$(cindex[$(index)])"), ifvarclass => "edit_$(cindex[$(index)])"; delete_lines: ".*" select_region => INI_section("$(sectionName)"), comment => "Remove all entries in the region so there are no extra entries"; insert_lines: "[$(sectionName)]" location => start, comment => "Insert lines"; "$(index)=$($(tab)[$(sectionName)][$(index)])" select_region => INI_section("$(sectionName)"), ifvarclass => "!manage_variable_values_ini_not_$(cindex[$(index)]).edit_$(cindex[$(index)])"; } bundle edit_line set_variable_values_ini(tab, sectionName) # @brief Sets the RHS of configuration items in the file of the form # `LHS=RHS` # # If the line is commented out with `#`, it gets uncommented first. # Adds a new line if none exists. # # @param tab An associative array containing `tab[sectionName][LHS]="RHS"`. # The value is not changed when the `RHS` is "dontchange" # @param sectionName The section in the file within which values should be # modified # # **See also:** `set_variable_values_ini()` { vars: "index" slist => getindices("$(tab)[$(sectionName)]"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); classes: "edit_$(cindex[$(index)])" not => strcmp("$($(tab)[$(sectionName)][$(index)])","dontchange"), comment => "Create conditions to make changes"; field_edits: # If the line is there, but commented out, first uncomment it "#+\s*$(index)\s*=.*" select_region => INI_section("$(sectionName)"), edit_field => col("=","1","$(index)","set"), ifvarclass => "edit_$(cindex[$(index)])"; # match a line starting like the key something "$(index)\s*=.*" edit_field => col("=","2","$($(tab)[$(sectionName)][$(index)])","set"), select_region => INI_section("$(sectionName)"), classes => if_ok("set_variable_values_ini_not_$(cindex[$(index)])"), ifvarclass => "edit_$(cindex[$(index)])"; insert_lines: "[$(sectionName)]" location => start, comment => "Insert lines"; "$(index)=$($(tab)[$(sectionName)][$(index)])" select_region => INI_section("$(sectionName)"), ifvarclass => "!set_variable_values_ini_not_$(cindex[$(index)]).edit_$(cindex[$(index)])"; } bundle edit_line insert_ini_section(name, config) # @brief Inserts a INI section with content # # ``` # # given an array "barray" # files: # "myfile.ini" edit_line => insert_innit_section("foo", "barray"); # ``` # # Inserts a section in an INI file with the given configuration # key-values from the array `config`. # # @param name the name of the INI section # @param config The fully-qualified name of an associative array containing `v[LHS]="rhs"` { vars: "k" slist => getindices($(config)); insert_lines: "[$(name)]" location => start, comment => "Prepend a line to the file if it doesn't already exist"; "$(k)=$($(config)[$(k)])"; } bundle edit_line set_quoted_values(v) # @brief Sets the RHS of variables in shell-like files of the form: # # ``` # LHS="RHS" # ``` # # Adds a new line if no LHS exists, and replaces RHS values if one does exist. # If the line is commented out with #, it gets uncommented first. # # @param v The fully-qualified name of an associative array containing `v[LHS]="rhs"` # # **Example:** # # ```cf3 # vars: # "stuff[lhs-1]" string => "rhs1"; # "stuff[lhs-2]" string => "rhs2"; # # files: # "myfile" # edit_line => set_quoted_values(stuff) # ``` # # **See also:** `set_variable_values()` { meta: "tags" slist => { "deprecated=3.6.0", "deprecation-reason=Generic reimplementation", "replaced-by=set_line_based" }; vars: "index" slist => getindices("$(v)"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); field_edits: # If the line is there, but commented out, first uncomment it "#+\s*$(index)\s*=.*" edit_field => col("=","1","$(index)","set"); # match a line starting like the key = something "\s*$(index)\s*=.*" edit_field => col("=","2",'"$($(v)[$(index)])"',"set"), classes => if_ok("$(cindex[$(index)])_in_file"), comment => "Match a line starting like key = something"; insert_lines: '$(index)="$($(v)[$(index)])"' comment => "Insert a variable definition", ifvarclass => "!$(cindex[$(index)])_in_file"; } bundle edit_line set_variable_values(v) # @brief Sets the RHS of variables in files of the form: # # ``` # LHS=RHS # ``` # # Adds a new line if no LHS exists, and replaces RHS values if one does exist. # If the line is commented out with #, it gets uncommented first. # # @param v The fully-qualified name of an associative array containing `v[LHS]="rhs"` # # **Example:** # # ```cf3 # vars: # "stuff[lhs-1]" string => "rhs1"; # "stuff[lhs-2]" string => "rhs2"; # # files: # "myfile" # edit_line => set_quoted_values(stuff) # ``` # # **See also:** `set_quoted_values()` { meta: "tags" slist => { "deprecated=3.6.0", "deprecation-reason=Generic reimplementation", "replaced-by=set_line_based" }; vars: "index" slist => getindices("$(v)"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); "cv" string => canonify("$(v)"); field_edits: # match a line starting like the key = something "\s*$(index)\s*=.*" edit_field => col("\s*$(index)\s*=","2","$($(v)[$(index)])","set"), classes => if_ok("$(cv)_$(cindex[$(index)])_in_file"), comment => "Match a line starting like key = something"; insert_lines: "$(index)=$($(v)[$(index)])" comment => "Insert a variable definition", ifvarclass => "!$(cv)_$(cindex[$(index)])_in_file"; } bundle edit_line set_config_values(v) # @brief Sets the RHS of configuration items in the file of the form: # # ``` # LHS RHS # ``` # # If the line is commented out with `#`, it gets uncommented first. # # Adds a new line if none exists. # # @param v The fully-qualified name of an associative array containing `v[LHS]="rhs"` { meta: "tags" slist => { "deprecated=3.6.0", "deprecation-reason=Generic reimplementation", "replaced-by=set_line_based" }; vars: "index" slist => getindices("$(v)"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); # Escape the value (had a problem with special characters and regex's) "ev[$(index)]" string => escape("$($(v)[$(index)])"); # Do we have more than one line commented out? "index_comment_matches_$(cindex[$(index)])" int => countlinesmatching("^\s*#\s*($(index)\s+.*|$(index))$","$(edit.filename)"); classes: # Check to see if this line exists "line_exists_$(cindex[$(index)])" expression => regline("^\s*($(index)\s.*|$(index))$","$(edit.filename)"); # if there's more than one comment, just add new (don't know who to use) "multiple_comments_$(cindex[$(index)])" expression => isgreaterthan("$(index_comment_matches_$(cindex[$(index)]))","1"); replace_patterns: # If the line is commented out, uncomment and replace with # the correct value "^\s*#\s*($(index)\s+.*|$(index))$" comment => "Uncommented the value $(index)", replace_with => value("$(index) $($(v)[$(index)])"), ifvarclass => "!line_exists_$(cindex[$(index)]).!replace_attempted_$(cindex[$(index)]).!multiple_comments_$(cindex[$(index)])", classes => always("uncommented_$(cindex[$(index)])"); # If the line is there with the wrong value, replace with # the correct value "^\s*($(index)\s+(?!$(ev[$(index)])$).*|$(index))$" comment => "Correct the value $(index)", replace_with => value("$(index) $($(v)[$(index)])"), classes => always("replace_attempted_$(cindex[$(index)])"); insert_lines: # If the line doesn't exist, or there is more than one occurance # of the LHS commented out, insert a new line and try to place it # after the commented LHS (keep new line with old comments) "$(index) $($(v)[$(index)])" comment => "Insert the value, marker exists $(index)", location => after("^\s*#\s*($(index)\s+.*|$(index))$"), ifvarclass => "replace_attempted_$(cindex[$(index)]).multiple_comments_$(cindex[$(index)])"; # If the line doesn't exist and there are no occurances # of the LHS commented out, insert a new line at the eof "$(index) $($(v)[$(index)])" comment => "Insert the value, marker doesn't exist $(index)", ifvarclass => "replace_attempted_$(cindex[$(index)]).!multiple_comments_$(cindex[$(index)])"; } bundle edit_line set_line_based(v, sep, bp, kp, cp) # @brief Sets the RHS of configuration items in the file of the form: # # ``` # LHS$(sep)RHS # ``` # # Example usage for `x=y` lines (e.g. rsyncd.conf): # # ```cf3 # "myfile" # edit_line => set_line_based("test.config", "=", "\s*=\s*", ".*", "\s*#\s*"); # ``` # # Example usage for `x y` lines (e.g. sshd_config): # # ```cf3 # "myfile" # edit_line => set_line_based("test.config", " ", "\s+", ".*", "\s*#\s*"); # ``` # # If the line is commented out with `$(cp)`, it gets uncommented first. # # Adds a new line if none exists or if more than one commented-out # possible matches exist. # # Originally `set_config_values` by Ed King. # # @param v The fully-qualified name of an associative array containing `v[LHS]="rhs"` # @param sep The separator to insert, e.g. ` ` for space-separated # @param bp The key-value separation regex, e.g. `\s+` for space-separated # @param kp The keys to select from v, use `.*` for all # @param cp The comment pattern from line-start, e.g. `\s*#\s*` { meta: "tags" slist => { "replaces=set_config_values", "replaces=set_config_values_matching", "replaces=set_variable_values", "replaces=set_quoted_values", "replaces=maintain_key_values", }; vars: "vkeys" slist => getindices("$(v)"); "i" slist => grep($(kp), vkeys); # Be careful if the index string contains funny chars "ci[$(i)]" string => canonify("$(i)"); # Escape the value (had a problem with special characters and regex's) "ev[$(i)]" string => escape("$($(v)[$(i)])"); # Do we have more than one line commented out? "comment_matches_$(ci[$(i)])" int => countlinesmatching("^$(cp)($(i)$(bp).*|$(i))$", $(edit.filename)); classes: # Check to see if this line exists "exists_$(ci[$(i)])" expression => regline("^\s*($(i)$(bp).*|$(i))$", $(edit.filename)); # if there's more than one comment, just add new (don't know who to use) "multiple_comments_$(ci[$(i)])" expression => isgreaterthan("$(comment_matches_$(ci[$(i)]))", "1"); replace_patterns: # If the line is commented out, uncomment and replace with # the correct value "^$(cp)($(i)$(bp).*|$(i))$" comment => "Uncommented the value '$(i)'", replace_with => value("$(i)$(sep)$($(v)[$(i)])"), ifvarclass => "!exists_$(ci[$(i)]).!replace_attempted_$(ci[$(i)]).!multiple_comments_$(ci[$(i)])", classes => always("uncommented_$(ci[$(i)])"); # If the line is there with the wrong value, replace with # the correct value "^\s*($(i)$(bp)(?!$(ev[$(i)])$).*|$(i))$" comment => "Correct the value '$(i)'", replace_with => value("$(i)$(sep)$($(v)[$(i)])"), classes => always("replace_attempted_$(ci[$(i)])"); insert_lines: # If the line doesn't exist, or there is more than one occurrence # of the LHS commented out, insert a new line and try to place it # after the commented LHS (keep new line with old comments) "$(i)$(sep)$($(v)[$(i)])" comment => "Insert the value, marker '$(i)' exists", location => after("^$(cp)($(i)$(bp).*|$(i))$"), ifvarclass => "replace_attempted_$(ci[$(i)]).multiple_comments_$(ci[$(i)])"; # If the line doesn't exist and there are no occurrences # of the LHS commented out, insert a new line at the eof "$(i)$(sep)$($(v)[$(i)])" comment => "Insert the value, marker '$(i)' doesn't exist", ifvarclass => "replace_attempted_$(ci[$(i)]).!multiple_comments_$(ci[$(i)]).!exists_$(ci[$(i)])"; reports: verbose_mode|EXTRA:: "$(this.bundle): Line for '$(i)' exists" ifvarclass => "exists_$(ci[$(i)])"; "$(this.bundle): Line for '$(i)' does not exist" ifvarclass => "!exists_$(ci[$(i)])"; } bundle edit_line set_config_values_matching(v,pat) # @brief Sets the RHS of configuration items in the file of the form # # ``` # LHS RHS # ``` # # If the line is commented out with `#`, it gets uncommented first. # Adds a new line if none exists. # # @param v the fully-qualified name of an associative array containing v[LHS]="rhs" # @param pat Only elements of `v` that match the regex `pat` are use { meta: "tags" slist => { "deprecated=3.6.0", "deprecation-reason=Generic reimplementation", "replaced-by=set_line_based" }; vars: "allparams" slist => getindices("$(v)"); "index" slist => grep("$(pat)", "allparams"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); replace_patterns: # If the line is there, maybe commented out, uncomment and replace with # the correct value "^\s*($(index)\s+(?!$($(v)[$(index)])).*|# ?$(index)\s+.*)$" comment => "Correct the value", replace_with => value("$(index) $($(v)[$(index)])"), classes => always("replace_attempted_$(cindex[$(index)])"); insert_lines: "$(index) $($(v)[$(index)])" ifvarclass => "replace_attempted_$(cindex[$(index)])"; } bundle edit_line maintain_key_values(v,sep) # @ignore # @brief Sets the RHS of configuration items with an giving separator # # Contributed by David Lee { meta: "tags" slist => { "deprecated=3.6.0", "deprecation-reason=Generic reimplementation", "replaced-by=set_line_based" }; vars: "index" slist => getindices("$(v)"); # Be careful if the index string contains funny chars "cindex[$(index)]" string => canonify("$(index)"); # Matching pattern for line (basically key-and-separator) "keypat[$(index)]" string => "\s*$(index)\s*$(sep)\s*"; # Values may contain regexps. Escape them for replace_pattern matching. "ve[$(index)]" string => escape("$($(v)[$(index)])"); classes: "$(cindex[$(index)])_key_in_file" comment => "Dynamic Class created if patterns matching", expression => regline("^$(keypat[$(index)]).*", "$(edit.filename)"); replace_patterns: # For convergence need to use negative lookahead on value: # "key sep (?!value).*" "^($(keypat[$(index)]))(?!$(ve[$(index)])$).*" comment => "Replace definition of $(index)", replace_with => value("$(match.1)$($(v)[$(index)])"); insert_lines: "$(index)$(sep)$($(v)[$(index)])" comment => "Insert definition of $(index)", ifvarclass => "!$(cindex[$(index)])_key_in_file"; } bundle edit_line append_users_starting(v) # @brief For adding to `/etc/passwd` or `etc/shadow` # @param v An array `v[username] string => "line..."` # # **Note:** To manage local users with CFEngine 3.6 and later, # consider making `users` promises instead of modifying system files. { vars: "index" slist => getindices("$(v)"); classes: "add_$(index)" not => userexists("$(index)"), comment => "Class created if user does not exist"; insert_lines: "$($(v)[$(index)])" comment => "Append users into a password file format", ifvarclass => "add_$(index)"; } bundle edit_line append_groups_starting(v) # @brief For adding groups to `/etc/group` # @param v An array `v[groupname] string => "line..."` # # **Note:** To manage local users with CFEngine 3.6 and later, # consider making `users` promises instead of modifying system files. { vars: "index" slist => getindices("$(v)"); classes: "add_$(index)" not => groupexists("$(index)"), comment => "Class created if group does not exist"; insert_lines: "$($(v)[$(index)])" comment => "Append users into a group file format", ifvarclass => "add_$(index)"; } bundle edit_line set_colon_field(key,field,val) # @brief Set the value of field number `field` of the line whose # first field is `key` to the value `val`, in a colon-separated file. # @param key The value the first field has to match # @param field The field to be modified # @param val The new value of `field` { field_edits: "$(key):.*" comment => "Edit a colon-separated file, using the first field as a key", edit_field => col(":","$(field)","$(val)","set"); } bundle edit_line set_user_field(user,field,val) # @brief Set the value of field number "field" in a `:-field` # formatted file like `/etc/passwd` # @param user The user to be modified # @param field The field that should be modified # @param val The value for `field` # # **Note:** To manage local users with CFEngine 3.6 and later, # consider making `users` promises instead of modifying system files. { field_edits: "$(user):.*" comment => "Edit a user attribute in the password file", edit_field => col(":","$(field)","$(val)","set"); } bundle edit_line append_user_field(group,field,allusers) # @brief For adding users to to a file like `/etc/group` # at field position `field`, comma separated subfields # @param group The group to be modified # @param field The field where users should be added # @param allusers The list of users to add to `field` # # **Note:** To manage local users with CFEngine 3.6 and later, # consider making `users` promises instead of modifying system files. { vars: "val" slist => { @(allusers) }; field_edits: "$(group):.*" comment => "Append users into a password file format", edit_field => col(":","$(field)","$(val)","alphanum"); } bundle edit_line expand_template(templatefile) # @brief Read in the named text file and expand `$(var)` inside the file # @param templatefile The name of the file { insert_lines: "$(templatefile)" insert_type => "file", comment => "Expand variables in the template file", expand_scalars => "true"; } bundle edit_line replace_or_add(pattern,line) # @brief Replace a pattern in a file with a single line. # # If the pattern is not found, add the line to the file. # # @param pattern The pattern that should be replaced # The pattern must match the whole line (it is automatically # anchored to the start and end of the line) to avoid # ambiguity. # @param line The line with which to replace matches of `pattern` { vars: "cline" string => canonify("$(line)"); "eline" string => escape("$(line)"); replace_patterns: "^(?!$(eline)$)$(pattern)$" comment => "Replace a pattern here", replace_with => value("$(line)"), classes => always("replace_done_$(cline)"); insert_lines: "$(line)" ifvarclass => "replace_done_$(cline)"; } bundle edit_line converge(marker, lines) # @brief Converge `lines` marked with `marker` # # Any content marked with `marker` is removed, then `lines` are # inserted. Every `line` should contain `marker`. # # @param marker The marker (not a regular expression; will be escaped) # @param lines The lines to insert; all must contain `marker` { vars: "regex" string => escape($(marker)); delete_lines: "$(regex)" comment => "Delete lines matching the marker"; insert_lines: "$(lines)" comment => "Insert the given lines"; } bundle edit_line fstab_option_editor(method, mount, option) # @brief Add or remove `/etc/fstab` options for a mount # # This bundle edits the options field of a mount. The `method` is a # `field_operation` which can be `append`, `prepend`, `set`, `delete`, # or `alphanum`. The option is OS-specific. # # @param method `field_operation` to apply # @param mount the mount point # @param option the option to add or remove # # **Example:** # # ```cf3 # files: # "/etc/fstab" edit_line => fstab_option_editor("delete", "/", "acl"); # "/etc/fstab" edit_line => fstab_option_editor("append", "/", "acl"); # ``` { field_edits: "(?!#)\S+\s+$(mount)\s.+" edit_field => fstab_options($(option), $(method)); } body edit_field fstab_options(newval, method) # @brief Edit the options field in a fstab format # @param newval the new option # @param method `field_operation` to apply # # This body edits the options field in the fstab file format. The # `method` is a `field_operation` which can be `append`, `prepend`, # `set`, `delete`, or `alphanum`. The `newval` option is OS-specific. # # **Example:** # # ```cf3 # # from the `fstab_options_editor` # field_edits: # "(?!#)\S+\s+$(mount)\s.+" # edit_field => fstab_options($(option), $(method)); # ``` { field_separator => "\s+"; select_field => "4"; value_separator => ","; field_value => "$(newval)"; field_operation => "$(method)"; } body edit_field quoted_var(newval,method) # @brief Edit the quoted value of the matching line # @param newval The new value # @param method The method by which to edit the field { field_separator => "\""; select_field => "2"; value_separator => " "; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "false"; allow_blank_fields => "true"; } body edit_field col(split,col,newval,method) # @brief Edit tabluar data with comma-separated sub-values # @param split The separator that defines columns # @param col The (1-based) index of the value to change # @param newval The new value # @param method The method by which to edit the field { field_separator => "$(split)"; select_field => "$(col)"; value_separator => ","; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "true"; allow_blank_fields => "true"; } body edit_field line(split,col,newval,method) # @brief Edit tabular data with space-separated sub-values # @param split The separator that defines columns # @param col The (1-based) index of the value to change # @param newval The new value # @param method The method by which to edit the field { field_separator => "$(split)"; select_field => "$(col)"; value_separator => " "; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "true"; allow_blank_fields => "true"; } body replace_with value(x) # @brief Replace matching lines # @param x The replacement string { replace_value => "$(x)"; occurrences => "all"; } body select_region INI_section(x) # @brief Restrict the `edit_line` promise to the lines in section `[x]` # @param x The name of the section in an INI-like configuration file { select_start => "\[$(x)\]\s*"; select_end => "\[.*\]\s*"; } body edit_defaults empty # @brief Empty the file before editing # # No backup is made { empty_file_before_editing => "true"; edit_backup => "false"; #max_file_size => "300000"; } body location start # @brief Editing occurs before the matched line { before_after => "before"; } body location after(str) # @brief Editing occurs after the line matching `str` # @param str Regular expression matching the file line location { before_after => "after"; select_line_matching => "$(str)"; } body location before(str) # @brief Editing occurs before the line matching `str` # @param str Regular expression matching the file line location { before_after => "before"; select_line_matching => "$(str)"; } body replace_with comment(c) # @brief Comment all lines matching the pattern by preprending `c` # @param c The prefix that comments out lines { replace_value => "$(c) $(match.1)"; occurrences => "all"; } body replace_with uncomment # @brief Uncomment all lines matching the pattern by removing # anything outside the matching string { replace_value => "$(match.1)"; occurrences => "all"; } body copy_from secure_cp(from,server) # @brief Download a file from a remote server over an encrypted channel # # Only copy the file if it is different from the local copy, and verify # that the copy is correct. # # @param from The location of the file on the remote server # @param server The hostname or IP of the server from which to download { source => "$(from)"; servers => { "$(server)" }; compare => "digest"; encrypt => "true"; verify => "true"; } body copy_from remote_cp(from,server) # @brief Download a file from a remote server. # # @param from The location of the file on the remote server # @param server The hostname or IP of the server from which to download { servers => { "$(server)" }; source => "$(from)"; compare => "mtime"; } body copy_from remote_dcp(from,server) # @brief Download a file from a remote server if it is different from the local copy. # # @param from The location of the file on the remote server # @param server The hostname or IP of the server from which to download { servers => { "$(server)" }; source => "$(from)"; compare => "digest"; } body copy_from local_cp(from) # @brief Copy a local file. # # @param from The path to the source file. { source => "$(from)"; } body copy_from local_dcp(from) # @brief Copy a local file if it is different from the existing copy. # # @param from The path to the source file. { source => "$(from)"; compare => "digest"; } body copy_from perms_cp(from) # @brief Copy a local file and preserve file permissions on the local copy. # # @param from The path to the source file. { source => "$(from)"; preserve => "true"; } body copy_from backup_local_cp(from) # @brief Copy a local file and keep a backup of old versions. # # @param from The path to the source file. { source => "$(from)"; copy_backup => "timestamp"; } body copy_from seed_cp(from) # @brief Copy a local file if the file does not already exist, i.e. seed the placement # # @param from The path to the source file. { source => "$(from)"; compare => "exists"; } body copy_from sync_cp(from,server) # @brief Download a file if the local copy does not already exist, i.e. seed the placement # # @param from The location of the file on the remote server # @param server The hostname or IP of the server from which to download { servers => { "$(server)" }; source => "$(from)"; purge => "true"; preserve => "true"; type_check => "false"; } body copy_from no_backup_cp(from) # @brief Copy a local file and don't make any backup of the previous version # # @param from The path to the source file. { source => "$(from)"; copy_backup => "false"; } body copy_from no_backup_dcp(from) # @brief Copy a local file if contents have changed, and don't make any backup # of the previous version # # @param from The path to the source file. { source => "$(from)"; copy_backup => "false"; compare => "digest"; } body link_from linkfrom(source, type) # @brief Make any kind of link to a file # @param source link to this # @param type the link's type (`symlink` or `hardlink`) { source => $(source); link_type => $(type); } body perms m(mode) # @brief Set the file mode # @param mode The new mode { mode => "$(mode)"; } body perms mo(mode,user) # @brief Set the file's mode and owners # @param mode The new mode # @param user The username of the new owner { owners => { "$(user)" }; mode => "$(mode)"; } body perms mog(mode,user,group) # @brief Set the file's mode, owner and group # @param mode The new mode # @param user The username of the new owner # @param group The group name { owners => { "$(user)" }; groups => { "$(group)" }; mode => "$(mode)"; } body perms og(u,g) # @brief Set the file's owner and group # @param u The username of the new owner # @param g The group name { owners => { "$(u)" }; groups => { "$(g)" }; } body perms owner(user) # @brief Set the file's owner # @param user The username of the new owner { owners => { "$(user)" }; } body perms system_owned(mode) # @brief Set the file owner and group to the system default # @param mode the access permission in octal format # # **Example:** # # ```cf3 # files: # "/etc/passwd" perms => system_owned("0644"); # ``` { mode => "$(mode)"; owners => { "root" }; freebsd|openbsd|netbsd|darwin:: groups => { "wheel" }; linux:: groups => { "root" }; solaris:: groups => { "sys" }; } body depth_search recurse(d) # @brief Search files and direcories recursively, up to the specified depth # Directories on different devices are included. # # @param d The maximum search depth { depth => "$(d)"; xdev => "true"; } body depth_search recurse_ignore(d,list) # @brief Search files and directories recursively, # but don't recurse into the specified directories # # @param d The maximum search depth # @param list The list of directories to be excluded { depth => "$(d)"; exclude_dirs => { @(list) }; } body depth_search recurse_with_base(d) # @brief Search files and directories recursively up to the specified # depth, starting from the base directory and including directories on # other devices. # # @param d The maximum search depth { depth => "$(d)"; xdev => "true"; include_basedir => "true"; } body delete tidy # @brief Delete the file and remove empty directories # and links to directories { dirlinks => "delete"; rmdirs => "true"; } body file_select all # @brief Select all file system entries { leaf_name => { ".*" }; file_result => "leaf_name"; } body changes all_changes # @brief Detect all file changes using sha256 # and report the diff to CFEngine Enterprise { hash => "sha256"; report_changes => "all"; report_diffs => "true"; update_hashes => "yes"; } bundle agent file_mustache(mustache_file, json_file, target_file) # @brief Make a file from a Mustache template and a JSON file # @param mustache_file the file with the Mustache template # @param json_file a file with JSON data # @param target_file the target file to write # # **Example:** # # ```cf3 # methods: # "m" usebundle => file_mustache("x.mustache", "y.json", "z.txt"); # ``` { files: "$(target_file)" create => "true", edit_template => $(mustache_file), template_data => readjson($(json_file), "100k"), template_method => "mustache"; } bundle agent file_mustache_jsonstring(mustache_file, json_string, target_file) # @brief Make a file from a Mustache template and a JSON string # @param mustache_file the file with the Mustache template # @param json_string a string with JSON data # @param target_file the target file to write # # **Example:** # # ```cf3 # methods: # "m" usebundle => file_mustache_jsonstring("x.mustache", '{ "x": "y" }', "z.txt"); # ``` { files: "$(target_file)" create => "true", edit_template => $(mustache_file), template_data => parsejson($(json_string)), template_method => "mustache"; } bundle agent file_tidy(file) # @brief Remove a file # @param file to remove # # **Example:** # # ```cf3 # methods: # "" usebundle => file_tidy("/tmp/z.txt"); # ``` { files: "$(file)" delete => tidy; reports: inform_mode|EXTRA:: "$(this.bundle): deleting $(file) with delete => tidy"; } bundle agent dir_sync(from, to) # @brief Synchronize a directory entire, deleting unknown files # @param from source directory # @param to destination directory # # **Example:** # # ```cf3 # methods: # "" usebundle => dir_sync("/tmp", "/var/tmp"); # ``` { files: "$(to)/." create => "true", depth_search => recurse("inf"), copy_from => copyfrom_sync($(from)); reports: inform_mode|EXTRA:: "$(this.bundle): copying directory $(from) to $(to)"; } bundle agent file_copy(from, to) # @brief Copy a file # @param from source file # @param to destination file # # **Example:** # # ```cf3 # methods: # "" usebundle => file_copy("/tmp/z.txt", "/var/tmp/y.txt"); # ``` { files: "$(to)" copy_from => copyfrom_sync($(from)); reports: inform_mode|EXTRA:: "$(this.bundle): copying file $(from) to $(to)"; } body copy_from copyfrom_sync(f) # @brief Copy a directory or file with digest checksums, preserving attributes and purging leftovers # @param f the file or directory { source => "$(f)"; purge => "true"; preserve => "true"; type_check => "false"; compare => "digest"; } bundle agent file_make(file, str) # @brief Make a file from a string # @param file target # @param str the string data # # **Example:** # # ```cf3 # methods: # "" usebundle => file_make("/tmp/z.txt", "Some text # and some more text here"); # ``` { files: "$(file)" create => "true", edit_line => insert_lines($(str)), edit_defaults => empty; reports: inform_mode|EXTRA:: "$(this.bundle): creating $(file) with contents '$(str)'"; } bundle agent file_empty(file) # @brief Make an empty file # @param file target # # **Example:** # # ```cf3 # methods: # "" usebundle => file_empty("/tmp/z.txt"); # ``` { files: "$(file)" create => "true", edit_defaults => empty; reports: inform_mode|EXTRA:: "$(this.bundle): creating empty $(file) with 0 size"; } bundle agent file_hardlink(target, link) # @brief Make a hard link to a file # @param target of link # @param link the hard link's location # # **Example:** # # ```cf3 # methods: # "" usebundle => file_hardlink("/tmp/z.txt", "/tmp/z.link"); # ``` { files: "$(link)" move_obstructions => "true", link_from => linkfrom($(target), "hardlink"); reports: inform_mode|EXTRA:: "$(this.bundle): $(link) will be a hard link to $(target)"; } bundle agent file_link(target, link) # @brief Make a symlink to a file # @param target of symlink # @param link the symlink's location # # **Example:** # # ```cf3 # methods: # "" usebundle => file_link("/tmp/z.txt", "/tmp/z.link"); # ``` { files: "$(link)" move_obstructions => "true", link_from => linkfrom($(target), "symlink"); reports: inform_mode|EXTRA:: "$(this.bundle): $(link) will be a symlink to $(target)"; } cfengine-3.6.2/tests/acceptance/20_meta/0000755000175100017510000000000012316547775017514 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/20_meta/basic.cf0000644000175100017510000000316112316547775021110 0ustar00a10038a1003800000000000000####################################################### # # Test basics of meta promises # ####################################################### body common control { inputs => { "../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { meta: "s" string => "Wally Walleye"; "l" slist => { "Be", "Hg", "Pb" }; "c" data => parsejson(' { "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null } '); } bundle agent check { vars: "actual[s]" string => $(test_meta.s); "actual[l]" string => format("%S", "test_meta.l"); "actual[c]" string => format("%S", "test_meta.c"); "expected[s]" string => "Wally Walleye"; "expected[l]" string => '{ "Be", "Hg", "Pb" }'; "expected[c]" string => '{ "first": 1, "seconds": 2, "third": [ "a", "b", "c" ], "fourth": null }'; "tests" slist => getindices(expected); classes: "ok_$(tests)" expression => strcmp("$(actual[$(tests)])", "$(expected[$(tests)])"); "ok_$(tests)" not => strcmp("$(actual[$(tests)])", "$(expected[$(tests)])"); "ok" and => { "ok_s", "ok_l", "ok_c" }; reports: DEBUG:: "OK: $(tests) got $(actual[$(tests)])" ifvarclass => "ok_$(tests)"; "FAIL: $(tests) got $(actual[$(tests)]) != $(expected[$(tests)])" ifvarclass => "not_ok_$(tests)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/0000755000175100017510000000000012236160673020210 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/02_classes/03_os/0000755000175100017510000000000012316547775021146 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/02_classes/03_os/powershell.cf0000644000175100017510000000331112316547775023642 0ustar00a10038a1003800000000000000####################################################### # # Test powershell class # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => { "!windows", "!powershell" }; # This relies on powershell being in the path, which it should be for a standard install. "detected_powershell" expression => regcmp(".*Succeeded.*", execresult("powershell Get-Content $(G.cwd)$(const.dirsep)text.txt", "useshell")); "ok" and => { "windows", "powershell", "detected_powershell" }; "ok" and => { "windows", "!powershell", "!detected_powershell" }; reports: DEBUG.windows.powershell.!detected_powershell:: "Powershell was detected by CFEngine, but not by the test."; DEBUG.windows.!powershell.detected_powershell:: "Powershell was detected by the test, but not by CFEngine."; DEBUG.windows.powershell.detected_powershell:: "Powershell was detected by CFEngine and the test."; DEBUG.windows.!powershell.!detected_powershell:: "Powershell was not detected by the test, nor by CFEngine."; DEBUG.!windows.powershell:: "Powershell was detected on a non-Windows system."; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/03_os/text.txt0000644000175100017510000000001212236160673022651 0ustar00a10038a1003800000000000000Succeeded cfengine-3.6.2/tests/acceptance/02_classes/02_functions/0000755000175100017510000000000012404565361022521 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/02_classes/02_functions/017.cf0000644000175100017510000000176412243421446023346 0ustar00a10038a1003800000000000000####################################################### # # Test classmatch() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => { classmatch("any"), classmatch("cfengine"), classmatch("cf.*"), classmatch("Hr.*"), classmatch("Yr.*"), classmatch("Min.*"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/laterthan.cf0000644000175100017510000000761012404565361025021 0ustar00a10038a1003800000000000000####################################################### # # Test laterthan() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent test { classes: # On 32-bit systems, dates before 1901-12-13 aren't representable "after_year_1902" expression => laterthan(1902,1,1,0,0,0), scope => "namespace"; "after_year_1902_month" expression => laterthan(1902,12,1,0,0,0), scope => "namespace"; "after_year_1902_day" expression => laterthan(1902,12,31,0,0,0), scope => "namespace"; "after_year_1902_hour" expression => laterthan(1902,12,31,23,0,0), scope => "namespace"; "after_year_1902_minute" expression => laterthan(1902,12,31,23,59,0), scope => "namespace"; "after_year_1902_second" expression => laterthan(1902,12,31,23,59,59), scope => "namespace"; # On 32-bit systems, dates after 2038-01-18 aren't representable "after_year_2037" expression => laterthan(2037,1,1,0,0,0), scope => "namespace"; "after_year_2037_month" expression => laterthan(2037,12,1,0,0,0), scope => "namespace"; "after_year_2037_day" expression => laterthan(2037,12,31,0,0,0), scope => "namespace"; "after_year_2037_hour" expression => laterthan(2037,12,31,23,0,0), scope => "namespace"; "after_year_2037_minute" expression => laterthan(2037,12,31,23,59,0), scope => "namespace"; "after_year_2037_second" expression => laterthan(2037,12,31,23,59,59), scope => "namespace"; } ####################################################### bundle agent check { vars: DEBUG:: # The date and time now, in laterthan-compatible format: "present" string => execresult("$(G.date) +(%Y,%m,%d,%H,%M,%S)", "noshell"); # NB: shell would try to sub-shell on this (...), hence noshell. classes: "check_after_year_1902" and => { "after_year_1902", "after_year_1902_month", "after_year_1902_day", "after_year_1902_hour", "after_year_1902_minute", "after_year_1902_second" }; "check_after_year_2037" or => { "after_year_2037", "after_year_2037_month", "after_year_2037_day", "after_year_2037_hour", "after_year_2037_minute", "after_year_2037_second" }; "ok" expression => "check_after_year_1902.!check_after_year_2037"; reports: DEBUG.!after_year_1902:: "Failed laterthan(1902,1,1,0,0,0); year"; DEBUG.!after_year_1902_month:: "Failed laterthan(1902,12,1,0,0,0); month"; DEBUG.!after_year_1902_day:: "Failed laterthan(1902,12,31,0,0,0); day"; DEBUG.!after_year_1902_hour:: "Failed laterthan(1902,12,31,23,0,0); hour"; DEBUG.!after_year_1902_minute:: "Failed laterthan(1902,12,31,23,59,0); minute"; DEBUG.!after_year_1902_second:: "Failed laterthan(1902,12,31,23,59,59); second"; DEBUG.after_year_2037:: "Satisfied laterthan(2037,1,1,0,0,0); year"; DEBUG.after_year_2037_month:: "Satisfied laterthan(2037,12,1,0,0,0); month"; DEBUG.after_year_2037_day:: "Satisfied laterthan(2037,12,31,0,0,0); day"; DEBUG.after_year_2037_hour:: "Satisfied laterthan(2037,12,31,23,0,0); hour"; DEBUG.after_year_2037_minute:: "Satisfied laterthan(2037,12,31,23,59,0); minute"; DEBUG.after_year_2037_second:: "Satisfied laterthan(2037,12,31,23,59,59); second"; DEBUG.!ok:: "The time now is '$(present)'"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/015.cf0000644000175100017510000000340212332665147023342 0ustar00a10038a1003800000000000000####################################################### # # Test islink() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "testfile" string => "/tmp/TEST.cfengine"; } ####################################################### bundle agent init { files: "$(G.testfile)" create => "true"; "$(G.testfile).dir/." create => "true"; "$(G.testfile).link" link_from => test_link("$(G.testfile)"); } body link_from test_link(original) { source => "$(original)"; link_type => "symlink"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "windows", meta => { "redmine4608" }; vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "good" and => { islink("$(G.testfile).link"), }; "bad" or => { islink("$(G.testfile).dir"), islink("$(G.testfile).dir/"), islink("$(G.testfile)"), islink("$(G.testfile).does-not-exist"), }; "ok" expression => "good&!bad"; reports: DEBUG.good:: "As expected, $(G.testfile).link is a symlink to $(G.testfile)"; DEBUG.bad:: "One of these is detected as a symlink: $(G.testfile).dir, $(G.testfile), $(G.testfile).does-not-exist"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { methods: "any" usebundle => dcs_fini("$(G.testfile)"); } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/makerule.cf0000644000175100017510000000441312332665147024645 0ustar00a10038a1003800000000000000####################################################### # # Test makerule() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "lold" slist => { "$(G.etc_passwd)", "$(G.etc_group)" }; "lnew" slist => { "$(G.etc_passwd)", "$(G.testfile)" }; "lnon" slist => { "$(G.etc_passwd)", "/etc/NoFriggin'WayThisExi5ts" }; files: "$(G.testfile)" create => "true"; "$(G.testfile).nosuchfile" delete => tidy; } ####################################################### bundle agent check { classes: # A new file does not need to be rebuilt from an older file (fails) "ok1" expression => makerule("$(G.testfile)", "$(G.etc_passwd)"); # An older file does need to be rebuilt from a newer file "ok2" expression => makerule("$(G.etc_passwd)", "$(G.testfile)"); # An older file cannot be rebuilt from a non existent file (fails) "ok3" expression => makerule("$(G.etc_passwd)", "$(G.testfile).nosuchfile"); # An non existent file does need to be rebuilt from a source file "ok4" expression => makerule("$(G.testfile).nosuchfile", "$(G.etc_passwd)"); # A new file does not need to be rebuilt from an older file (fails) "ok5" expression => makerule("$(G.testfile)", "@(test.lold)"); # An old file does need to be rebuilt from an newer file in a list "ok6" expression => makerule("$(G.etc_passwd)", "@(test.lnew)"); # An old file does not need to be rebuilt from sources with a missing file (fails) "ok7" expression => makerule("$(G.etc_passwd)", "@(test.lnon)"); "ok" and => { "!ok1", "ok2", "!ok3", "ok4", "!ok5", "ok6", "!ok7" }; reports: DEBUG.ok1:: "1. pass"; DEBUG.ok2:: "2. pass"; DEBUG.ok3:: "3. pass"; DEBUG.ok4:: "4. pass"; DEBUG.ok5:: "5. pass"; DEBUG.ok6:: "6. pass"; DEBUG.ok7:: "7. pass"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/011.cf0000644000175100017510000000152612316547775023353 0ustar00a10038a1003800000000000000####################################################### # # Test isplain() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { isplain("$(G.etc_passwd)"), isplain("$(G.etc)"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/classes_body_function_param.cf0000644000175100017510000000176112332665147030602 0ustar00a10038a1003800000000000000####################################################### # # Test that a classes body can take a function as a parameter # Redmine:4319 (https://cfengine.com/dev/issues/4319) ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { vars: "filename" string => "this is a filename"; methods: "test" usebundle => noop, classes => if_repaired(canonify("define_a_class_$(filename)")); } ####################################################### bundle agent noop { reports: !any:: "never"; } bundle agent check { classes: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/004.cf0000644000175100017510000000223612243421446023335 0ustar00a10038a1003800000000000000####################################################### # # Test strcmp() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "null" string => ""; "one" int => "1"; classes: "should_fail" or => { strcmp("$(null)", "$(one)"), strcmp("01", "$(one)"), strcmp("init.x", "$(init.x)") }; "should_pass" not => "should_fail"; "ok" and => { "should_pass", strcmp("", "$(null)"), strcmp("1", "$(one)"), strcmp("dummy", "$(init.dummy)") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/016.cf0000644000175100017510000000266412243421446023345 0ustar00a10038a1003800000000000000####################################################### # # Test isvariable() on arrays # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "a[b]" string => "c"; "a[x][y]" string => "z"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "a[b]" string => "c"; "a[x][y]" string => "z"; classes: "should_fail" or => { isvariable("g.a"), isvariable("g.a[c]"), isvariable("g.a[x]"), isvariable("g.a[x][y][z]"), isvariable("a"), isvariable("a[c]"), isvariable("a[x]"), isvariable("a[x][y][z]"), }; "ok" and => { "!should_fail", isvariable("g.a[b]"), isvariable("g.a[x][y]"), isvariable("a[b]"), isvariable("a[x][y]"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/usemodule.cf0000644000175100017510000000504612316547775025055 0ustar00a10038a1003800000000000000####################################################### # # Test usemodule() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_location" string => dirname("$(this.promise_filename)"); classes: "ok_to_run" not => regcmp("/var/cfengine|.*\.cf-agent", "$(sys.workdir)"); files: ok_to_run:: "$(sys.workdir)/modules/usemodule.cf.bat" create => "true", perms => usemodule_perms, edit_line => usemodule_lines; } bundle edit_line usemodule_lines { insert_lines: windows:: "@echo off"; "\"$(init.script_location)\usemodule.cf.bat\""; !windows:: "#!/bin/sh"; ". \"$(init.script_location)/usemodule.cf.bat\""; delete_lines: ".*"; } body perms usemodule_perms { mode => "755"; } ####################################################### bundle agent test { classes: "ok_to_run" not => regcmp("/var/cfengine|.*\.cf-agent", "$(sys.workdir)"); classes: ok_to_run:: # Should be undefined by the following script. "undefined_class" expression => "any"; "function_ok" expression => usemodule("usemodule.cf.bat", ""); "defined_variable" expression => strcmp("$(usemodule_cf_bat.defined_variable)", "yes"); "ok" and => { "function_ok", "defined_class", "!undefined_class", "defined_variable" }; vars: ok:: "ok" string => "yes"; reports: !ok_to_run:: "Must be run using testall script"; ok_to_run.DEBUG.!function_ok:: "usemodule did not execute correctly."; ok_to_run.DEBUG.!defined_class:: "defined_class was not set, but should be."; ok_to_run.DEBUG.undefined_class:: "undefined_class was set, but shouldn't be."; ok_to_run.DEBUG.!defined_variable:: "defined_variable was not set, but should be."; ok_to_run.DEBUG.function_ok:: "usemodule executed correctly."; ok_to_run.DEBUG.defined_class:: "defined_class was set."; ok_to_run.DEBUG.!undefined_class:: "undefined_class was not set."; ok_to_run.DEBUG.defined_variable:: "defined_variable was set."; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("$(test.ok)", "yes"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/returnszero.cf0000644000175100017510000001503412332665147025443 0ustar00a10038a1003800000000000000####################################################### # # Test returnszero() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; meta: "test_suppress_fail" string => "windows", meta => { "redmine4687" }; } ####################################################### bundle agent check { vars: windows:: "zero_rel" string => "fc $(this.promise_filename) $(this.promise_filename)"; "one_rel" string => "fc $(this.promise_filename) $(this.promise_filename).doesnotexist"; "nxe_rel" string => "nosuchprogramexists"; "zero_abs" string => "c:\windows\system32\fc.exe $(this.promise_filename) $(this.promise_filename)"; "one_abs" string => "c:\windows\system32\fc.exe $(this.promise_filename) $(this.promise_filename).doesnotexist"; "nxe_abs" string => "c:\xbin\nosuchprogramexists"; "zero_powershell" string => "if (diff $(this.promise_filename) $(this.promise_filename)) { exit 1 } else { exit 0 }"; "one_powershell" string => "if (diff $(this.promise_filename) $(this.promise_filename).doesnotexit) { exit 1 } else { exit 0 }"; "nxe_powershell" string => "nosuchprogramexists"; !windows:: "zero_rel" string => "grep root $(G.etc_passwd)"; "one_rel" string => "grep gluequaggaunlikely $(G.etc_passwd)"; "nxe_rel" string => "nosuchprogramexists"; "zero_abs" string => "$(G.grep) root $(G.etc_passwd)"; "one_abs" string => "$(G.grep) gluequaggaunlikely $(G.etc_passwd)"; "nxe_abs" string => "/xbin/nosuchprogramexists"; classes: "rawshell_no_prefix" expression => returnszero("ls /", "useshell"); "rawnoshell_no_prefix" expression => returnszero("ls /", "noshell"); "zero_noshell_rel" expression => returnszero("$(zero_rel)", "noshell"); "zero_useshell_rel" expression => returnszero("$(zero_rel)", "useshell"); "zero_noshell_abs" expression => returnszero("$(zero_abs)", "noshell"); "zero_useshell_abs" expression => returnszero("$(zero_abs)", "useshell"); "one_noshell_rel" expression => returnszero("$(one_rel)", "noshell"); "one_useshell_rel" expression => returnszero("$(one_rel)", "useshell"); "one_noshell_abs" expression => returnszero("$(one_abs)", "noshell"); "one_useshell_abs" expression => returnszero("$(one_abs)", "useshell"); "nxe_noshell_rel" expression => returnszero("$(nxe_rel)", "noshell"); "nxe_useshell_rel" expression => returnszero("$(nxe_rel)", "useshell"); "nxe_noshell_abs" expression => returnszero("$(nxe_abs)", "noshell"); "nxe_useshell_abs" expression => returnszero("$(nxe_abs)", "useshell"); windows:: "zero_powershell" expression => returnszero("$(zero_powershell)", "powershell"); "one_powershell" expression => returnszero("$(one_powershell)", "powershell"); "nxe_powershell" expression => returnszero("$(nxe_powershell)", "powershell"); any:: "ok_common" and => { "!zero_noshell_rel", "zero_useshell_rel", "zero_noshell_abs", "zero_useshell_abs", "!one_noshell_rel", "!one_useshell_rel", "!one_noshell_abs", "!one_useshell_abs", "!nxe_noshell_rel", "!nxe_useshell_rel", "!nxe_noshell_abs", "!nxe_useshell_abs", }; windows:: "ok_windows" and => { "zero_powershell", "!one_powershell", "!nxe_powershell", }; "ok" and => { "ok_common", "ok_windows", }; !windows:: "ok" and => { "ok_common" }; reports: DEBUG.zero_noshell_rel:: "'$(zero_rel)' erroneously returns 0 with noshell"; DEBUG.!zero_noshell_rel:: "'$(zero_rel)' returns non-zero with noshell"; DEBUG.zero_useshell_rel:: "'$(zero_rel)' returns 0 with useshell"; DEBUG.!zero_useshell_rel:: "'$(zero_rel)' erroneously returns non-zero with useshell"; DEBUG.!one_noshell_rel:: "'$(one_rel)' returns non-zero with noshell"; DEBUG.one_noshell_rel:: "'$(one_rel)' erroneously returns 0 with noshell"; DEBUG.!one_useshell_rel:: "'$(one_rel)' returns non-zero with useshell"; DEBUG.one_useshell_rel:: "'$(one_rel)' erroneously returns 0 with useshell"; DEBUG.!nxe_noshell_rel:: "'$(nxe_rel)' returns non-zero with noshell"; DEBUG.nxe_noshell_rel:: "'$(nxe_rel)' erroneously returns 0 with noshell"; DEBUG.!nxe_useshell_rel:: "'$(nxe_rel)' returns non-zero with useshell"; DEBUG.nxe_useshell_rel:: "'$(nxe_rel)' erroneously returns 0 with useshell"; DEBUG.zero_noshell_abs:: "'$(zero_abs)' returns 0 with noshell"; DEBUG.!zero_noshell_abs:: "'$(zero_abs)' erroneously returns non-zero with noshell"; DEBUG.zero_useshell_abs:: "'$(zero_abs)' returns 0 with useshell"; DEBUG.!zero_useshell_abs:: "'$(zero_abs)' erroneously returns non-zero with useshell"; DEBUG.!one_noshell_abs:: "'$(one_abs)' returns non-zero with noshell"; DEBUG.one_noshell_abs:: "'$(one_abs)' erroneously returns 0 with noshell"; DEBUG.!one_useshell_abs:: "'$(one_abs)' returns non-zero with useshell"; DEBUG.one_useshell_abs:: "'$(one_abs)' erroneously returns 0 with useshell"; DEBUG.!nxe_noshell_abs:: "'$(nxe_abs)' returns non-zero with noshell"; DEBUG.nxe_noshell_abs:: "'$(nxe_abs)' erroneously returns 0 with noshell"; DEBUG.!nxe_useshell_abs:: "'$(nxe_abs)' returns non-zero with useshell"; DEBUG.nxe_useshell_abs:: "'$(nxe_abs)' erroneously returns 0 with useshell"; windows.DEBUG.!zero_powershell:: "'$(zero_powershell)' erroneously returns non-zero with powershell"; windows.DEBUG.zero_powershell:: "'$(zero_powershell)' returns 0 with powershell"; windows.DEBUG.!one_powershell:: "'$(one_powershell)' returns non-zero with powershell"; windows.DEBUG.one_powershell:: "'$(one_powershell)' erroneously returns 0 with powershell"; windows.DEBUG.!nxe_powershell:: "'$(nxe_powershell)' returns non-zero with powershell"; windows.DEBUG.nxe_powershell:: "'$(nxe_powershell)' erroneously returns 0 with powershell"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/008.cf0000644000175100017510000000162712316547775023363 0ustar00a10038a1003800000000000000####################################################### # # Test userexists() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { userexists("root"), userexists("xxxscrabbleroot"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/getvalues_containers.cf0000644000175100017510000000143212243421446027253 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "arr" data => parsejson('["a", [], { "x": 1 }, 2, 5.30, true]'); } ####################################################### bundle agent test { vars: "arr_v" slist => getvalues("init.arr"); reports: DEBUG:: "arr_v $(arr_v)"; } ####################################################### bundle agent check { classes: "ok" and => { strcmp("a,2,5.30,true", join(",", "test.arr_v")), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/013.cf0000644000175100017510000000141412243421446023332 0ustar00a10038a1003800000000000000####################################################### # # Test isplain() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" not => isplain("/xxgobbleroot"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/014.cf0000644000175100017510000000146612243421446023342 0ustar00a10038a1003800000000000000####################################################### # # Test hostinnetgroup # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { classes: "ng_host" expression => hostinnetgroup("netgroup2"); } ####################################################### bundle agent check { classes: "ok" expression => "any"; # check not crashed reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/003.cf0000644000175100017510000000204312243421446023330 0ustar00a10038a1003800000000000000####################################################### # # Test isvariable() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "present" int => "1"; classes: "should_fail" or => { isvariable("x"), isvariable("init.x") }; "should_pass" not => "should_fail"; "ok" and => { "should_pass", isvariable("present"), isvariable("init.dummy") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/030.cf0000644000175100017510000000250212243421446023330 0ustar00a10038a1003800000000000000####################################################### # # Test concat() function # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "a" string => "a"; "b" string => "b"; "c" string => "c"; "str" string => "str"; "nil" string => ""; classes: "noarg" expression => strcmp(concat(), ""); "a" expression => strcmp(concat("$(a)"), "a"); "a_b" expression => strcmp(concat("$(a)", "$(b)"), "ab"); "a_b_c" expression => strcmp(concat("$(a)", "$(b)", "$(c)"), "abc"); "nil_nil" expression => strcmp(concat("$(nil)", "$(nil)"), ""); "str_str" expression => strcmp(concat("$(str)", "$(str)"), "strstr"); "ok" and => { "noarg", "a", "a_b", "a_b_c", "nil_nil", "str_str" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/005.cf0000644000175100017510000000431112243421446023332 0ustar00a10038a1003800000000000000####################################################### # # Test join() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "zeros" slist => { "solo" }; "zero" string => join("NOISE", "zeros"); "ones" slist => { "a", "bb", "ccc" }; "one" string => join(":", "ones"); "twos" slist => { "xx", "xx", "xx" }; "two" string => join("..", "twos"); "threes" slist => { "" }; "three" string => join("", "threes"); "fours" slist => { "1", "", "3" }; "four" string => join("", "fours"); "fives" slist => { "1", "", "3" }; "five" string => join(",", "fives"); "sixs" slist => { "one ", " two ", " three" }; "six" string => join(" and ", "sixs"); classes: "ok1" expression => strcmp("solo", "$(zero)"); "ok2" expression => strcmp("a:bb:ccc", "$(one)"); "ok3" expression => strcmp("xx..xx..xx", "$(two)"); "ok4" expression => strcmp("", "$(three)"); "ok5" expression => strcmp("13", "$(four)"); "ok6" expression => strcmp("1,,3", "$(five)"); "ok7" expression => strcmp("one and two and three", "$(six)"); "ok" and => { ok1, ok2, ok3, ok4, ok5, ok6, ok7 }; reports: DEBUG.ok1:: "ok1"; DEBUG.ok2:: "ok2"; DEBUG.ok3:: "ok3"; DEBUG.ok4:: "ok4"; DEBUG.ok5:: "ok5"; DEBUG.ok6:: "ok6"; DEBUG.ok7:: "ok7"; DEBUG:: 'strcmp("solo", "$(zero)")'; 'strcmp("a:bb:ccc", "$(one)")'; 'strcmp("xx..xx..xx", "$(two)")'; 'strcmp("", "$(three)")'; 'strcmp("13", "$(four)")'; 'strcmp("1,,3", "$(five)")'; 'strcmp("one and two and three", "$(six)")'; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/006.cf0000644000175100017510000000477312332665147023356 0ustar00a10038a1003800000000000000####################################################### # # Test grep() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "zeros" slist => { "", "a", "bb", "ccc", "dddd" }; "zeroz" slist => grep('\d.*', "zeros"); "zero" string => join(",", "zeroz"); "ones" slist => { "", "a", "bb", "ccc", "dddd" }; "onez" slist => grep("c.*", "ones"); "one" string => join(",", "onez"); "twos" slist => { "", "a", "bb", "ccc", "dddd" }; "twoz" slist => grep(".{1,2}", "twos"); "two" string => join(",", "twoz"); "threes" slist => { "", "a", "bb", "ccc", "dddd" }; "threez" slist => grep("ccc", "threes"); "three" string => join(",", "threez"); "fours" slist => { "", "a", "bb", "ccc", "dddd" }; "fourz" slist => grep(".+", "fours"); "four" string => join(",", "fourz"); "fives" slist => { "", "a", "bb", "ccc", "dddd" }; "fivez" slist => grep(".*", "fives"); "five" string => join(",", "fivez"); "sixs" slist => { "", "a", "bb", "ccc", "dddd", '' }; "sixz" slist => grep("^$", "sixs"); "six" string => join(",", "sixz"); classes: "ok1" expression => strcmp("", "$(zero)"); "ok2" expression => strcmp("ccc", "$(one)"); "ok3" expression => strcmp("a,bb", "$(two)"); "ok4" expression => strcmp("ccc", "$(three)"); "ok5" expression => strcmp("a,bb,ccc,dddd", "$(four)"); "ok6" expression => strcmp(",a,bb,ccc,dddd", "$(five)"); "ok7" expression => strcmp(",", "$(six)"); "ok" and => { ok1, ok2, ok3, ok4, ok5, ok6, ok7 }; reports: DEBUG.ok1:: "ok1"; DEBUG.ok2:: "ok2"; DEBUG.ok3:: "ok3"; DEBUG.ok4:: "ok4"; DEBUG.ok5:: "ok5"; DEBUG.ok6:: "ok6"; DEBUG.ok7:: "ok7"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/009.cf0000644000175100017510000000163012316547775023356 0ustar00a10038a1003800000000000000####################################################### # # Test groupexists() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { groupexists("bin"), groupexists("xxxscrabblebin"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/029.cf0000644000175100017510000000564512243421446023353 0ustar00a10038a1003800000000000000####################################################### # # Test logical functions in ifvarclass # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "and_yes_both" expression => "any", ifvarclass => and("any", "any"); "and_no_left" expression => "any", ifvarclass => and("any", "none"); "and_no_right" expression => "any", ifvarclass => and("none", "any"); "and_no_none" expression => "any", ifvarclass => and("none", "none"); "and_arg_fun" expression => "any", ifvarclass => and(isdir("/")); "and_no_arg_fun" expression => "any", ifvarclass => and(isdir("/bin/sh")); "and_two_args_fun" expression => "any", ifvarclass => and(isdir("/"), isdir("/")); "and_long" expression => "any", ifvarclass => and("any", "any", "any", "any", "any", "any", "any", "any"); "and_ok" and => { "and_yes_both", "!and_no_left", "!and_no_right", "!and_no_none", "and_arg_fun", "!and_no_arg_fun", "and_two_args_fun", "and_long" }; # "or_yes_both" expression => "any", ifvarclass => or("any", "any"); "or_yes_left" expression => "any", ifvarclass => or("any", "none"); "or_yes_right" expression => "any", ifvarclass => or("none", "any"); "or_no_none" expression => "any", ifvarclass => or("none", "none"); "or_arg_fun" expression => "any", ifvarclass => or(isdir("/")); "or_no_arg_fun" expression => "any", ifvarclass => or(isdir("/bin/sh")); "or_two_args_fun" expression => "any", ifvarclass => or(isdir("/"), isexecutable("/")); "or_long" expression => "any", ifvarclass => or("any", "any", "any", "any", "any", "any", "any", "any"); "or_ok" and => { "or_yes_both", "or_yes_left", "or_yes_right", "!or_no_none", "or_arg_fun", "!or_no_arg_fun", "or_two_args_fun", "or_long" }; # "not_yes_no" expression => "any", ifvarclass => not("none"); "not_no_yes" expression => "any", ifvarclass => not("any"); "not_arg_fun" expression => "any", ifvarclass => not(islink("/")); "not_ok" and => { "not_yes_no", "!not_no_yes", "not_arg_fun" }; "ok" and => { "and_ok", "or_ok", "not_ok" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/002.cf0000644000175100017510000000272312243421446023334 0ustar00a10038a1003800000000000000####################################################### # # Test islessthan() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok1" expression => islessthan("0", "1"); "ok2" expression => islessthan("1", "2.7e3"); "ok3" expression => islessthan("1.1", "2"); "ok4" expression => islessthan("2.7e3", "1e9"); "ok5" expression => islessthan("2z", "3b"); "ok6" expression => islessthan("alpha", "beta"); "ok7" expression => islessthan("", "beta"); "ok8" expression => islessthan("-75", "beta"); "ok9" expression => islessthan("", "3"); "ok" and => { ok1, ok2, ok3, ok4, ok5, ok6, ok7, ok8, ok9 }; reports: DEBUG.ok1:: "ok1"; DEBUG.ok2:: "ok2"; DEBUG.ok3:: "ok3"; DEBUG.ok4:: "ok4"; DEBUG.ok5:: "ok5"; DEBUG.ok6:: "ok6"; DEBUG.ok7:: "ok7"; DEBUG.ok8:: "ok8"; DEBUG.ok9:: "ok9"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/staging/0000755000175100017510000000000012332665147024160 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/02_classes/02_functions/staging/017.cf0000644000175100017510000000265112243421446024776 0ustar00a10038a1003800000000000000####################################################### # # Test select_class - partial test only, hard to prove persistence # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { vars: "dummy" string => "dummy"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "sel1" select_class => { "one" }; "sel2" select_class => { "alpha", "beta" }; "sel3" select_class => { "able", "baker", "charlie" }; "sel4" select_class => { "foo", "baz", "gar", "bletch" }; "ok2" xor => { "alpha", "beta" }; "ok3" xor => { "able", "baker", "charlie" }; "ok4" xor => { "foo", "baz", "gar", "bletch" }; "ok" and => { "sel1", "one", "sel2", "xor2", "sel3", "xor3", "sel4", "xor4", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ####################################################### bundle agent fini { vars: "dummy" string => "dummy"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/staging/usemodule.cf0000644000175100017510000000644112316547775026511 0ustar00a10038a1003800000000000000####################################################### # # Test usemodule() # ####################################################### body common control { inputs => { "../../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "script_location" string => dirname("$(this.promise_filename)"); classes: "ok_to_run" not => regcmp("/var/cfengine|.*\.cf-agent", "$(sys.workdir)"); files: ok_to_run:: "$(sys.workdir)/modules/usemodule.cf.bat" create => "true", perms => usemodule_perms, edit_line => usemodule_lines; "$(sys.workdir)/modules/usemodule-neg.cf.bat" create => "true", perms => usemodule_perms, edit_line => usemodule_lines_neg; } bundle edit_line usemodule_lines_neg { insert_lines: !windows:: "#!/bin/sh"; ". \"$(init.script_location)/usemodule.cf.bat\""; "exit 1"; delete_lines: ".*"; } bundle edit_line usemodule_lines { insert_lines: windows:: "@echo off"; "\"$(init.script_location)\usemodule.cf.bat\""; !windows:: "#!/bin/sh"; ". \"$(init.script_location)/usemodule.cf.bat\""; delete_lines: ".*"; } body perms usemodule_perms { mode => "755"; } ####################################################### bundle agent test { classes: "ok_to_run" not => regcmp("/var/cfengine|.*\.cf-agent", "$(sys.workdir)"); classes: ok_to_run:: # Should be undefined by the following script. "undefined_class" expression => "any"; "function_ok" expression => usemodule("usemodule.cf.bat", ""); "function_neg_ok" comment => "Negative test. Class set if module returns non-zero", not => usemodule("usemodule-neg.cf.bat", ""); "defined_variable" expression => strcmp("$(usemodule_cf_bat.defined_variable)", "yes"); "ok" and => { "function_neg_ok", "function_ok", "defined_class", "!undefined_class", "defined_variable" }; vars: ok:: "ok" string => "yes"; reports: !ok_to_run:: "Must be run using testall script"; ok_to_run.DEBUG.!function_ok:: "usemodule did not execute correctly."; ok_to_run.DEBUG.!function_neg_ok:: "usemodule returned non-zero, class function_neg_ok was not set, but should be set."; ok_to_run.DEBUG.!defined_class:: "defined_class was not set, but should be."; ok_to_run.DEBUG.undefined_class:: "undefined_class was set, but shouldn't be."; ok_to_run.DEBUG.!defined_variable:: "defined_variable was not set, but should be."; ok_to_run.DEBUG.function_ok:: "usemodule executed correctly."; ok_to_run.DEBUG.function_neg_ok:: "usemodule returned non-zero and class function_neg_ok was set."; ok_to_run.DEBUG.defined_class:: "defined_class was set."; ok_to_run.DEBUG.!undefined_class:: "undefined_class was not set."; ok_to_run.DEBUG.defined_variable:: "defined_variable was set."; } ####################################################### bundle agent check { classes: "ok" expression => strcmp("$(test.ok)", "yes"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/usemodule.cf.bat0000755000175100017510000000025512236160673025607 0ustar00a10038a1003800000000000000@rem ' @echo off @rem Careful. Batch and shell script in the same file. @rem ' 1>/dev/null 2>/dev/null echo +defined_class echo -undefined_class echo =defined_variable=yes cfengine-3.6.2/tests/acceptance/02_classes/02_functions/021.cf0000644000175100017510000000250312316547775023350 0ustar00a10038a1003800000000000000####################################################### # # Test filesexist() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "f1" string => "$(G.etc_passwd)"; "f2" string => "$(G.etc_group)"; "f3" string => "/etc/NoFriggin'WayThisExi5ts"; "s1" slist => { "$(f1)", "$(f2)" }; "s2" slist => { "$(f1)", "$(f2)", "$(f3)" }; classes: "ok1" expression => filesexist("@(s1)"); "ok2" not => filesexist("@(s2)"); "ok" and => { "ok1", "ok2" }; reports: DEBUG.ok1:: "All files in list s1 $(s1) exist as expected"; DEBUG.!ok1:: "All files in list s1 $(s1) DO NOT exist (and should)"; DEBUG.ok2:: "All files in list s2 $(s2) do not exist as expected"; DEBUG.!ok2:: "All files in list s2 $(s2) DO exist (and shouldn't)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/001.cf0000644000175100017510000000226312243421446023332 0ustar00a10038a1003800000000000000####################################################### # # Test isgreaterthan() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => { isgreaterthan("1", "0"), isgreaterthan("2.7e3", "1"), isgreaterthan("2", "1.1"), isgreaterthan("2.7e3", "9e1"), isgreaterthan("3b", "2z"), isgreaterthan("beta", "alpha"), isgreaterthan("beta", ""), isgreaterthan("beta", "-75"), isgreaterthan("3", ""), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/getindices_containers.cf0000644000175100017510000000165412243421446027400 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "obj" data => parsejson('{ "a": 1, "b": 2 }'); "arr" data => parsejson('["a", "b"]'); } ####################################################### bundle agent test { vars: "obj_i" slist => getindices("init.obj"); "arr_i" slist => getindices("init.arr"); reports: DEBUG:: "obj_i $(obj_i)"; "arr_i $(arr_i)"; } ####################################################### bundle agent check { classes: "ok" and => { strcmp("a,b", join(",", "test.obj_i")), strcmp("0,1", join(",", "test.arr_i")) }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/classesmatching.cf0000644000175100017510000000375712243421446026213 0ustar00a10038a1003800000000000000####################################################### # # Test classesmatching() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "known" slist => { "cfengine", "cfengine_3", "agent", "any", $(dow), $(dow) }; "known_str" string => join(" ", "known"); Monday:: "dow" string => "Monday"; Tuesday:: "dow" string => "Tuesday"; Wednesday:: "dow" string => "Wednesday"; Thursday:: "dow" string => "Thursday"; Friday:: "dow" string => "Friday"; Saturday:: "dow" string => "Saturday"; Sunday:: "dow" string => "Sunday"; } ####################################################### bundle agent test { vars: "matched" slist => { classesmatching("^cfengine$"), # static string # range of multiples classesmatching("^cfengine_[0-9]$"), # alternation/capture of single classesmatching("^a(g)ent$"), # range of single classesmatching("^a[n]y$"), # alternation of multiples classesmatching("^(Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day$"), # interpolation classesmatching("^$(init.dow)$"), }; "matched_str" string => join(" ", "matched"); } ####################################################### bundle agent check { classes: "ok" expression => strcmp($(init.known_str), $(test.matched_str)); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG.!ok:: "$(this.promise_filename) expected '$(init.known_str)', got '$(test.matched_str)'"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/010.cf0000644000175100017510000000151112316547775023344 0ustar00a10038a1003800000000000000####################################################### # # Test isdir() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { isdir("/"), isdir("$(G.etc_passwd)"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/012.cf0000644000175100017510000000141012243421446023325 0ustar00a10038a1003800000000000000####################################################### # # Test isdir() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" not => isdir("/xxgobbleroot"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/020.cf0000644000175100017510000000253512316547775023354 0ustar00a10038a1003800000000000000####################################################### # # Test fileexists() # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "f1" string => "$(G.etc_passwd)"; "f2" string => "$(G.etc_group)"; "f3" string => "/etc/NoFriggin'WayThisExi5ts"; } ####################################################### bundle agent check { classes: "ok1" expression => fileexists("$(test.f1)"); "ok2" expression => fileexists("$(test.f2)"); "ok3" not => fileexists("$(test.f3)"); "ok" and => { "ok1", "ok2", "ok3" }; reports: DEBUG.ok1:: "File $(test.f1) exists as expected"; DEBUG.!ok1:: "File $(test.f1) DOES NOT exist (and should)"; DEBUG.ok2:: "File $(test.f2) exists as expected"; DEBUG.!ok2:: "File $(test.f2) DOES NOT exist (and should)"; DEBUG.ok3:: "File $(test.f3) does not exist as expected"; DEBUG.!ok3:: "File $(test.f3) DOES exist (and shouldn't)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/02_functions/function_args_flattening.cf0000644000175100017510000000231712332665147030115 0ustar00a10038a1003800000000000000####################################################### # # This really tests that the list returned from splitstring() # gets flattened into the variadic function and() # # Test that and function can take a splitstring function call asa paramater # Redmine:4320 (https://cfengine.com/dev/issues/4320) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { } ####################################################### bundle agent test { classes: "one" expression => "any"; reports: "both_elements_are_classes" classes => if_ok("fail"), ifvarclass => and("one", "non_existing_class"); "each_split_element_is_class" classes => if_ok("fail"), ifvarclass => and(splitstring("one,non_existing_class", ",", "20")); } ####################################################### bundle agent check { classes: "ok" expression => "!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/0000755000175100017510000000000012411001073021550 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/02_classes/01_basic/persistent_tags.cf0000644000175100017510000000227412332665147025331 0ustar00a10038a1003800000000000000####################################################### # # Redmine#5017: persistent classes should keep their tags # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dflags" string => ifelse("EXTRA", "-DDEBUG,EXTRA", "-DDEBUG"); commands: "$(G.echo)" classes => init_cancel_always; } body classes init_cancel_always { cancel_repaired => { "myclass" }; cancel_notkept => { "myclass" }; cancel_kept => { "myclass" }; } bundle agent test { commands: "$(sys.cf_agent) -K $(init.dflags) -f $(this.promise_filename).sub" classes => test_always("done_persisting"); } body classes test_always(x) { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; repair_failed => { "$(x)" }; repair_denied => { "$(x)" }; repair_timeout => { "$(x)" }; } bundle agent check { vars: done_persisting:: "subout" string => execresult("$(sys.cf_agent) -K $(init.dflags) -f $(this.promise_filename).sub2", "noshell"); reports: "$(subout)"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/018.cf0000644000175100017510000000153112316547775022426 0ustar00a10038a1003800000000000000####################################################### # # Test brackets on "or" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" or => { userexists("root") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/025.cf0000644000175100017510000000165612243421446022415 0ustar00a10038a1003800000000000000####################################################### # # Check ifvarclass with array # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { classes: "classtotest" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "foobar[0]" string => "classtotest"; classes: "ok" expression => "any", ifvarclass => "$(foobar[0])"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/action_policy_warn_sets_classes.cf0000644000175100017510000000306412400110676030533 0ustar00a10038a1003800000000000000####################################################### # # Test not # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { files: "/tmp/dont_create_me" create => 'true', classes => classes_generic( "test_files" ), action => warnonly; commands: "$(G.echo) 'dont_print_me'" classes => classes_generic( "test_commands" ), action => warnonly; processes: "cf-agent-x" restart_class => "restart_cf_agent", classes => classes_generic( "test_processes" ), action => warnonly; reports: "Test output" classes => classes_generic("test_reports"), action => warnonly; } body action warnonly { action_policy => "warn"; } ####################################################### bundle agent check { vars: "classes" slist => classesmatching( "test_.*" ); classes: "ok" and => { "test_files_not_kept", "test_commands_not_kept", "test_processes_not_kept", "test_reports_not_kept" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; debug:: "$(classes)"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/027.cf0000644000175100017510000000146212332665147022421 0ustar00a10038a1003800000000000000####################################################### # # Check canonification in ifvarclass # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { commands: "$(G.true)" classes => if_repaired("/test"); } ####################################################### bundle agent check { classes: "ok" expression => "_test"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/017.cf0000644000175100017510000000153312316547775022427 0ustar00a10038a1003800000000000000####################################################### # # Test brackets on "and" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => { userexists("root") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/030.cf.namespaced.sub0000644000175100017510000000065212236160673025277 0ustar00a10038a1003800000000000000body file control { namespace => "test_namespace"; } bundle agent classchecker { classes: "noedit_$(cindex[$(key)])" expression => strcmp("x","dontchange"); vars: "key" string => "1 2 3"; "cindex[$(key)]" string => canonify("$(key)"); "var1" string => "data1", ifvarclass => "noedit_$(cindex[$(key)])"; "var1" string => "data1", ifvarclass => "!noedit_$(cindex[$(key)])"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/021.x.cf0000644000175100017510000000137312243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test brackets on "not" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" not => { userexists("root"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/026.cf0000644000175100017510000000162012243421446022405 0ustar00a10038a1003800000000000000####################################################### # # Check ifvarclass with qualified variable # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { classes: "classtotest" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "foobar" string => "classtotest"; } ####################################################### bundle agent check { classes: "ok" expression => "any", ifvarclass => "$(test.foobar)"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/007.cf0000644000175100017510000000147712243421446022416 0ustar00a10038a1003800000000000000####################################################### # # Test or # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" or => { "this_was_not_defined" }; "ok" not => "ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/015.cf0000644000175100017510000000151212243421446022403 0ustar00a10038a1003800000000000000####################################################### # # Test xor # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { "!any", "!any", "any", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/118.x.cf0000644000175100017510000000144212243421446022657 0ustar00a10038a1003800000000000000####################################################### # # Test no brackets on "or" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" or => userexists("root"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/011.cf0000644000175100017510000000146212243421446022403 0ustar00a10038a1003800000000000000####################################################### # # Test xor # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" xor => { "cfengine_3", "any", }; "ok" not => "not_ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/022.x.cf0000644000175100017510000000146212243421446022653 0ustar00a10038a1003800000000000000####################################################### # # Test syntactically errorneous class expression # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: !.!:: "undererror" string => "undererror"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/024.cf0000644000175100017510000000171212243421446022405 0ustar00a10038a1003800000000000000####################################################### # # Test complex expression (issue 487) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "class1" expression => "any"; "class2" expression => "any"; "class3" expression => "any"; "class4" expression => "any"; class1.(class2|class3.class4):: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/avoid_reevaluation.cf0000644000175100017510000000134312411001073025743 0ustar00a10038a1003800000000000000####################################################### # # Redmine#5241: do not reevaluate classes if they are known already # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent check { methods: "" usebundle => dcs_passif_output(".*", ".*loquacious quaalude.*", "$(sys.cf_agent) -KI -f $(this.promise_filename).sub -Dloquacious | $(G.grep) qua", $(this.promise_filename)); } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/ifvarclass_common_bundles.cf0000644000175100017510000000217212243421446027322 0ustar00a10038a1003800000000000000####################################################### # # Check that we can use ifvarclass in common bundle class expressions # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle common init { classes: "initclass" expression => "any"; } ####################################################### bundle common test { classes: "shouldset" expression => "any", ifvarclass => "initclass"; "shouldnot" expression => "any", ifvarclass => "notaclass"; } ####################################################### bundle agent check { vars: "classes" slist => { "shouldset", "shouldnot" }; classes: shouldset.!shouldnot:: "ok" expression => "any"; reports: DEBUG:: "$(classes) is set" ifvarclass => "$(classes)"; "$(classes) is not" ifvarclass => "!$(classes)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/004.cf0000644000175100017510000000146312243421446022406 0ustar00a10038a1003800000000000000####################################################### # # Test and # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => { "any", "cfengine_3" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/023.cf0000644000175100017510000000171412243421446022406 0ustar00a10038a1003800000000000000####################################################### # # Test complex expression (issue 487) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "class1" expression => "any"; "class2" expression => "any"; "class3" expression => "any"; "class4" expression => "any"; class1.(class2|(class3.class4)):: "ok" expression => "any"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/avoid_reevaluation.cf.sub0000644000175100017510000000034112411001073026530 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { run }; } bundle agent run { classes: "loquacious" expression => returnszero("$(G.echo) loquacious quaalude", "noshell"); } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/016.cf0000644000175100017510000000151012243421446022402 0ustar00a10038a1003800000000000000####################################################### # # Test xor # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { "any", "any", "any", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/008.cf0000644000175100017510000000155312243421446022412 0ustar00a10038a1003800000000000000####################################################### # # Test or # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" or => { "this_was_not_defined", "neither_was_this", }; "ok" not => "ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/persistent_tags.cf.sub20000644000175100017510000000252012332665147026175 0ustar00a10038a1003800000000000000body common control { bundlesequence => { run }; } bundle agent run { vars: "tagged" slist => classesmatching("myclass"); "unsorted_tags_$(tagged)" slist => getclassmetatags($(tagged)); "tags_$(tagged)" slist => sort("unsorted_tags_$(tagged)", "lex"); "tagged_str" string => format("%S", tagged); "tags_$(tagged)_str" string => format("%S", "tags_$(tagged)"); "expected_classes" string => '{ "myclass" }'; "expected_tags" string => '{ "source=persistent", "source=promise", "specialtag" }'; classes: "ok_class" expression => strcmp($(tagged_str), $(expected_classes)); "ok_tags" expression => strcmp($(tags_myclass_str), $(expected_tags)); "ok" and => { "ok_class", "ok_tags" }; reports: !ok_class.DEBUG:: "The list of tagged classes '$(tagged_str)' did NOT match the expected '$(expected_classes)'"; !ok_tags.DEBUG:: "The list of tags '$(tags_myclass_str)' did NOT match the expected '$(expected_tags)'"; ok_class.EXTRA:: "The list of tagged classes '$(tagged_str)' matched the expected '$(expected_classes)'"; ok_tags.EXTRA:: "The list of tags '$(tags_myclass_str)' matched the expected '$(expected_tags)'"; ok:: "${this.promise_dirname}/persistent_tags.cf Pass"; !ok:: "${this.promise_dirname}/persistent_tags.cf FAIL"; }cfengine-3.6.2/tests/acceptance/02_classes/01_basic/109.cf0000644000175100017510000000146612243421446022417 0ustar00a10038a1003800000000000000# Test that classes in common bundles can be passed across bundles and namespaces body common control { inputs => { "../../default.cf.sub", "109.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } bundle common shared { classes: "shared_class" expression => "any"; } bundle agent test { methods: "shared" usebundle => shared; "namespaced" usebundle => ns109:pass(); } bundle agent check { classes: "ok" expression => strcmp("works", "$(ns109:pass.shared_dependent)"); reports: DEBUG:: "The class expression in ns109:pass() was $(ns109:pass.class_needed)"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/028.cf0000644000175100017510000000204612243421446022412 0ustar00a10038a1003800000000000000####################################################### # # Check that we can use || in class expressions # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: any||something:: "oklhs" expression => "any"; something||any:: "okrhs" expression => "any"; any||any:: "okboth" expression => "any"; something||something:: "okno" expression => "any"; any:: "ok" and => { "oklhs", "okrhs", "okboth", "!okno" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/040.cf0000644000175100017510000000164312243421446022406 0ustar00a10038a1003800000000000000####################################################### # # Check that countclassesmatching() works # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: "num" int => countclassesmatching("any"); classes: # One and only one match "ok" and => { isgreaterthan("$(num)", "0"), islessthan("$(num)", "2") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/042.cf0000644000175100017510000000220312243421446022401 0ustar00a10038a1003800000000000000####################################################### # # Check that weekday classes make sense # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: # Only one of these should be set at a time "num" int => countclassesmatching("(Min00_05|Min05_10|Min10_15|Min15_20|Min20_25|Min25_30|Min30_35|Min35_40|Min40_45|Min45_50|Min50_55|Min55_00)"); classes: # One and only one match "ok" and => { isgreaterthan("$(num)", "0"), islessthan("$(num)", "2") }; reports: cfengine:: "Found $(num) matches when there should be 1"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/013.cf0000644000175100017510000000150512243421446022403 0ustar00a10038a1003800000000000000####################################################### # # Test xor # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { "cfengine_3", "this_was_not_defined", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/014.cf0000644000175100017510000000146512243421446022411 0ustar00a10038a1003800000000000000####################################################### # # Test xor # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { "cfengine_3", "!any", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/003.cf0000644000175100017510000000143012243421446022377 0ustar00a10038a1003800000000000000####################################################### # # Test and # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => { "cfengine_3" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/031.cf.namespaced.sub0000644000175100017510000000071612236160673025301 0ustar00a10038a1003800000000000000body file control { namespace => "test_namespace"; } bundle agent classchecker { classes: "localclass1" and => { "default:GLOBALCLASS" }; "localclass2" or => { "default:GLOBALCLASS" }; "localclass3" and => { "default:$(classname)" }; vars: "classname" string => "GLOBALCLASS"; localclass1:: "var1" string => "data1"; localclass2:: "var2" string => "data2"; localclass3:: "var3" string => "data3"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/031.cf0000644000175100017510000000246112236160673022411 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub", "031.cf.namespaced.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle common globalclasses { classes: "GLOBALCLASS" expression => "any"; } bundle agent test { methods: "globals" usebundle => globalclasses; "call" usebundle => test_namespace:classchecker; } ####################################################### bundle agent check { classes: "ok1" expression => strcmp("$(test_namespace:classchecker.var1)", "data1"); "ok2" expression => strcmp("$(test_namespace:classchecker.var2)", "data2"); "ok3" expression => strcmp("$(test_namespace:classchecker.var3)", "data3"); any:: "ok" and => { "ok1", "ok2", "ok3" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; !ok1||DEBUG:: "Expected data1, got $(test_namespace:classchecker.var1)"; !ok2||DEBUG:: "Expected data2, got $(test_namespace:classchecker.var2)"; !ok3||DEBUG:: "Expected data3, got $(test_namespace:classchecker.var3)"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/030.cf0000644000175100017510000000157312236160673022413 0ustar00a10038a1003800000000000000body common control { inputs => { "../../default.cf.sub", "030.cf.namespaced.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; methods: "call" usebundle => test_namespace:classchecker; } ####################################################### bundle agent check { classes: "ok1" expression => strcmp("$(test_namespace:classchecker.var1)", "data1"); any:: "ok" and => { "ok1" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG:: "Expected data1, got $(test_namespace:classchecker.var1)"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/119.x.cf0000644000175100017510000000144412243421446022662 0ustar00a10038a1003800000000000000####################################################### # # Test no brackets on "xor" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => userexists("root"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/005.cf0000644000175100017510000000151012243421446022400 0ustar00a10038a1003800000000000000####################################################### # # Test and # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" and => { "any", "cfengine_3", "this_was_not_defined" }; "ok" not => "ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/117.x.cf0000644000175100017510000000144412243421446022660 0ustar00a10038a1003800000000000000####################################################### # # Test no brackets on "and" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" and => userexists("root"); reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/006.cf0000644000175100017510000000145512243421446022411 0ustar00a10038a1003800000000000000####################################################### # # Test and # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" and => { "this_was_not_defined" }; "ok" not => "ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/009.cf0000644000175100017510000000155012243421446022410 0ustar00a10038a1003800000000000000####################################################### # # Test or # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" or => { "this_was_not_defined", "cfengine_3", "neither_was_this", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/032.cf0000644000175100017510000000220712316547775022423 0ustar00a10038a1003800000000000000# # Test whether classes defined by promises end up in right namespace # body common control { inputs => { "../../default.cf.sub", "031.cf.namespaced.sub", "032.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { methods: "call" usebundle => xxx:localclass; reports: cfengine:: "testing class 1" classes => xxx:always("another_class_global_from_command"); } ####################################################### bundle agent check { classes: "ok" and => { "xxx:a_class_global_from_command", "default:another_class_global_from_command" }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; DEBUG:: "xxx:a_class_global_from_command is set" ifvarclass => "xxx:a_class_global_from_command"; DEBUG.another_class_global_from_command:: "another_class_global_from_command is set"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/002.cf0000644000175100017510000000142312243421446022400 0ustar00a10038a1003800000000000000####################################################### # # Test not # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" not => "any"; "ok" not => "not_ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/staging/0000755000175100017510000000000012243421446023221 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/02_classes/01_basic/staging/028.c0000644000175100017510000000237012236160673023704 0ustar00a10038a1003800000000000000#include #include #include #include #define CF_HASHTABLESIZE 8192 #define DAILY 12*24 main() { char s[] = "xx"; char c,c2; int hash, box, minblocks; int period=DAILY-1; char *boxes[DAILY]; for (box=0; box {\n"); for (box=0; box> 6 ); } h += ( h << 3 ); h ^= ( h >> 11 ); h += ( h << 15 ); return (h & (hashtablesize-1)); } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/staging/028.cf0000644000175100017510000003135312243421446024051 0ustar00a10038a1003800000000000000####################################################### # # Check splayclass - requires familiaity with internals # See associated C file to generate mutually exclusive classes # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle common g { classes: "classtotest" expression => "any"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: # The program 028.c generates this list, and exactly 1 class will # be True at any time of day "ok" xor => { splayclass("AT","daily"), # Box 0 splayclass("AA","daily"), # Box 1 splayclass("AH","daily"), # Box 2 splayclass("AZ","daily"), # Box 3 splayclass("Cd","daily"), # Box 4 splayclass("CV","daily"), # Box 5 splayclass("Am","daily"), # Box 6 splayclass("EH","daily"), # Box 7 splayclass("Bh","daily"), # Box 8 splayclass("HF","daily"), # Box 9 splayclass("Bz","daily"), # Box 10 splayclass("CM","daily"), # Box 11 splayclass("OR","daily"), # Box 12 splayclass("FK","daily"), # Box 13 splayclass("Ay","daily"), # Box 14 splayclass("Cc","daily"), # Box 15 splayclass("IF","daily"), # Box 16 splayclass("IA","daily"), # Box 17 splayclass("HP","daily"), # Box 18 splayclass("Et","daily"), # Box 19 splayclass("Ga","daily"), # Box 20 splayclass("EF","daily"), # Box 21 splayclass("DS","daily"), # Box 22 splayclass("Ee","daily"), # Box 23 splayclass("BI","daily"), # Box 24 splayclass("CH","daily"), # Box 25 splayclass("AS","daily"), # Box 26 splayclass("Gd","daily"), # Box 27 splayclass("Dm","daily"), # Box 28 splayclass("CA","daily"), # Box 29 splayclass("FZ","daily"), # Box 30 splayclass("Gv","daily"), # Box 31 splayclass("ES","daily"), # Box 32 splayclass("Db","daily"), # Box 33 splayclass("BS","daily"), # Box 34 splayclass("KP","daily"), # Box 35 splayclass("EZ","daily"), # Box 36 splayclass("Ax","daily"), # Box 37 splayclass("An","daily"), # Box 38 splayclass("Mq","daily"), # Box 39 splayclass("Bw","daily"), # Box 40 splayclass("BL","daily"), # Box 41 splayclass("AI","daily"), # Box 42 splayclass("CN","daily"), # Box 43 splayclass("Aw","daily"), # Box 44 splayclass("Ce","daily"), # Box 45 splayclass("Mh","daily"), # Box 46 splayclass("Gs","daily"), # Box 47 splayclass("He","daily"), # Box 48 splayclass("Ex","daily"), # Box 49 splayclass("KJ","daily"), # Box 50 splayclass("GN","daily"), # Box 51 splayclass("Bm","daily"), # Box 52 splayclass("Iy","daily"), # Box 53 splayclass("JG","daily"), # Box 54 splayclass("Po","daily"), # Box 55 splayclass("CF","daily"), # Box 56 splayclass("Fg","daily"), # Box 57 splayclass("KQ","daily"), # Box 58 splayclass("AB","daily"), # Box 59 splayclass("Cq","daily"), # Box 60 splayclass("KX","daily"), # Box 61 splayclass("ER","daily"), # Box 62 splayclass("De","daily"), # Box 63 splayclass("Fn","daily"), # Box 64 splayclass("Bn","daily"), # Box 65 splayclass("DZ","daily"), # Box 66 splayclass("DA","daily"), # Box 67 splayclass("Ag","daily"), # Box 68 splayclass("Bi","daily"), # Box 69 splayclass("Ki","daily"), # Box 70 splayclass("Kw","daily"), # Box 71 splayclass("Ed","daily"), # Box 72 splayclass("In","daily"), # Box 73 splayclass("CC","daily"), # Box 74 splayclass("Dy","daily"), # Box 75 splayclass("OB","daily"), # Box 76 splayclass("DU","daily"), # Box 77 splayclass("Cj","daily"), # Box 78 splayclass("EC","daily"), # Box 79 splayclass("Gr","daily"), # Box 80 splayclass("AO","daily"), # Box 81 splayclass("Bf","daily"), # Box 82 splayclass("Gk","daily"), # Box 83 splayclass("AX","daily"), # Box 84 splayclass("Ar","daily"), # Box 85 splayclass("Hq","daily"), # Box 86 splayclass("Ac","daily"), # Box 87 splayclass("BG","daily"), # Box 88 splayclass("Dq","daily"), # Box 89 splayclass("AY","daily"), # Box 90 splayclass("BY","daily"), # Box 91 splayclass("Cn","daily"), # Box 92 splayclass("BJ","daily"), # Box 93 splayclass("Yu","daily"), # Box 94 splayclass("DC","daily"), # Box 95 splayclass("Dd","daily"), # Box 96 splayclass("Ca","daily"), # Box 97 splayclass("Kc","daily"), # Box 98 splayclass("Op","daily"), # Box 99 splayclass("PV","daily"), # Box 100 splayclass("MJ","daily"), # Box 101 splayclass("GE","daily"), # Box 102 splayclass("EJ","daily"), # Box 103 splayclass("Hh","daily"), # Box 104 splayclass("CJ","daily"), # Box 105 splayclass("Ev","daily"), # Box 106 splayclass("Cw","daily"), # Box 107 splayclass("Cb","daily"), # Box 108 splayclass("Eh","daily"), # Box 109 splayclass("Bt","daily"), # Box 110 splayclass("EB","daily"), # Box 111 splayclass("Fo","daily"), # Box 112 splayclass("Nb","daily"), # Box 113 splayclass("HG","daily"), # Box 114 splayclass("KD","daily"), # Box 115 splayclass("DW","daily"), # Box 116 splayclass("Ak","daily"), # Box 117 splayclass("Cp","daily"), # Box 118 splayclass("Ae","daily"), # Box 119 splayclass("Bg","daily"), # Box 120 splayclass("Qq","daily"), # Box 121 splayclass("PC","daily"), # Box 122 splayclass("CL","daily"), # Box 123 splayclass("HA","daily"), # Box 124 splayclass("Aq","daily"), # Box 125 splayclass("Ef","daily"), # Box 126 splayclass("PJ","daily"), # Box 127 splayclass("BA","daily"), # Box 128 splayclass("Dp","daily"), # Box 129 splayclass("DK","daily"), # Box 130 splayclass("Gq","daily"), # Box 131 splayclass("GW","daily"), # Box 132 splayclass("Hp","daily"), # Box 133 splayclass("BK","daily"), # Box 134 splayclass("NY","daily"), # Box 135 splayclass("NP","daily"), # Box 136 splayclass("CB","daily"), # Box 137 splayclass("CI","daily"), # Box 138 splayclass("AR","daily"), # Box 139 splayclass("Pb","daily"), # Box 140 splayclass("Co","daily"), # Box 141 splayclass("Ms","daily"), # Box 142 splayclass("Oq","daily"), # Box 143 splayclass("Pt","daily"), # Box 144 splayclass("RQ","daily"), # Box 145 splayclass("AF","daily"), # Box 146 splayclass("Fs","daily"), # Box 147 splayclass("DO","daily"), # Box 148 splayclass("Cu","daily"), # Box 149 splayclass("Ds","daily"), # Box 150 splayclass("Tv","daily"), # Box 151 splayclass("Ys","daily"), # Box 152 splayclass("BW","daily"), # Box 153 splayclass("BP","daily"), # Box 154 splayclass("cV","daily"), # Box 155 splayclass("DE","daily"), # Box 156 splayclass("Fz","daily"), # Box 157 splayclass("EM","daily"), # Box 158 splayclass("DL","daily"), # Box 159 splayclass("cM","daily"), # Box 160 splayclass("BD","daily"), # Box 161 splayclass("Bd","daily"), # Box 162 splayclass("GC","daily"), # Box 163 splayclass("AE","daily"), # Box 164 splayclass("Ho","daily"), # Box 165 splayclass("JE","daily"), # Box 166 splayclass("CZ","daily"), # Box 167 splayclass("RG","daily"), # Box 168 splayclass("As","daily"), # Box 169 splayclass("Ai","daily"), # Box 170 splayclass("IT","daily"), # Box 171 splayclass("Cg","daily"), # Box 172 splayclass("Cl","daily"), # Box 173 splayclass("JS","daily"), # Box 174 splayclass("FO","daily"), # Box 175 splayclass("HO","daily"), # Box 176 splayclass("Bq","daily"), # Box 177 splayclass("OH","daily"), # Box 178 splayclass("DN","daily"), # Box 179 splayclass("Hx","daily"), # Box 180 splayclass("CK","daily"), # Box 181 splayclass("NC","daily"), # Box 182 splayclass("PO","daily"), # Box 183 splayclass("Dz","daily"), # Box 184 splayclass("Eq","daily"), # Box 185 splayclass("AG","daily"), # Box 186 splayclass("Ke","daily"), # Box 187 splayclass("DT","daily"), # Box 188 splayclass("EY","daily"), # Box 189 splayclass("BE","daily"), # Box 190 splayclass("Br","daily"), # Box 191 splayclass("Qk","daily"), # Box 192 splayclass("Jw","daily"), # Box 193 splayclass("KM","daily"), # Box 194 splayclass("AP","daily"), # Box 195 splayclass("DY","daily"), # Box 196 splayclass("Jz","daily"), # Box 197 splayclass("Hi","daily"), # Box 198 splayclass("AM","daily"), # Box 199 splayclass("WQ","daily"), # Box 200 splayclass("Cv","daily"), # Box 201 splayclass("BQ","daily"), # Box 202 splayclass("Fu","daily"), # Box 203 splayclass("CR","daily"), # Box 204 splayclass("JQ","daily"), # Box 205 splayclass("FN","daily"), # Box 206 splayclass("QW","daily"), # Box 207 splayclass("Fb","daily"), # Box 208 splayclass("DB","daily"), # Box 209 splayclass("OI","daily"), # Box 210 splayclass("Ei","daily"), # Box 211 splayclass("FY","daily"), # Box 212 splayclass("Cm","daily"), # Box 213 splayclass("IE","daily"), # Box 214 splayclass("HM","daily"), # Box 215 splayclass("BN","daily"), # Box 216 splayclass("BT","daily"), # Box 217 splayclass("HD","daily"), # Box 218 splayclass("GK","daily"), # Box 219 splayclass("BB","daily"), # Box 220 splayclass("Bo","daily"), # Box 221 splayclass("EV","daily"), # Box 222 splayclass("Ht","daily"), # Box 223 splayclass("BM","daily"), # Box 224 splayclass("Lk","daily"), # Box 225 splayclass("Er","daily"), # Box 226 splayclass("AD","daily"), # Box 227 splayclass("GI","daily"), # Box 228 splayclass("SX","daily"), # Box 229 splayclass("JH","daily"), # Box 230 splayclass("IZ","daily"), # Box 231 splayclass("Cs","daily"), # Box 232 splayclass("Ym","daily"), # Box 233 splayclass("DI","daily"), # Box 234 splayclass("Oo","daily"), # Box 235 splayclass("LK","daily"), # Box 236 splayclass("DX","daily"), # Box 237 splayclass("HR","daily"), # Box 238 splayclass("Fj","daily"), # Box 239 splayclass("XC","daily"), # Box 240 splayclass("AV","daily"), # Box 241 splayclass("AC","daily"), # Box 242 splayclass("CW","daily"), # Box 243 splayclass("AJ","daily"), # Box 244 splayclass("Av","daily"), # Box 245 splayclass("CX","daily"), # Box 246 splayclass("ED","daily"), # Box 247 splayclass("HE","daily"), # Box 248 splayclass("Ao","daily"), # Box 249 splayclass("Gm","daily"), # Box 250 splayclass("BC","daily"), # Box 251 splayclass("EN","daily"), # Box 252 splayclass("EP","daily"), # Box 253 splayclass("FQ","daily"), # Box 254 splayclass("Dt","daily"), # Box 255 splayclass("RC","daily"), # Box 256 splayclass("Ib","daily"), # Box 257 splayclass("JI","daily"), # Box 258 splayclass("BU","daily"), # Box 259 splayclass("BV","daily"), # Box 260 splayclass("Xp","daily"), # Box 261 splayclass("GA","daily"), # Box 262 splayclass("NE","daily"), # Box 263 splayclass("Mo","daily"), # Box 264 splayclass("CE","daily"), # Box 265 splayclass("AL","daily"), # Box 266 splayclass("Es","daily"), # Box 267 splayclass("Py","daily"), # Box 268 splayclass("Hl","daily"), # Box 269 splayclass("IC","daily"), # Box 270 splayclass("Bp","daily"), # Box 271 splayclass("Iz","daily"), # Box 272 splayclass("HU","daily"), # Box 273 splayclass("DQ","daily"), # Box 274 splayclass("EI","daily"), # Box 275 splayclass("Cf","daily"), # Box 276 splayclass("GH","daily"), # Box 277 splayclass("Aa","daily"), # Box 278 splayclass("EG","daily"), # Box 279 splayclass("Ct","daily"), # Box 280 splayclass("Gl","daily"), # Box 281 splayclass("AW","daily"), # Box 282 splayclass("CP","daily"), # Box 283 splayclass("CO","daily"), # Box 284 splayclass("AK","daily"), # Box 285 splayclass("BZ","daily"), # Box 286 splayclass("Fk","daily"), # Box 287 }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/020.x.cf0000644000175100017510000000141112243421446022643 0ustar00a10038a1003800000000000000####################################################### # # Test brackets on "expression" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" expression => { userexists("root"), }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/041.cf0000644000175100017510000000212512243421446022403 0ustar00a10038a1003800000000000000####################################################### # # Check that weekday classes make sense # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { vars: # Only one of these should be set at a time "num" int => countclassesmatching("(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)"); classes: # One and only one match "ok" and => { isgreaterthan("$(num)", "0"), islessthan("$(num)", "2") }; reports: cfengine:: "Found val $(num) matches when there should be 1"; ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/109.cf.sub0000644000175100017510000000120712236160673023204 0ustar00a10038a1003800000000000000body file control { namespace => "ns109"; } bundle agent pass() { classes: "shred" expression => "default:shared_class"; vars: "shared_dependent" string => "works", ifvarclass => "default:shared_class"; shred:: "forced_dependent" string => "works"; reports: DEBUG:: "Does the shared class work in a variable? Is '$(shared_dependent)' == 'works'?"; "Does the shared class work explicitly? Is '$(forced_dependent)' == 'works'?"; "The shared class claims to work." ifvarclass => "$(class_needed)"; "The shared class does not work" ifvarclass => "!$(class_needed)"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/001.cf0000644000175100017510000000140312243421446022375 0ustar00a10038a1003800000000000000####################################################### # # Test not # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" not => "class_never_defined"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/agent_class_scope.cf0000644000175100017510000000237612243421446025563 0ustar00a10038a1003800000000000000####################################################### # # Check that we can use scope attributes to promise global classes # from agent bundles # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "classes" slist => { "global_c", "local_c", "unglobal_c", "unlocal_c" }; } bundle agent test { classes: "global_c" expression => "any", scope => "namespace"; "unglobal_c" expression => "!any", scope => "namespace"; "local_c" expression => "any"; "unlocal_c" expression => "!any"; reports: DEBUG:: "$(init.classes) defined from test" ifvarclass => "${init.classes}"; "$(init.classes) not defined from test" ifvarclass => "!${init.classes}"; } bundle agent check { classes: global_c.!local_c.!unglobal_c.!unlocal_c:: "ok" expression => "any"; reports: DEBUG:: "$(init.classes) defined from check" ifvarclass => "${init.classes}"; "$(init.classes) not defined from check" ifvarclass => "!${init.classes}"; ok:: "${this.promise_filename} Pass"; !ok:: "${this.promise_filename} FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/019.cf0000644000175100017510000000153212316547775022430 0ustar00a10038a1003800000000000000####################################################### # # Test brackets on "xor" (Issue 234) # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_skip_unsupported" string => "windows"; vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" xor => { userexists("root") }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/redmine_6509.cf0000644000175100017510000000445512411001073024200 0ustar00a10038a1003800000000000000####################################################### # # Redmine#6509: repairs from delete bodies should not be seen as kept # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { meta: "test_suppress_fail" string => "any", meta => { "redmine6509" }; files: "$(G.testdir)/redmine_6509_1/." create => "true"; "$(G.testdir)/redmine_6509_2" delete => tidy; } bundle agent test { files: "$(G.testdir)/redmine_6509_1" classes => mygeneric("dir1_absent"), delete => tidy; "$(G.testdir)/redmine_6509_2" classes => mygeneric("dir2_absent"), delete => tidy; } bundle agent check { vars: "expected_ok" slist => { "dir1_absent_ok", "dir1_absent_repaired", "dir1_absent_reached", "dir2_absent_ok", "dir2_absent_kept", "dir2_absent_reached", }; "seen_fail" slist => { "dir1_absent_error", "dir1_absent_repair_failed", "dir1_absent_repair_denied", "dir1_absent_repair_timeout", "dir1_absent_kept", }; classes: "ok" and => { @(expected_ok) }; "fail" or => { @(seen_fail) }; reports: DEBUG:: "Found $(expected_ok) defined as expected" ifvarclass => "$(expected_ok)"; "Found $(seen_fail) which is not expected and causes the test to fail" ifvarclass => "$(seen_fail)"; "Missing $(expected_ok) which is expected and not being defined causes the test to fail" ifvarclass => "!$(expected_ok)"; !fail.ok:: "$(this.promise_filename) Pass"; fail:: "$(this.promise_filename) FAIL"; } body classes mygeneric(x) { promise_kept => { "$(x)_ok", "$(x)_kept", "$(x)_reached" }; promise_repaired => { "$(x)_ok", "$(x)_repaired", "$(x)_reached" }; repair_failed => { "$(x)_error", "$(x)_repair_failed", "$(x)_reached" }; repair_denied => { "$(x)_error", "$(x)_repair_denied", "$(x)_reached" }; repair_timeout => { "$(x)_error", "$(x)_repair_timeout", "$(x)_reached" }; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/common_class_scope.cf0000644000175100017510000000237212243421446025751 0ustar00a10038a1003800000000000000####################################################### # # Check that we can use scope attributes to promise global classes # from common bundles # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "classes" slist => { "global_c", "local_c", "unglobal_c", "unlocal_c" }; } bundle common test { classes: "global_c" expression => "any"; "unglobal_c" expression => "!any"; "local_c" expression => "any", scope => "bundle"; "unlocal_c" expression => "!any", scope => "bundle"; reports: DEBUG:: "$(init.classes) defined from test" ifvarclass => "${init.classes}"; "$(init.classes) not defined from test" ifvarclass => "!${init.classes}"; } bundle agent check { classes: global_c.!local_c.!unglobal_c.!unlocal_c:: "ok" expression => "any"; reports: DEBUG:: "$(init.classes) defined from check" ifvarclass => "${init.classes}"; "$(init.classes) not defined from check" ifvarclass => "!${init.classes}"; ok:: "${this.promise_filename} Pass"; !ok:: "${this.promise_filename} FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/032.cf.sub0000644000175100017510000000132212316547775023210 0ustar00a10038a1003800000000000000body file control { namespace => "xxx"; } bundle agent localclass { reports: cfengine:: "testing class 2" classes => always("a_class_global_from_command"); a_class_global_from_command:: "Global class from 'classes' attribute, accessed in the same namespace"; default:a_class_global_from_command:: "Global class from 'classes' attribute, accessed in the default namespace"; } body classes always(x) # Define a class no matter what the outcome of the promise is { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; repair_failed => { "$(x)" }; repair_denied => { "$(x)" }; repair_timeout => { "$(x)" }; # persist_time => "1"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/010.cf0000644000175100017510000000146012243421446022400 0ustar00a10038a1003800000000000000####################################################### # # Test or # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "ok" or => { "cfengine_3", "any", }; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/persistent_tags.cf.sub0000644000175100017510000000030612332665147026113 0ustar00a10038a1003800000000000000body common control { bundlesequence => { run }; } bundle common run { classes: "myclass" expression => "any", meta => { "specialtag" }, persistence => "120"; # 2 hours. }cfengine-3.6.2/tests/acceptance/02_classes/01_basic/012.cf0000644000175100017510000000151112243421446022377 0ustar00a10038a1003800000000000000####################################################### # # Test xor # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { vars: "dummy" string => "dummy"; } ####################################################### bundle agent check { classes: "not_ok" xor => { "this_was_not_defined", "neither_was_this", }; "ok" not => "not_ok"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } cfengine-3.6.2/tests/acceptance/02_classes/01_basic/027.c0000644000175100017510000000222312236160673022244 0ustar00a10038a1003800000000000000#include #include #include #define CF_HASHTABLESIZE 8192 #define HOURLY 12 main() { char s[] = "a"; char c; int hash, box, minblocks; int period=HOURLY-1; char *boxes[HOURLY]; for (c=0; c {\n"); for (c=0; c> 6 ); } h += ( h << 3 ); h ^= ( h >> 11 ); h += ( h << 15 ); return (h & (hashtablesize-1)); } cfengine-3.6.2/tests/acceptance/06_storage/0000755000175100017510000000000012236160673020223 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/06_storage/01_local/0000755000175100017510000000000012400110676021604 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/06_storage/01_local/staging/0000755000175100017510000000000012243421446023245 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/acceptance/06_storage/01_local/staging/002.cf0000644000175100017510000000212012243421446024053 0ustar00a10038a1003800000000000000####################################################### # # Test simple storage promises - free space not in range # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { storage: "/var" volume => test_volume, classes => test_set_class("fail","pass"); } body volume test_volume { freespace => "1000G"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" expression => "pass.!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 31 cfengine-3.6.2/tests/acceptance/06_storage/01_local/001.cf0000644000175100017510000000252112400110676022416 0ustar00a10038a1003800000000000000####################################################### # # Test simple storage promises - free space in range # ####################################################### body common control { inputs => { "../../default.cf.sub" }; bundlesequence => { default("$(this.promise_filename)") }; version => "1.0"; } ####################################################### bundle agent init { vars: "dummy" string => "dummy"; } ####################################################### bundle agent test { meta: "test_suppress_fail" string => "sunos_5_10|sunos_5_11", meta => { "redmine5234" }; vars: windows:: "path" string => "C:\\"; !windows:: "path" string => "/var"; storage: "$(path)" volume => test_volume, classes => test_set_class("pass","fail"); } body volume test_volume { freespace => "1k"; } body classes test_set_class(ok_class,notok_class) { promise_kept => { "$(ok_class)" }; promise_repaired => { "$(ok_class)" }; repair_failed => { "$(notok_class)" }; } ####################################################### bundle agent check { classes: "ok" expression => "pass.!fail"; reports: ok:: "$(this.promise_filename) Pass"; !ok:: "$(this.promise_filename) FAIL"; } ### PROJECT_ID: core ### CATEGORY_ID: 31 cfengine-3.6.2/tests/acceptance/mock_package_manager.c0000644000175100017510000003057512400110676022515 0ustar00a10038a1003800000000000000#include #include #include // Syntax() #include static char AVAILABLE_PACKAGES_FILE_NAME[PATH_MAX]; static char INSTALLED_PACKAGES_FILE_NAME[PATH_MAX]; static const int MAX_PACKAGE_ENTRY_LENGTH = 256; #define DEFAULT_ARCHITECTURE "x666" #define Error(msg) fprintf(stderr, "%s:%d: %s", __FILE__, __LINE__, msg) static const struct option OPTIONS[] = { {"clear-installed", no_argument, 0, 'c'}, {"clear-available", no_argument, 0, 'C'}, {"list-installed", no_argument, 0, 'l'}, {"list-available", no_argument, 0, 'L'}, {"populate-available", required_argument, 0, 'P'}, {"add", required_argument, 0, 'a'}, {"delete", required_argument, 0, 'd'}, {"reinstall", required_argument, 0, 'r'}, {"update", required_argument, 0, 'u'}, {"addupdate", required_argument, 0, 'U'}, {"verify", required_argument, 0, 'v'}, {NULL, 0, 0, '\0'} }; static const char *HINTS[] = { "Clear all installed imaginary packages", "Clear all available imaginary packages", "List installed imarginary packages", "List imaginary packages available to be installed", "Add an imaginary package to list of available", "Add an imaginary package", "Delete a previously imagined package", "Reinstall an imaginary package", "Update a previously imagined package", "Add or update an imaginary package", "Verify a previously imagined package", NULL }; typedef struct { char *name; char *version; char *arch; } Package; typedef struct { char *name; char *version; char *arch; } PackagePattern; /******************************************************************************/ static char *SerializePackage(Package *package) { char *s; xasprintf(&s, "%s:%s:%s", package->name, package->version, package->arch); return s; } /******************************************************************************/ static char *SerializePackagePattern(PackagePattern *pattern) { char *s; xasprintf(&s, "%s:%s:%s", pattern->name ? pattern->name : "*", pattern->version ? pattern->version : "*", pattern->arch ? pattern->arch : "*"); return s; } /******************************************************************************/ static Package *DeserializePackage(const char *entry) { Package *package = xcalloc(1, sizeof(Package)); char *entry_copy = xstrdup(entry); package->name = strtok(entry_copy, ":"); package->version = strtok(NULL, ":"); package->arch = strtok(NULL, ":"); if (package->name == NULL || strcmp(package->name, "*") == 0 || package->version == NULL || strcmp(package->version, "*") == 0 || package->arch == NULL || strcmp(package->arch, "*") == 0) { fprintf(stderr, "Incomplete package specification: %s:%s:%s\n", package->name, package->version, package->arch); exit(255); } return package; } /******************************************************************************/ static bool IsWildcard(const char *str) { return str && (strcmp(str, "*") == 0 || strcmp(str, "") == 0); } /******************************************************************************/ static void CheckWellformedness(const char *str) { if (str && strchr(str, '*') != NULL) { fprintf(stderr, "* is encountered in pattern not as wildcard: '%s'\n", str); exit(255); } } /******************************************************************************/ static PackagePattern *NewPackagePattern(const char *name, const char *version, const char *arch) { PackagePattern *pattern = xcalloc(1, sizeof(PackagePattern)); pattern->name = name ? xstrdup(name) : NULL; pattern->version = version ? xstrdup(version) : NULL; pattern->arch = arch ? xstrdup(arch) : NULL; return pattern; } /******************************************************************************/ static PackagePattern *DeserializePackagePattern(const char *entry) { //PackagePattern *pattern = xcalloc(1, sizeof(PackagePattern)); char *entry_copy = xstrdup(entry); char *name = strtok(entry_copy, ":"); if (IsWildcard(name)) { name = NULL; } CheckWellformedness(name); char *version = strtok(NULL, ":"); if (IsWildcard(version)) { version = NULL; } CheckWellformedness(version); char *arch = strtok(NULL, ":"); if (arch == NULL) { arch = DEFAULT_ARCHITECTURE; } else if (IsWildcard(arch)) { arch = NULL; } CheckWellformedness(arch); if (strtok(NULL, ":") != NULL) { fprintf(stderr, "Too many delimiters are encountered in pattern: %s\n", entry); exit(255); } return NewPackagePattern(name, version, arch); } /******************************************************************************/ static Seq *ReadPackageEntries(const char *database_filename) { FILE *packages_file = fopen(database_filename, "r"); Seq *packages = SeqNew(1000, NULL); if (packages_file != NULL) { char serialized_package[MAX_PACKAGE_ENTRY_LENGTH]; while (fscanf(packages_file, "%s\n", serialized_package) != EOF) { Package *package = DeserializePackage(serialized_package); SeqAppend(packages, package); } fclose(packages_file); } return packages; } /******************************************************************************/ static void SavePackages(const char *database_filename, Seq *package_entries) { FILE *packages_file = fopen(database_filename, "w"); for (size_t i = 0; i < SeqLength(package_entries); i++) { fprintf(packages_file, "%s\n", SerializePackage(SeqAt(package_entries, i))); } fclose(packages_file); } /******************************************************************************/ static PackagePattern *MatchAllVersions(const Package *p) { return NewPackagePattern(p->name, NULL, p->arch); } /******************************************************************************/ static PackagePattern *MatchSame(const Package *p) { return NewPackagePattern(p->name, p->version, p->arch); } /******************************************************************************/ static bool MatchPackage(PackagePattern *a, Package *b) { return (a->name == NULL || strcmp(a->name, b->name) == 0) && (a->version == NULL || strcmp(a->version, b->version) == 0) && (a->arch == NULL || strcmp(a->arch, b->arch) == 0); } /******************************************************************************/ static Seq *FindPackages(const char *database_filename, PackagePattern *pattern) { Seq *db = ReadPackageEntries(database_filename); Seq *matching = SeqNew(1000, NULL); for (size_t i = 0; i < SeqLength(db); i++) { Package *package = SeqAt(db, i); if (MatchPackage(pattern, package)) { SeqAppend(matching, package); } } return matching; } /******************************************************************************/ static void ShowPackages(FILE *out, Seq *package_entries) { for (size_t i = 0; i < SeqLength(package_entries); i++) { fprintf(out, "%s\n", SerializePackage(SeqAt(package_entries, i))); } } /******************************************************************************/ static void ClearPackageList(const char *db_file_name) { FILE *packages_file = fopen(db_file_name, "w"); if (packages_file == NULL) { fprintf(stderr, "fopen(%s): %s", INSTALLED_PACKAGES_FILE_NAME, strerror(errno)); exit(255); } fclose(packages_file); } /******************************************************************************/ static void ClearInstalledPackages(void) { ClearPackageList(INSTALLED_PACKAGES_FILE_NAME); } /******************************************************************************/ static void ClearAvailablePackages(void) { ClearPackageList(AVAILABLE_PACKAGES_FILE_NAME); } /******************************************************************************/ static void AddPackage(PackagePattern *pattern) { fprintf(stderr, "Trying to install all packages matching pattern %s\n", SerializePackagePattern(pattern)); Seq *matching_available = FindPackages(AVAILABLE_PACKAGES_FILE_NAME, pattern); if (SeqLength(matching_available) == 0) { fprintf(stderr, "Unable to find any package matching %s\n", SerializePackagePattern(pattern)); exit(EXIT_FAILURE); } for (size_t i = 0; i < SeqLength(matching_available); i++) { Package *p = SeqAt(matching_available, i); PackagePattern *pat = MatchAllVersions(p); if (SeqLength(FindPackages(INSTALLED_PACKAGES_FILE_NAME, pat)) > 0) { fprintf(stderr, "Package %s is already installed.\n", SerializePackage(p)); exit(EXIT_FAILURE); } } Seq *installed_packages = ReadPackageEntries(INSTALLED_PACKAGES_FILE_NAME); for (size_t i = 0; i < SeqLength(matching_available); i++) { Package *p = SeqAt(matching_available, i); SeqAppend(installed_packages, p); fprintf(stderr, "Succesfully installed package %s\n", SerializePackage(p)); } SavePackages(INSTALLED_PACKAGES_FILE_NAME, installed_packages); exit(EXIT_SUCCESS); } /******************************************************************************/ static void PopulateAvailable(const char *arg) { Package *p = DeserializePackage(arg); PackagePattern *pattern = MatchSame(p); if (SeqLength(FindPackages(AVAILABLE_PACKAGES_FILE_NAME, pattern)) > 0) { fprintf(stderr, "Skipping already available package %s\n", SerializePackage(p)); return; } Seq *available_packages = ReadPackageEntries(AVAILABLE_PACKAGES_FILE_NAME); SeqAppend(available_packages, p); SavePackages(AVAILABLE_PACKAGES_FILE_NAME, available_packages); } /******************************************************************************/ int main(int argc, char *argv[]) { extern char *optarg; int option_index = 0; int c; #ifdef __MINGW32__ InitializeWindows(); #endif char *workdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); char *tempdir = getenv("TEMP"); if (!workdir && !tempdir) { fprintf(stderr, "Please set either CFENGINE_TEST_OVERRIDE_WORKDIR or TEMP environment variables\n" "to a valid directory.\n"); return 2; } xsnprintf(AVAILABLE_PACKAGES_FILE_NAME, 256, "%s/cfengine-mock-package-manager-available", workdir ? workdir : tempdir); xsnprintf(INSTALLED_PACKAGES_FILE_NAME, 256, "%s/cfengine-mock-package-manager-installed", workdir ? workdir : tempdir); while ((c = getopt_long(argc, argv, "", OPTIONS, &option_index)) != EOF) { PackagePattern *pattern = NULL; switch (c) { case 'c': ClearInstalledPackages(); break; case 'C': ClearAvailablePackages(); break; case 'l': { Seq *installed_packages = ReadPackageEntries(INSTALLED_PACKAGES_FILE_NAME); ShowPackages(stdout, installed_packages); } break; case 'L': { Seq *available_packages = ReadPackageEntries(AVAILABLE_PACKAGES_FILE_NAME); ShowPackages(stdout, available_packages); } break; case 'a': pattern = DeserializePackagePattern(optarg); AddPackage(pattern); break; case 'P': PopulateAvailable(optarg); break; /* case 'd': */ /* DeletePackage(pattern); */ /* break; */ /* case 'r': */ /* ReinstallPackage(pattern); */ /* break; */ /* case 'u': */ /* UpdatePackage(pattern); */ /* break; */ /* case 'U': */ /* AddUpdatePackage(pattern); */ /* break; */ /* case 'v': */ /* VerifyPackage(pattern); */ /* break; */ default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "mock-package-manager - pretend that you are managing packages!", OPTIONS, HINTS, false); FileWriterDetach(w); } exit(EXIT_FAILURE); } } return 0; } cfengine-3.6.2/tests/Makefile.in0000664000175100017510000005152412412324464016236 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = tests DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ SUBDIRS = unit load acceptance all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/tests/Makefile.am0000664000175100017510000000003712411001073016201 0ustar00a10038a1003800000000000000SUBDIRS = unit load acceptance cfengine-3.6.2/tests/load/0000775000175100017510000000000012413020725015073 5ustar00a10038a1003800000000000000cfengine-3.6.2/tests/load/lastseen_load.c0000664000175100017510000000342412400110676020060 0ustar00a10038a1003800000000000000#include #include #include char CFWORKDIR[CF_BUFSIZE] = "/tmp"; void UpdateLastSawHost(const char *hostkey, const char *address, bool incoming, time_t timestamp); int main() { xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/lastseen_migration_test.XXXXXX"); mkdtemp(CFWORKDIR); for (int i = 0; i < 1000000; ++i) { if ((i % 10000) == 0) { printf("."); fflush(stdout); } char hostkey[50]; xsnprintf(hostkey, 50, "SHA-%040d", i); char ip[50]; xsnprintf(ip, 50, "250.%03d.%03d.%03d", i / (256*256), (i / 256) % 256, i % 256); UpdateLastSawHost(hostkey, ip, false, i); UpdateLastSawHost(hostkey, ip, true, 2000000 - i); } char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); return 0; } /* STUBS */ void FatalError(char *s, ...) { exit(42); } HashMethod CF_DEFAULT_DIGEST; const char *const DAY_TEXT[] = {}; const char *const MONTH_TEXT[] = {}; const char *const SHIFT_TEXT[] = {}; pthread_mutex_t *cft_output; char VIPADDRESS[CF_MAX_IP_LEN]; RSA *PUBKEY; Item *IdempPrependItem(Item **liststart, const char *itemstring, const char *classes) { exit(42); } bool IsItemIn(Item *list, const char *item) { exit(42); } void DeleteItemList(Item *item) { exit(42); } bool MINUSF; char *MapAddress(char *addr) { exit(42); } char *HashPrintSafe(char *dst, size_t dst_size, const unsigned char *digest, HashMethod type, bool use_prefix) { exit(42); } void HashPubKey(RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type) { exit(42); } void *ConstraintGetRvalValue(char *lval, Promise *promise, char type) { exit(42); } cfengine-3.6.2/tests/load/run_lastseen_threaded_load.sh0000775000175100017510000000006112400110676022771 0ustar00a10038a1003800000000000000#!/bin/sh ./lastseen_threaded_load -c 1 4 1 1 cfengine-3.6.2/tests/load/lastseen_threaded_load.c0000664000175100017510000004206712400110676021726 0ustar00a10038a1003800000000000000#include #include #include #include /* GracefulTerminate */ #include /* ThreadLock */ #include /* xclock_gettime */ #include /* basename */ unsigned int ROUND_DURATION = 10; /* how long to run each loop */ #define NHOSTS 5000 /* how many hosts to store in db */ #define MAX_NUM_THREADS 10000 #define MAX_NUM_FORKS 10000 /* TODO all these counters should be guarded by mutex since they are written * from child threads and read from the main one. It's only a test, so * @ediosyncratic please spare me. */ time_t START_TIME; char CFWORKDIR[CF_BUFSIZE]; unsigned long lastsaw_COUNTER[MAX_NUM_THREADS]; unsigned long keycount_COUNTER[MAX_NUM_THREADS]; unsigned long scanlastseen_COUNTER[MAX_NUM_THREADS]; int CHILDREN_OUTPUTS[MAX_NUM_FORKS]; volatile bool DONE; /* Counter and wait condition to see if test properly finished. */ unsigned long FINISHED_THREADS = 0; unsigned long TOTAL_NUM_THREADS; pthread_mutex_t end_mtx = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; pthread_cond_t end_cond = PTHREAD_COND_INITIALIZER; void UpdateLastSawHost(const char *hostkey, const char *address, bool incoming, time_t timestamp); static bool PurgeCurrentLastSeen() { CF_DB *db_conn = NULL; CF_DBC *db_cursor = NULL; char *key = NULL; void *value = NULL; int ksize = 0, vsize = 0; if (!OpenDB(&db_conn, dbid_lastseen)) { Log(LOG_LEVEL_ERR, "Unable to open lastseen db"); return false; } if (!NewDBCursor(db_conn, &db_cursor)) { Log(LOG_LEVEL_ERR, "Unable to scan lastseen db"); CloseDB(db_conn); return false; } while (NextDB(db_cursor, &key, &ksize, &value, &vsize)) { /* Only read the 'quality of connection' entries */ if (key[0] != 'q') { continue; } time_t then = 0; if (value != NULL) { if (sizeof(KeyHostSeen) < vsize) { Log(LOG_LEVEL_ERR, "Invalid entry in lastseen database."); continue; } KeyHostSeen entry = { 0 }; memcpy(&entry, value, vsize); then = entry.lastseen; } if (then - START_TIME > NHOSTS) { DBCursorDeleteEntry(db_cursor); Log(LOG_LEVEL_DEBUG, "Deleting expired entry for %s", key); continue; } } DeleteDBCursor(db_cursor); CloseDB(db_conn); return true; } static bool callback(const char *hostkey ARG_UNUSED, const char *address ARG_UNUSED, bool incoming ARG_UNUSED, const KeyHostSeen *quality ARG_UNUSED, void *ctx ARG_UNUSED) { return true; } /* ============== WORKER THREADS ================ */ static void thread_exit_clean() { /* Signal that we finished. */ ThreadLock(&end_mtx); FINISHED_THREADS++; if (FINISHED_THREADS >= TOTAL_NUM_THREADS) { pthread_cond_signal(&end_cond); } ThreadUnlock(&end_mtx); } void *lastsaw_worker_thread(void *arg) { int thread_id = (intptr_t) arg; size_t i = 0; while (!DONE) { char hostkey[50]; xsnprintf(hostkey, sizeof(hostkey), "SHA-%040zx", i); char ip[50]; xsnprintf(ip, sizeof(ip), "250.%03zu.%03zu.%03zu", i / (256*256), (i / 256) % 256, i % 256); UpdateLastSawHost(hostkey, ip, ((i % 2 == 0) ? LAST_SEEN_ROLE_ACCEPT : LAST_SEEN_ROLE_CONNECT), START_TIME + i); i = (i + 1) % NHOSTS; lastsaw_COUNTER[thread_id]++; } thread_exit_clean(); return NULL; } void *keycount_worker_thread(void *arg) { int id = (intptr_t) arg; while (!DONE) { LastSeenHostKeyCount(); keycount_COUNTER[id]++; } thread_exit_clean(); return NULL; } void *scanlastseen_worker_thread(void *arg) { int id = (intptr_t) arg; while (!DONE) { ScanLastSeenQuality(callback, NULL); scanlastseen_COUNTER[id]++; } thread_exit_clean(); return NULL; } /* ============== END OF WORKER THREADS ================ */ /* ============== CHILD PROCESS ======================== */ unsigned long child_COUNTER; int PIPE_FD[2]; FILE *PARENT_INPUT; bool child_START = false; void print_progress_sighandler(int signum ARG_UNUSED) { fprintf(PARENT_INPUT, "%5lu", child_COUNTER); putc('\0', PARENT_INPUT); fflush(PARENT_INPUT); child_COUNTER = 0; } /* First time the signal is received, it interrupts the sleep() syscall and * sets child_START to true, which causes db crunching to start. Second time * child_START is set to false and we exit the child process. */ void startstop_handler(int signum ARG_UNUSED) { child_START = !child_START; } void worker_process() { struct sigaction new_handler; int ret; /* 1a. Register SIGUSR1 handler so that we start/finish the test */ new_handler = (struct sigaction) { .sa_handler = startstop_handler }; sigemptyset(&new_handler.sa_mask); ret = sigaction(SIGUSR1, &new_handler, NULL); if (ret != 0) { perror("sigaction"); exit(EXIT_FAILURE); } /* 1b. Register SIGUSR2 handler so that we report progress when pinged */ new_handler = (struct sigaction) { .sa_handler = print_progress_sighandler }; sigemptyset(&new_handler.sa_mask); ret = sigaction(SIGUSR2, &new_handler, NULL); if (ret != 0) { perror("sigaction"); exit(EXIT_FAILURE); } /* 2. Wait for signal */ unsigned retu = sleep(100); if (retu == 0) { fprintf(stderr, "Child was never signaled to start, exiting!\n"); exit(EXIT_FAILURE); } /* 3. DO THE WORK until SIGUSR1 comes */ while (child_START) { if (child_COUNTER % 10 == 0) { LastSeenHostKeyCount(); } else if (child_COUNTER % 10 == 1) { ScanLastSeenQuality(callback, NULL); } else if (child_COUNTER % 10 == 2) { PurgeCurrentLastSeen(); } else { char hostkey[50]; xsnprintf(hostkey, sizeof(hostkey), "SHA-%040lx", child_COUNTER); char ip[50]; xsnprintf(ip, sizeof(ip), "250.%03lu.%03lu.%03lu", child_COUNTER / (256*256), (child_COUNTER / 256) % 256, child_COUNTER % 256); UpdateLastSawHost(hostkey, ip, ((child_COUNTER % 2 == 0) ? LAST_SEEN_ROLE_ACCEPT : LAST_SEEN_ROLE_CONNECT), START_TIME + child_COUNTER); } child_COUNTER++; } } /* ============== END OF CHILD PROCESS ================= */ void spawn_worker_threads(void *(*worker_routine) (void *), int num_threads, const char *description) { pthread_t tid[num_threads]; printf("Spawning %s worker threads: ", description); for (int i = 0; i < num_threads; i++) { int ret = pthread_create(&tid[i], NULL, worker_routine, (void *)(intptr_t) i); if (ret != 0) { fprintf(stderr, "pthread_create(%d): %s", i, GetErrorStrFromCode(ret)); exit(EXIT_FAILURE); } printf("%i ", i+1); } printf("done!\n"); } void print_progress(int lastsaw_num_threads, int keycount_num_threads, int scanlastseen_num_threads, int num_children) { for (int j = 0; j < lastsaw_num_threads; j++) { printf("%5lu", lastsaw_COUNTER[j]); lastsaw_COUNTER[j] = 0; } if (keycount_num_threads > 0) { fputs(" | ", stdout); } for (int j = 0; j < keycount_num_threads; j++) { printf("%5lu", keycount_COUNTER[j]); keycount_COUNTER[j] = 0; } if (scanlastseen_num_threads > 0) { fputs(" | ", stdout); } for (int j = 0; j < scanlastseen_num_threads; j++) { printf("%5lu", scanlastseen_COUNTER[j]); scanlastseen_COUNTER[j] = 0; } if (num_children > 0) { fputs(" | Children:", stdout); } for (int j = 0; j < num_children; j++) { char child_report[32] = {0}; int ret = read(CHILDREN_OUTPUTS[j], child_report, sizeof(child_report) - 1); if (ret <= 0) { fprintf(stderr, "Couldn't read from child %d, it probably died!\n", j); exit(EXIT_FAILURE); } printf("%5s", child_report); } } void print_usage(const char *argv0) { printf("\ \n\ Usage:\n\ %s [options] LASTSAW_NUM_THREADS [KEYCOUNT_NUM_THREADS [SCAN_NUM_THREADS]]\n\ \n\ This program creates many threads and optionally many processes stressing the\n\ lastseen database.\n\ \n\ Options:\n\ -d N: Duration of each round of testing in seconds (default is 10s)\n\ -c N: After finishing all rounds with threads, N spawned child\n\ processes shall apply a mixed workload to the database each one\n\ for another round (default is 0, i.e. don't fork children)\n\ \n", argv0); } void parse_args(int argc, char *argv[], int *lastsaw_num_threads, int *keycount_num_threads, int *scanlastseen_num_threads, int *num_forked_children) { *lastsaw_num_threads = 0; *keycount_num_threads = 0; *scanlastseen_num_threads = 0; *num_forked_children = 0; int i = 1; while (i < argc && argv[i][0] == '-') { switch (argv[i][1]) { case 'd': { i++; int N = 0; int ret = sscanf((argv[i] != NULL) ? argv[i] : "", "%d", &N); if (ret != 1 || N <= 0) { print_usage(basename(argv[0])); exit(EXIT_FAILURE); } ROUND_DURATION = N; break; } case 'c': { i++; int N = -1; int ret = sscanf((argv[i] != NULL) ? argv[i] : "", "%d", &N); if (ret != 1 || N < 0) { print_usage(basename(argv[0])); exit(EXIT_FAILURE); } *num_forked_children = N; break; } default: print_usage(basename(argv[0])); exit(EXIT_FAILURE); } i++; } /* Last 3 arguments */ if (i < argc) { sscanf(argv[i], "%d", lastsaw_num_threads); } if (i + 1 < argc) { sscanf(argv[i + 1], "%d", keycount_num_threads); } if (i + 2 < argc) { sscanf(argv[i + 2], "%d", scanlastseen_num_threads); } /* lastsaw_num_threads is the only /mandatory/ argument. */ if (*lastsaw_num_threads <= 0 || *lastsaw_num_threads > MAX_NUM_THREADS) { print_usage(basename(argv[0])); exit(EXIT_FAILURE); } if (*num_forked_children > 1) /* TODO FIX! */ { printf("WARNING: Currently only one forked child is supported TODO FIX!\n"); *num_forked_children = 1; } } int main(int argc, char *argv[]) { int ret; int lastsaw_num_threads, keycount_num_threads, scanlastseen_num_threads; int num_forked_children; LogSetGlobalLevel(LOG_LEVEL_DEBUG); parse_args(argc, argv, &lastsaw_num_threads, &keycount_num_threads, &scanlastseen_num_threads, &num_forked_children); TOTAL_NUM_THREADS = lastsaw_num_threads + keycount_num_threads + scanlastseen_num_threads; xsnprintf(CFWORKDIR, sizeof(CFWORKDIR), "/tmp/lastseen_threaded_load.XXXXXX"); char *retp = mkdtemp(CFWORKDIR); if (retp == NULL) { perror("mkdtemp"); exit(EXIT_FAILURE); } printf("Work directory: %s\n", CFWORKDIR); START_TIME = time(NULL); /* === SPAWN A CHILD PROCESS FOR LATER === */ pid_t child; if (num_forked_children > 0) { ret = pipe(PIPE_FD); if (ret != 0) { perror("pipe"); exit(EXIT_FAILURE); } child = fork(); if (child == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (child == 0) /* child */ { /* We only write to the pipe. */ close(PIPE_FD[0]); /* Connect pipe to a FILE to talk to parent via fprintf(). */ PARENT_INPUT = fdopen(PIPE_FD[1], "w"); if (PARENT_INPUT == NULL) { perror("child fdopen"); exit(EXIT_FAILURE); } worker_process(); exit(EXIT_SUCCESS); } /* We only read from the pipe. */ close(PIPE_FD[1]); CHILDREN_OUTPUTS[0] = PIPE_FD[0]; } printf("Showing number of operations per second:\n\n"); /* === CREATE lastsaw() WORKER THREADS === */ spawn_worker_threads(lastsaw_worker_thread, lastsaw_num_threads, "UpdateLastSawHost()"); /* === PRINT PROGRESS FOR ROUND_DURATION SECONDS === */ for (int i = 0; i < ROUND_DURATION; i++) { sleep(1); print_progress(lastsaw_num_threads, 0, 0, 0); putc('\n', stdout); } /* === CREATE CURSOR COUNTING WORKERS === */ if (keycount_num_threads > 0) { spawn_worker_threads(keycount_worker_thread, keycount_num_threads, "LastSeenHostKeyCount()"); /* === PRINT PROGRESS FOR ROUND_DURATION SECONDS === */ for (int i = 0; i < ROUND_DURATION; i++) { sleep(1); print_progress(lastsaw_num_threads, keycount_num_threads, 0, 0); putc('\n', stdout); } } /* === CREATE CURSOR READING WORKERS === */ if (scanlastseen_num_threads > 0) { spawn_worker_threads(scanlastseen_worker_thread, scanlastseen_num_threads, "ScanLastSeenQuality()"); /* === PRINT PROGRESS FOR ROUND_DURATION SECONDS === */ for (int i = 0; i < ROUND_DURATION; i++) { sleep(1); print_progress(lastsaw_num_threads, keycount_num_threads, scanlastseen_num_threads, 0); putc('\n', stdout); } } /* === START CHILD PROCESS WORK === */ if (num_forked_children > 0) { printf("Doing mix of operations in forked children\n"); kill(child, SIGUSR1); /* === PRINT PROGRESS FOR ROUND_DURATION SECONDS === */ for (int i = 0; i < ROUND_DURATION; i++) { sleep(1); kill(child, SIGUSR2); /* receive progress from child */ print_progress(lastsaw_num_threads, keycount_num_threads, scanlastseen_num_threads, 1); putc('\n', stdout); } kill(child, SIGUSR1); /* signal child to finish */ } /* === TEST FINISHED, signal threads to exit === */ DONE = true; /* === WAIT AT MOST 30 SECONDS FOR EVERYBODY TO FINISH === */ printf("Waiting at most 30s for all threads to finish...\n"); unsigned long finished_children = 0; time_t wait_starttime = time(NULL); time_t seconds_waited = 0; ThreadLock(&end_mtx); while (!( FINISHED_THREADS == TOTAL_NUM_THREADS && finished_children == num_forked_children) && seconds_waited < 30) { struct timespec ts; xclock_gettime(CLOCK_REALTIME, &ts); /* Wait at most 1s for the thread to signal us before looping over. */ ts.tv_sec++; if (FINISHED_THREADS < TOTAL_NUM_THREADS) { pthread_cond_timedwait(&end_cond, &end_mtx, &ts); } else { sleep(1); } /* Has any child process died? */ while (waitpid(-1, NULL, WNOHANG) > 0) { finished_children++; } seconds_waited = time(NULL) - wait_starttime; } ThreadUnlock(&end_mtx); /* === CLEAN UP TODO register these with atexit() === */ int retval = EXIT_SUCCESS; if (finished_children != num_forked_children) { fprintf(stderr, "Forked child seems to be still alive, killing it!\n"); GracefulTerminate(child, PROCESS_START_TIME_UNKNOWN); wait(NULL); retval = EXIT_FAILURE; } if (FINISHED_THREADS != TOTAL_NUM_THREADS) { fprintf(stderr, "Only %lu of %lu threads actually finished!\n", FINISHED_THREADS, TOTAL_NUM_THREADS); retval = EXIT_FAILURE; } if (retval == EXIT_SUCCESS) { printf("DONE!\n\n"); } char *cmd; xasprintf(&cmd, "rm -rf '%s'", CFWORKDIR); system(cmd); free(cmd); return retval; } cfengine-3.6.2/tests/load/Makefile.in0000664000175100017510000012107412412324464017153 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @XNU_FALSE@check_PROGRAMS = db_load$(EXEEXT) lastseen_load$(EXEEXT) \ @XNU_FALSE@ lastseen_threaded_load$(EXEEXT) subdir = tests/load DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__db_load_SOURCES_DIST = db_load.c @XNU_FALSE@am_db_load_OBJECTS = db_load.$(OBJEXT) db_load_OBJECTS = $(am_db_load_OBJECTS) @XNU_FALSE@db_load_DEPENDENCIES = ../unit/libdb.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__lastseen_load_SOURCES_DIST = lastseen_load.c \ $(srcdir)/../../libpromises/lastseen.c \ $(srcdir)/../../libutils/statistics.c @XNU_FALSE@am_lastseen_load_OBJECTS = lastseen_load.$(OBJEXT) \ @XNU_FALSE@ lastseen.$(OBJEXT) statistics.$(OBJEXT) lastseen_load_OBJECTS = $(am_lastseen_load_OBJECTS) @XNU_FALSE@lastseen_load_DEPENDENCIES = ../unit/libdb.la \ @XNU_FALSE@ ../../libpromises/libpromises.la lastseen_threaded_load_SOURCES = lastseen_threaded_load.c lastseen_threaded_load_OBJECTS = lastseen_threaded_load.$(OBJEXT) lastseen_threaded_load_DEPENDENCIES = ../unit/libtest.la \ ../../libpromises/libpromises.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(db_load_SOURCES) $(lastseen_load_SOURCES) \ lastseen_threaded_load.c DIST_SOURCES = $(am__db_load_SOURCES_DIST) \ $(am__lastseen_load_SOURCES_DIST) lastseen_threaded_load.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ # automake does not support "maude_LIBS" variables. We can only alter # the generic LIBS one. In case the functions are mocked in the test # implementation, then we are pretty sure that they will be overriden by # our local implementation. So we include *everything*... LIBS = $(CORE_LIBS) LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ AM_LDFLAGS = $(CORE_LDFLAGS) # Those tests use stub functions interposition which does not work (yet) # under OS X. Another way of stubbing functions from libpromises is needed. @XNU_FALSE@AM_CPPFLAGS = $(CORE_CPPFLAGS) \ @XNU_FALSE@ $(ENTERPRISE_CFLAGS) \ @XNU_FALSE@ -I../../libpromises \ @XNU_FALSE@ -I../../libutils \ @XNU_FALSE@ -I../../libcfnet \ @XNU_FALSE@ -I../../libpromises @XNU_FALSE@EXTRA_DIST = \ @XNU_FALSE@ run_db_load.sh \ @XNU_FALSE@ run_lastseen_threaded_load.sh @XNU_FALSE@TESTS = \ @XNU_FALSE@ run_db_load.sh \ @XNU_FALSE@ run_lastseen_threaded_load.sh @XNU_FALSE@db_load_SOURCES = db_load.c @XNU_FALSE@db_load_LDADD = ../unit/libdb.la @XNU_FALSE@lastseen_load_SOURCES = lastseen_load.c \ @XNU_FALSE@ $(srcdir)/../../libpromises/lastseen.c \ @XNU_FALSE@ $(srcdir)/../../libutils/statistics.c @XNU_FALSE@lastseen_load_LDADD = ../unit/libdb.la ../../libpromises/libpromises.la lastseen_threaded_load_LDADD = ../unit/libtest.la \ ../../libpromises/libpromises.la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(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) --foreign tests/load/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/load/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-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list db_load$(EXEEXT): $(db_load_OBJECTS) $(db_load_DEPENDENCIES) $(EXTRA_db_load_DEPENDENCIES) @rm -f db_load$(EXEEXT) $(AM_V_CCLD)$(LINK) $(db_load_OBJECTS) $(db_load_LDADD) $(LIBS) lastseen_load$(EXEEXT): $(lastseen_load_OBJECTS) $(lastseen_load_DEPENDENCIES) $(EXTRA_lastseen_load_DEPENDENCIES) @rm -f lastseen_load$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lastseen_load_OBJECTS) $(lastseen_load_LDADD) $(LIBS) lastseen_threaded_load$(EXEEXT): $(lastseen_threaded_load_OBJECTS) $(lastseen_threaded_load_DEPENDENCIES) $(EXTRA_lastseen_threaded_load_DEPENDENCIES) @rm -f lastseen_threaded_load$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lastseen_threaded_load_OBJECTS) $(lastseen_threaded_load_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen_load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen_threaded_load.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistics.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< lastseen.o: $(srcdir)/../../libpromises/lastseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lastseen.o -MD -MP -MF $(DEPDIR)/lastseen.Tpo -c -o lastseen.o `test -f '$(srcdir)/../../libpromises/lastseen.c' || echo '$(srcdir)/'`$(srcdir)/../../libpromises/lastseen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lastseen.Tpo $(DEPDIR)/lastseen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../../libpromises/lastseen.c' object='lastseen.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lastseen.o `test -f '$(srcdir)/../../libpromises/lastseen.c' || echo '$(srcdir)/'`$(srcdir)/../../libpromises/lastseen.c lastseen.obj: $(srcdir)/../../libpromises/lastseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lastseen.obj -MD -MP -MF $(DEPDIR)/lastseen.Tpo -c -o lastseen.obj `if test -f '$(srcdir)/../../libpromises/lastseen.c'; then $(CYGPATH_W) '$(srcdir)/../../libpromises/lastseen.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../../libpromises/lastseen.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lastseen.Tpo $(DEPDIR)/lastseen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../../libpromises/lastseen.c' object='lastseen.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lastseen.obj `if test -f '$(srcdir)/../../libpromises/lastseen.c'; then $(CYGPATH_W) '$(srcdir)/../../libpromises/lastseen.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../../libpromises/lastseen.c'; fi` statistics.o: $(srcdir)/../../libutils/statistics.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT statistics.o -MD -MP -MF $(DEPDIR)/statistics.Tpo -c -o statistics.o `test -f '$(srcdir)/../../libutils/statistics.c' || echo '$(srcdir)/'`$(srcdir)/../../libutils/statistics.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/statistics.Tpo $(DEPDIR)/statistics.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../../libutils/statistics.c' object='statistics.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o statistics.o `test -f '$(srcdir)/../../libutils/statistics.c' || echo '$(srcdir)/'`$(srcdir)/../../libutils/statistics.c statistics.obj: $(srcdir)/../../libutils/statistics.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT statistics.obj -MD -MP -MF $(DEPDIR)/statistics.Tpo -c -o statistics.obj `if test -f '$(srcdir)/../../libutils/statistics.c'; then $(CYGPATH_W) '$(srcdir)/../../libutils/statistics.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../../libutils/statistics.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/statistics.Tpo $(DEPDIR)/statistics.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../../libutils/statistics.c' object='statistics.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o statistics.obj `if test -f '$(srcdir)/../../libutils/statistics.c'; then $(CYGPATH_W) '$(srcdir)/../../libutils/statistics.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../../libutils/statistics.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? run_db_load.sh.log: run_db_load.sh @p='run_db_load.sh'; \ b='run_db_load.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) run_lastseen_threaded_load.sh.log: run_lastseen_threaded_load.sh @p='run_lastseen_threaded_load.sh'; \ b='run_lastseen_threaded_load.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) 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 $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) 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-checkPROGRAMS clean-generic clean-libtool \ 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: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ ctags ctags-am 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 \ recheck tags tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/tests/load/Makefile.am0000664000175100017510000000221012411001073017113 0ustar00a10038a1003800000000000000# automake does not support "maude_LIBS" variables. We can only alter # the generic LIBS one. In case the functions are mocked in the test # implementation, then we are pretty sure that they will be overriden by # our local implementation. So we include *everything*... LIBS = $(CORE_LIBS) AM_LDFLAGS = $(CORE_LDFLAGS) # Those tests use stub functions interposition which does not work (yet) # under OS X. Another way of stubbing functions from libpromises is needed. if !XNU AM_CPPFLAGS = $(CORE_CPPFLAGS) \ $(ENTERPRISE_CFLAGS) \ -I../../libpromises \ -I../../libutils \ -I../../libcfnet \ -I../../libpromises EXTRA_DIST = \ run_db_load.sh \ run_lastseen_threaded_load.sh TESTS = \ run_db_load.sh \ run_lastseen_threaded_load.sh check_PROGRAMS = db_load lastseen_load lastseen_threaded_load db_load_SOURCES = db_load.c db_load_LDADD = ../unit/libdb.la lastseen_load_SOURCES = lastseen_load.c \ $(srcdir)/../../libpromises/lastseen.c \ $(srcdir)/../../libutils/statistics.c lastseen_load_LDADD = ../unit/libdb.la ../../libpromises/libpromises.la endif lastseen_threaded_load_LDADD = ../unit/libtest.la \ ../../libpromises/libpromises.la cfengine-3.6.2/tests/load/db_load.c0000664000175100017510000001420112400110676016622 0ustar00a10038a1003800000000000000#include #include #define MAX_THREADS 10000 #define DB_ID dbid_classes #define STATUS_SUCCESS 0 #define STATUS_FAILED_OPEN 1 #define STATUS_FAILED_CLOSE 2 #define STATUS_ERROR 3 #define READWRITEKEY 123123123 #define READWRITEDATA1 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" #define READWRITEDATA2 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" #define RECORD_COUNT_JUNK 7000 #define RECORD_COUNT_READWRITE 1 // only one read/write key above #define RECORD_COUNT_TOTAL (RECORD_COUNT_JUNK + RECORD_COUNT_READWRITE) #define VALUE_OFFSET1 10000 #define VALUE_OFFSET2 100000 char CFWORKDIR[CF_BUFSIZE]; static void WriteReadWriteData(CF_DB *db); static bool ReadWriteDataIsValid(char *data); static void DBWriteTestData(CF_DB *db); static void TestReadWriteData(CF_DB *db); static void TestCursorIteration(CF_DB *db); static void *contend(ARG_UNUSED void *param) { CF_DB *db; if (!OpenDB(&db, DB_ID)) { return (void *)STATUS_FAILED_OPEN; } DBWriteTestData(db); TestReadWriteData(db); TestCursorIteration(db); CloseDB(db); return (void *)STATUS_SUCCESS; } static void TestReadWriteData(CF_DB *db) { WriteReadWriteData(db); int iterations = rand() % 1000000; for(int i = 0; i < iterations; i++) { // sleep gets complicated in threads... } static const int key = READWRITEKEY; char readData[sizeof(READWRITEDATA1)]; if(!ReadComplexKeyDB(db, (const char *)&key, sizeof(key), readData, sizeof(readData))) { printf("Error read\n"); } if(!ReadWriteDataIsValid(readData)) { printf("corrupt data: \"%s\"\n", readData); } } static bool CoinFlip(void) { return rand() % 2 == 0; } static void WriteReadWriteData(CF_DB *db) { const char *const data = CoinFlip() ? READWRITEDATA1 : READWRITEDATA2; static const int key = READWRITEKEY; if(!WriteComplexKeyDB(db, (const char *)&key, sizeof(key), data, sizeof(READWRITEDATA1))) { printf("Error write!\n"); pthread_exit((void*)STATUS_ERROR); } } static bool ReadWriteDataIsValid(char *data) { return (strcmp(data, READWRITEDATA1) == 0 || strcmp(data, READWRITEDATA2) == 0); } static void TestCursorIteration(CF_DB *db) { CF_DBC *dbc; if(!NewDBCursor(db, &dbc)) { fprintf(stderr, "Test: could not create cursor"); pthread_exit((void*)STATUS_ERROR); exit(EXIT_FAILURE); } char *key; void *value; int key_sz, value_sz; int count = 0; while(NextDB(dbc, &key, &key_sz, &value, &value_sz)) { int key_num = *(int *)key; int value_num = *(int *)value; if(key_num >= 0 && key_num < RECORD_COUNT_JUNK) { if((key_num + VALUE_OFFSET1 != value_num) && (key_num + VALUE_OFFSET2 != value_num)) { printf("Error: key,value %d,%d are inconsistent\n", key_num, value_num); } } else if(key_num == READWRITEKEY) { if(!ReadWriteDataIsValid(value)) { printf("Error: ReadWrite data is invalid\n"); } } else { printf("Error: invalid key \"%s\"", key); } count++; } if(count != RECORD_COUNT_TOTAL) { printf("Error: During iteration count was %d (expected %d)\n", count, RECORD_COUNT_TOTAL); } if(!DeleteDBCursor(dbc)) { fprintf(stderr, "Test: could not delete cursor"); exit(EXIT_FAILURE); } } int WriteReturnValues(int retvals[MAX_THREADS], pthread_t tids[MAX_THREADS], int numthreads) { int failures = 0; for(int i = 0; i < numthreads; i++) { uintptr_t status; pthread_join(tids[i], (void **)&status); retvals[i] = status; if(status != STATUS_SUCCESS) { failures++; } } return failures; } static void Cleanup(void) { char cmd[CF_BUFSIZE]; xsnprintf(cmd, CF_BUFSIZE, "rm -rf '%s'", CFWORKDIR); system(cmd); } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "Usage: db_load \n"); exit(EXIT_FAILURE); } /* To clean up after databases are closed */ atexit(&Cleanup); xsnprintf(CFWORKDIR, CF_BUFSIZE, "/tmp/db_load.XXXXXX"); mkdtemp(CFWORKDIR); int numthreads = atoi(argv[1]); assert(numthreads < MAX_THREADS); srand(time(NULL)); pthread_t tids[MAX_THREADS]; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 65536); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for (int i = 0; i < numthreads; ++i) { int ret = pthread_create(&(tids[i]), &attr, &contend, NULL); if (ret != 0) { fprintf(stderr, "Unable to create thread: %s\n", strerror(ret)); } } pthread_attr_destroy(&attr); int retvals[MAX_THREADS]; int failures = WriteReturnValues(retvals, tids, numthreads); exit(failures); } static void DBWriteTestData(CF_DB *db) { for(int i = 0; i < RECORD_COUNT_JUNK; i++) { bool flip = CoinFlip(); int value_num = i + (flip ? VALUE_OFFSET1 : VALUE_OFFSET2); if (!WriteComplexKeyDB(db, (const char *)&i, sizeof(i), &value_num, sizeof(value_num))) { Log(LOG_LEVEL_ERR, "Unable to write data to database"); pthread_exit((void*)STATUS_ERROR); } } WriteReadWriteData(db); } /* Stub out */ void FatalError(ARG_UNUSED const EvalContext *ctx, char *fmt, ...) { if (fmt) { va_list ap; char buf[CF_BUFSIZE] = ""; va_start(ap, fmt); vsnprintf(buf, CF_BUFSIZE - 1, fmt, ap); va_end(ap); Log(LOG_LEVEL_ERR, "Fatal CFEngine error: %s", buf); } else { Log(LOG_LEVEL_ERR, "Fatal CFEngine error (no description)"); } exit(EXIT_FAILURE); } pthread_mutex_t test_lock = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; pthread_mutex_t *cft_dbhandle; const char *const DAY_TEXT[] = {}; const char *const MONTH_TEXT[] = {}; cfengine-3.6.2/tests/load/run_db_load.sh0000755000175100017510000000015612352022221017675 0ustar00a10038a1003800000000000000#!/bin/sh -e #for threads in 1 5 10 50; do while false; do echo db_load $threads ./db_load $threads done cfengine-3.6.2/cf-runagent/0000775000175100017510000000000012413020723015221 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-runagent/cf-runagent.c0000664000175100017510000005466212411001073017606 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ProtocolVersionParse */ #include typedef enum { RUNAGENT_CONTROL_HOSTS, RUNAGENT_CONTROL_PORT_NUMBER, RUNAGENT_CONTROL_FORCE_IPV4, RUNAGENT_CONTROL_TRUSTKEY, RUNAGENT_CONTROL_ENCRYPT, RUNAGENT_CONTROL_BACKGROUND, RUNAGENT_CONTROL_MAX_CHILD, RUNAGENT_CONTROL_OUTPUT_TO_FILE, RUNAGENT_CONTROL_OUTPUT_DIRECTORY, RUNAGENT_CONTROL_TIMEOUT, RUNAGENT_CONTROL_NONE } RunagentControl; static void ThisAgentInit(void); static GenericAgentConfig *CheckOpts(int argc, char **argv); static void KeepControlPromises(EvalContext *ctx, const Policy *policy); static int HailServer(EvalContext *ctx, char *host); static void SendClassData(AgentConnection *conn); static void HailExec(AgentConnection *conn, char *peer, char *recvbuffer, char *sendbuffer); static FILE *NewStream(char *name); /*******************************************************************/ /* Command line options */ /*******************************************************************/ static const char *const CF_RUNAGENT_SHORT_DESCRIPTION = "activate cf-agent on a remote host"; static const char *const CF_RUNAGENT_MANPAGE_LONG_DESCRIPTION = "cf-runagent connects to a list of running instances of " "cf-serverd. It allows foregoing the usual cf-execd schedule " "to activate cf-agent. Additionally, a user " "may send classes to be defined on the remote\n" "host. Two kinds of classes may be sent: classes to decide " "on which hosts cf-agent will be started, and classes that " "the user requests cf-agent should define on execution. " "The latter type is regulated by cf-serverd's role based access control."; static const struct option OPTIONS[] = { {"help", no_argument, 0, 'h'}, {"background", optional_argument, 0, 'b'}, {"debug", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"dry-run", no_argument, 0, 'n'}, {"version", no_argument, 0, 'V'}, {"file", required_argument, 0, 'f'}, {"define-class", required_argument, 0, 'D'}, {"select-class", required_argument, 0, 's'}, {"inform", no_argument, 0, 'I'}, {"remote-options", required_argument, 0, 'o'}, {"diagnostic", no_argument, 0, 'x'}, {"hail", required_argument, 0, 'H'}, {"interactive", no_argument, 0, 'i'}, {"timeout", required_argument, 0, 't'}, {"legacy-output", no_argument, 0, 'l'}, {"color", optional_argument, 0, 'C'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { "Print the help message", "Parallelize connections (50 by default)", "Enable debugging output", "Output verbose information about the behaviour of the agent", "All talk and no action mode - make no changes, only inform of promises not kept", "Output the version of the software", "Specify an alternative input file than the default", "Define a list of comma separated classes to be sent to a remote agent", "Define a list of comma separated classes to be used to select remote agents by constraint", "Print basic information about changes made to the system, i.e. promises repaired", "Pass options to a remote server process", "Activate internal diagnostics (developers only)", "Hail the following comma-separated lists of hosts, overriding default list", "Enable interactive mode for key trust", "Connection timeout, seconds", "Use legacy output format", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", NULL }; extern const ConstraintSyntax CFR_CONTROLBODY[]; int INTERACTIVE = false; /* GLOBAL_A */ int OUTPUT_TO_FILE = false; /* GLOBAL_P */ char OUTPUT_DIRECTORY[CF_BUFSIZE] = ""; /* GLOBAL_P */ int BACKGROUND = false; /* GLOBAL_P GLOBAL_A */ int MAXCHILD = 50; /* GLOBAL_P GLOBAL_A */ char REMOTE_AGENT_OPTIONS[CF_MAXVARSIZE] = ""; /* GLOBAL_A */ const Rlist *HOSTLIST = NULL; /* GLOBAL_P GLOBAL_A */ char SENDCLASSES[CF_MAXVARSIZE] = ""; /* GLOBAL_A */ char DEFINECLASSES[CF_MAXVARSIZE] = ""; /* GLOBAL_A */ /*****************************************************************************/ int main(int argc, char *argv[]) { #if !defined(__MINGW32__) int count = 0; int status; int pid; #endif GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); Policy *policy = LoadPolicy(ctx, config); ThisAgentInit(); KeepControlPromises(ctx, policy); // Set RUNATTR using copy if (BACKGROUND && INTERACTIVE) { Log(LOG_LEVEL_ERR, "You cannot specify background mode and interactive mode together"); exit(EXIT_FAILURE); } /* HvB */ if (HOSTLIST) { const Rlist *rp = HOSTLIST; while (rp != NULL) { #ifdef __MINGW32__ if (BACKGROUND) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); BACKGROUND = false; } #else if (BACKGROUND) /* parallel */ { if (count <= MAXCHILD) { if (fork() == 0) /* child process */ { HailServer(ctx, RlistScalarValue(rp)); exit(EXIT_SUCCESS); } else /* parent process */ { rp = rp->next; count++; } } else { pid = wait(&status); Log(LOG_LEVEL_DEBUG, "child = %d, child number = %d", pid, count); count--; } } else /* serial */ #endif /* __MINGW32__ */ { HailServer(ctx, RlistScalarValue(rp)); rp = rp->next; } } /* end while */ } /* end if HOSTLIST */ #ifndef __MINGW32__ if (BACKGROUND) { Log(LOG_LEVEL_NOTICE, "Waiting for child processes to finish"); while (count > 1) { pid = wait(&status); Log(LOG_LEVEL_VERBOSE, "Child %d ended, number %d", pid, count); count--; } } #endif PolicyDestroy(policy); GenericAgentFinalize(ctx, config); return 0; } /*******************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_RUNAGENT); DEFINECLASSES[0] = '\0'; SENDCLASSES[0] = '\0'; while ((c = getopt_long(argc, argv, "t:q:db:vnKhIif:D:VSxo:s:MH:lC::", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'l': LEGACY_OUTPUT = true; break; case 'f': GenericAgentConfigSetInputFile(config, GetInputDir(), optarg); MINUSF = true; break; case 'b': BACKGROUND = true; if (optarg) { MAXCHILD = atoi(optarg); } break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case 'K': config->ignore_locks = true; break; case 's': strlcpy(SENDCLASSES, optarg, CF_MAXVARSIZE); if (strlen(optarg) > CF_MAXVARSIZE) { Log(LOG_LEVEL_ERR, "Argument too long (-s)"); exit(EXIT_FAILURE); } break; case 'D': strlcpy(DEFINECLASSES, optarg, CF_MAXVARSIZE); if (strlen(optarg) > CF_MAXVARSIZE) { Log(LOG_LEVEL_ERR, "Argument too long (-D)"); exit(EXIT_FAILURE); } break; case 'H': HOSTLIST = RlistFromSplitString(optarg, ','); break; case 'o': strlcpy(REMOTE_AGENT_OPTIONS, optarg, CF_MAXVARSIZE); break; case 'I': LogSetGlobalLevel(LOG_LEVEL_INFO); break; case 'i': INTERACTIVE = true; break; case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); break; case 'n': DONTDO = true; config->ignore_locks = true; break; case 't': CONNTIMEOUT = atoi(optarg); break; case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-runagent", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-runagent", time(NULL), CF_RUNAGENT_SHORT_DESCRIPTION, CF_RUNAGENT_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, true); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'x': Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired."); exit(EXIT_SUCCESS); case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-runagent", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_FAILURE); } } if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind)) { Log(LOG_LEVEL_ERR, "Too many arguments"); exit(EXIT_FAILURE); } return config; } /*******************************************************************/ static void ThisAgentInit(void) { umask(077); if (strstr(REMOTE_AGENT_OPTIONS, "--file") || strstr(REMOTE_AGENT_OPTIONS, "-f")) { Log(LOG_LEVEL_ERR, "The specified remote options include a useless --file option. The remote server has promised to ignore this, thus it is disallowed."); exit(EXIT_FAILURE); } } /********************************************************************/ static int HailServer(EvalContext *ctx, char *host) { assert(host != NULL); AgentConnection *conn; char sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], hostkey[CF_HOSTKEY_STRING_SIZE], user[CF_SMALLBUF]; bool gotkey; char reply[8]; bool trustkey = false; char *hostname, *port; ParseHostPort(host, &hostname, &port); if (hostname == NULL || strcmp(hostname, "localhost") == 0) { Log(LOG_LEVEL_INFO, "No remote hosts were specified to connect to"); return false; } if (port == NULL) { port = "5308"; } char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, hostname, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_ERR, "HailServer: ERROR, could not resolve '%s'", hostname); return false; } Address2Hostkey(hostkey, sizeof(hostkey), ipaddr); GetCurrentUserName(user, CF_SMALLBUF); if (INTERACTIVE) { Log(LOG_LEVEL_VERBOSE, "Using interactive key trust..."); gotkey = HavePublicKey(user, ipaddr, hostkey) != NULL; if (!gotkey) { printf("WARNING - You do not have a public key from host %s = %s\n", hostname, ipaddr); printf(" Do you want to accept one on trust? (yes/no)\n\n--> "); while (true) { if (fgets(reply, sizeof(reply), stdin) == NULL) { FatalError(ctx, "EOF trying to read answer from terminal"); } if (Chop(reply, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } if (strcmp(reply, "yes") == 0) { printf("Will trust the key...\n"); trustkey = true; break; } else if (strcmp(reply, "no") == 0) { printf("Will not trust the key...\n"); trustkey = false; break; } else { printf("Please reply yes or no...(%s)\n", reply); } } } } #ifndef __MINGW32__ if (BACKGROUND) { Log(LOG_LEVEL_INFO, "Hailing '%s' : %s, with options '%s' (parallel)", hostname, port, REMOTE_AGENT_OPTIONS); } else #endif { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_INFO, "..........................................................................."); Log(LOG_LEVEL_INFO, " * Hailing %s : %s, with options \"%s\" (serial)", hostname, port, REMOTE_AGENT_OPTIONS); Log(LOG_LEVEL_INFO, "..........................................................................."); } else { Log(LOG_LEVEL_INFO, "Hailing '%s' : %s, with options '%s' (serial)", hostname, port, REMOTE_AGENT_OPTIONS); } } const char *s = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_PROTOCOL_VERSION); ConnectionFlags connflags = { .protocol_version = ProtocolVersionParse(s), .trust_server = trustkey }; int err = 0; conn = ServerConnection(hostname, port, CONNTIMEOUT, connflags, &err); if (conn == NULL) { Log(LOG_LEVEL_VERBOSE, "No suitable server responded to hail"); return false; } /* Send EXEC command. */ HailExec(conn, hostname, recvbuffer, sendbuffer); return true; } /********************************************************************/ /* Level 2 */ /********************************************************************/ static void KeepControlPromises(EvalContext *ctx, const Policy *policy) { Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_RUNAGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_runagent"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in runagent control body", cp->lval); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_FORCE_IPV4].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TRUSTKEY].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_ENCRYPT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_PORT_NUMBER].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_BACKGROUND].lval) == 0) { /* * Only process this option if are is no -b or -i options specified on * command line. */ if (BACKGROUND || INTERACTIVE) { Log(LOG_LEVEL_WARNING, "'background_children' setting from 'body runagent control' is overridden by command-line option."); } else { BACKGROUND = BooleanFromString(value); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_MAX_CHILD].lval) == 0) { MAXCHILD = (short) IntFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_TO_FILE].lval) == 0) { OUTPUT_TO_FILE = BooleanFromString(value); continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_OUTPUT_DIRECTORY].lval) == 0) { if (IsAbsPath(value)) { strlcpy(OUTPUT_DIRECTORY, value, CF_BUFSIZE); Log(LOG_LEVEL_VERBOSE, "Setting output direcory to '%s'", OUTPUT_DIRECTORY); } continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_TIMEOUT].lval) == 0) { continue; } if (strcmp(cp->lval, CFR_CONTROLBODY[RUNAGENT_CONTROL_HOSTS].lval) == 0) { if (HOSTLIST == NULL) // Don't override if command line setting { HOSTLIST = value; } continue; } } } const char *expire_after = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (expire_after) { LASTSEENEXPIREAFTER = IntFromString(expire_after) * 60; } } static void SendClassData(AgentConnection *conn) { Rlist *classes, *rp; char sendbuffer[CF_BUFSIZE]; classes = RlistFromSplitRegex(SENDCLASSES, "[,: ]", 99, false); for (rp = classes; rp != NULL; rp = rp->next) { if (SendTransaction(conn->conn_info, RlistScalarValue(rp), 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Transaction failed. (send: %s)", GetErrorStr()); return; } } snprintf(sendbuffer, CF_MAXVARSIZE, "%s", CFD_TERMINATOR); if (SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Transaction failed. (send: %s)", GetErrorStr()); return; } } /********************************************************************/ static void HailExec(AgentConnection *conn, char *peer, char *recvbuffer, char *sendbuffer) { FILE *fp = stdout; char *sp; int n_read; if (strlen(DEFINECLASSES)) { snprintf(sendbuffer, CF_BUFSIZE, "EXEC %s -D%s", REMOTE_AGENT_OPTIONS, DEFINECLASSES); } else { snprintf(sendbuffer, CF_BUFSIZE, "EXEC %s", REMOTE_AGENT_OPTIONS); } if (SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Transmission rejected. (send: %s)", GetErrorStr()); DisconnectServer(conn); return; } fp = NewStream(peer); SendClassData(conn); while (true) { memset(recvbuffer, 0, CF_BUFSIZE); if ((n_read = ReceiveTransaction(conn->conn_info, recvbuffer, NULL)) == -1) { return; } if (n_read == 0) { break; } if (strlen(recvbuffer) == 0) { continue; } if ((sp = strstr(recvbuffer, CFD_TERMINATOR)) != NULL) { break; } if ((sp = strstr(recvbuffer, "BAD:")) != NULL) { fprintf(fp, "%s> !! %s\n", VPREFIX, recvbuffer + 4); continue; } if (strstr(recvbuffer, "too soon")) { fprintf(fp, "%s> !! %s\n", VPREFIX, recvbuffer); continue; } fprintf(fp, "%s> -> %s", VPREFIX, recvbuffer); } if (fp != stdout) { fclose(fp); } DisconnectServer(conn); } /********************************************************************/ /* Level */ /********************************************************************/ static FILE *NewStream(char *name) { FILE *fp; char filename[CF_BUFSIZE]; if (OUTPUT_DIRECTORY[0] != '\0') { snprintf(filename, CF_BUFSIZE, "%s/%s_runagent.out", OUTPUT_DIRECTORY, name); } else { snprintf(filename, CF_BUFSIZE, "%s/outputs/%s_runagent.out", CFWORKDIR, name); } if (OUTPUT_TO_FILE) { printf("Opening file...%s\n", filename); if ((fp = fopen(filename, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Unable to open file '%s'", filename); fp = stdout; } } else { fp = stdout; } return fp; } cfengine-3.6.2/cf-runagent/Makefile.in0000664000175100017510000005656112412324463017312 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-runagent$(EXEEXT) subdir = cf-runagent DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcf_runagent_la_DEPENDENCIES = ../libpromises/libpromises.la am_libcf_runagent_la_OBJECTS = cf-runagent.lo libcf_runagent_la_OBJECTS = $(am_libcf_runagent_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_cf_runagent_OBJECTS = cf_runagent_OBJECTS = $(am_cf_runagent_OBJECTS) @BUILTIN_EXTENSIONS_FALSE@cf_runagent_DEPENDENCIES = \ @BUILTIN_EXTENSIONS_FALSE@ libcf-runagent.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_runagent_la_SOURCES) $(cf_runagent_SOURCES) DIST_SOURCES = $(libcf_runagent_la_SOURCES) $(cf_runagent_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-runagent.la AM_CPPFLAGS = -I$(srcdir)/../libpromises -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = @CFLAGS@ \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_runagent_la_LIBADD = ../libpromises/libpromises.la libcf_runagent_la_SOURCES = cf-runagent.c @BUILTIN_EXTENSIONS_FALSE@cf_runagent_LDADD = libcf-runagent.la @BUILTIN_EXTENSIONS_FALSE@cf_runagent_SOURCES = CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-runagent/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-runagent/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-runagent.la: $(libcf_runagent_la_OBJECTS) $(libcf_runagent_la_DEPENDENCIES) $(EXTRA_libcf_runagent_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_runagent_la_OBJECTS) $(libcf_runagent_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-runagent$(EXEEXT): $(cf_runagent_OBJECTS) $(cf_runagent_DEPENDENCIES) $(EXTRA_cf_runagent_DEPENDENCIES) @rm -f cf-runagent$(EXEEXT) $(AM_V_CCLD)$(LINK) $(cf_runagent_OBJECTS) $(cf_runagent_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-runagent.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/cf-runagent/Makefile.am0000664000175100017510000000110512411001073017245 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-runagent.la AM_CPPFLAGS = -I$(srcdir)/../libpromises -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = @CFLAGS@ \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_runagent_la_LIBADD = ../libpromises/libpromises.la libcf_runagent_la_SOURCES = cf-runagent.c if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-runagent cf_runagent_LDADD = libcf-runagent.la cf_runagent_SOURCES = endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/LICENSE0000664000175100017510000012625012236160673014037 0ustar00a10038a1003800000000000000This file contains a copy of: 1) The GNU General Public License version 3 1) The Commericial Open Source License (COSL) ---------------------------------------------------------------------------- CFEngine is provided under the terms of the GNU General Public License version 3 (below), with explicit permission to link with the OpenSSL library, BerkeleyDB library and and PCRE library. On some systems, code under the Frontier Artistic License (/libcompat/snprintf) might become compiled. This is compatible with the GPL. Users of the software may, at their option, choose the COSL license below as part of the enterprise CFEngine product. ---------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ------------------------------------------------------------------------------ COMMERCIAL OPEN SOURCE LICENSE This CFEngine commercial open source license ("COSL") is entered into between Cfengine AS, a Norwegian company, as licensor and a) the Customer entity stipulated on a complete agreement front page (“Front page”), b) any entity or natural person downloading, installing or taking the Software or any part of it into use, or c) any entity or person who otherwise has agreed to be bound by these terms (collectively the "Licensee"). 1 LICENSE 1.1 General The Software is licensed on a consecutive basis (rental) or perpetually, as stipulated on the Front page. See 1.2 and 1.3 below respectively. The following shall apply to either type of license grants. Subject to the terms of this COSL and other agreement between the parties, Cfengine hereby grants to Licensee a non-exclusive, non-transferable, non-sublicensable and limited license to install, use, study and modify the number of copies of the Software on the number of Instances stipulated on the Front page for use within its organization. The number of Instances the Software may be installed on may be changed by the Customer from time to time, provided ample notice is given to Cfengine. See Front page for reporting. The Licensee may modify, adapt and create derivative works based upon the Software, for use within its organisation and for sharing between other consecutive licensees under the COSL. Therefore, the Licensee shall have access to the source code of the Software. However, the Licensee shall not reproduce, distribute, resell, rent, lease or disclose the Software in any manner or form to any other third party not holding a COSL to the Software. Licensee may not transfer any of its rights under this COSL without the prior and express written consent of Cfengine. Any CFEngine software component used by both the CFEngine enterprise version and CFEngine community edition is licensed under the terms of this COSL if the Licensee does not state in writing to Cfengine that the Licensee instead wish to license the component in question under the GNU General Public License (GPL) v.3.0 or other applicable license. Third party software is licensed under the license of such third party. 1.2 Consecutive license grant (subscription) If the license grant is agreed to be consecutive (see stipulation on Front page), it shall be effective for the period the consecutive license fee (subscription fee) is paid and this license is otherwise complied to. The payment of the consecutive license fee entitles the Customer to Updates and New versions of the Software (as stipulated in appendix 1). 1.3 Perpetual license grant If the license grant is agreed to be perpetual (see stipulation on Front page), the grant is for ever, provided the license terms are complied to. The perpetual license grant is limited to current the version of the Software at the Effective date. Updates or New versions of the Software are not included, unless stated on the Front page (subject to additional fee). 2 DEFINITIONS The following definitions shall apply to the COSL: “Instances” means each physical or virtual computer (server or client), onto which an installation of the Software takes place. “New version” (of the Software) means a new edition of the Software containing functionality or properties not present in the previous edition of the Software. "Software" means: a) the CFEngine Enterprise data centre administration software downloaded by the Licensee or otherwise given access to including bundled documentation and other material, as described at http://www.cfengine.com/; and b) new versions and updates to such software provided by Cfengine, and “Update” (of Software) means smaller adjustments of the Software with the existing functionality, normally by way of installation of new copy of the Software. 3 FEES The Licensee shall pay a license fee per Instance the Software is installed on for the license granted herein; either: a) per time unit (as agreed) e.g. year, for consecutive license grants, or b) once, for perpetual license grants, for the number of Instances stated on the Front page, or any later adjustments. See the Front page for further details. 4 INTELLECTUAL PROPERTY RIGHTS Cfengine and its suppliers do not by this COSL transfer any copyrights or other intellectual property rights relating to the Software to the Licensee. Such rights are protected by intellectual property legislation in the United States, Europe and other jurisdictions and by international treaty provisions. Cfengine and its suppliers retain all rights in the Software that are not expressly granted to the Licensee through this COSL. Licensee is not allowed to remove, alter or destroy any proprietary, trademark or copyright markings or notices placed upon or contained within the Software. 5 TERMINATION Cfengine may terminate the COSL if the Licensee fails to comply with the terms of this COSL, hereunder fails to pay the stipulated fees. In the event of such termination, the Licensee shall immediately stop using the Software, return any received media and documentation, and destroy or permanently delete any installed versions of the Software, and confirm such destruction or deletion in writing within 7 days. 6 IDEMNINFICATION If the Software (except for third party software) during the term of the license grant is held by a court of competent jurisdiction to infringe any third party intellectual property rights and the Licensee incurs loss or expense as a result of such holding, then Licenee's sole remedy shall be, and Cfengine will, at its option: (i) obtain the right for Licensse to continue to use the Software consistent with the COSL; (ii) modify the Software so that it becomes non-infringing; (iii) replace the infringing component with a non-infringing component, or (iv) refund monies paid by Licensee under the Agreement during the prior six (6) months to the court holding (for consecutive license grants) or a forth of any perpetual license fee paid, and all Licensees rights and licenses under this Agreement shall automatically terminate. The Licensee is aware that the Software is also comprised of third party software, mostly open source software. Such third party software are subject to its individual license terms, and any claims shall be directed at the ultimate right holder to that software. Consequently Cfengine is not liable for any defective title in such third party software. See schedule 5 for a list of software contained by the Software with related licenses. 7 NO WARRANTY To the maximum extent permitted by law, Cfengine disclaims any warranty for the Software (except as stated in clause 6). The Software, any services and any related documentation is provided on an "as is" basis without warranty of any kind, whether express or implied, including, but not limited to, implied warranties of merchantability, fitness for a particular purpose or non-infringement (except as stated in clause 6). Hereunder the parties acknowledges that Cfengine does not warrant for the performance of any data centre on which the Software runs, or the absence of any errors in the Software, and that any such errors does not constitute a contractual defect. 8 LIABILITY The liability of the parties in contract, tort (including negligence) or otherwise shall for all incidents during the entire term of the COSL be limited to a fifth of the fees paid for a perpetual license or the annual consecutive license fees paid for the Software causing the damage or loss, up to a maximum of NOK 100 000. Cfengine or its suppliers shall not be liable for any special, incidental, indirect or consequential damages whatsoever (including, without limitation, damages for loss of business profits, lost savings, business interruption, loss of business information, personal injury, loss of privacy, loss of goodwill or any other financial loss) arising out of the use of or inability to use the Software, even if advised of the possibility of such damages. 9 THIRD-PARTY TERMS For third-party software that is made available to the Licensee by Cfengine, the current terms of the relevant third party software supplier shall apply. cfengine-3.6.2/ylwrap0000755000175100017510000001531212403654566014275 0ustar00a10038a1003800000000000000#! /bin/sh # ylwrap - wrapper for lex/yacc invocations. scriptversion=2013-01-12.17; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . get_dirname () { case $1 in */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';; # Otherwise, we want the empty string (not "."). esac } # guard FILE # ---------- # The CPP macro used to guard inclusion of FILE. guard () { printf '%s\n' "$1" \ | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \ -e 's/__*/_/g' } # quote_for_sed [STRING] # ---------------------- # Return STRING (or stdin) quoted to be used as a sed pattern. quote_for_sed () { case $# in 0) cat;; 1) printf '%s\n' "$1";; esac \ | sed -e 's|[][\\.*]|\\&|g' } case "$1" in '') echo "$0: No files given. Try '$0 --help' for more information." 1>&2 exit 1 ;; --basedir) basedir=$2 shift 2 ;; -h|--h*) cat <<\EOF Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... Wrapper for lex/yacc invocations, renaming files as desired. INPUT is the input file OUTPUT is one file PROG generates DESIRED is the file we actually want instead of OUTPUT PROGRAM is program to run ARGS are passed to PROG Any number of OUTPUT,DESIRED pairs may be used. Report bugs to . EOF exit $? ;; -v|--v*) echo "ylwrap $scriptversion" exit $? ;; esac # The input. input=$1 shift # We'll later need for a correct munging of "#line" directives. input_sub_rx=`get_dirname "$input" | quote_for_sed` case $input in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input=`pwd`/$input ;; esac input_rx=`get_dirname "$input" | quote_for_sed` # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot=false if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot=true fi # The parser itself, the first file, is the destination of the .y.c # rule in the Makefile. parser=$1 # A sed program to s/FROM/TO/g for all the FROM/TO so that, for # instance, we rename #include "y.tab.h" into #include "parse.h" # during the conversion from y.tab.c to parse.c. sed_fix_filenames= # Also rename header guards, as Bison 2.7 for instance uses its header # guard in its implementation file. sed_fix_header_guards= while test $# -ne 0; do if test x"$1" = x"--"; then shift break fi from=$1 # Handle y_tab.c and y_tab.h output by DOS if $y_tab_nodot; then case $from in "y.tab.c") from=y_tab.c;; "y.tab.h") from=y_tab.h;; esac fi shift to=$1 shift sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;" sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;" done # The program to run. prog=$1 shift # Make any relative path in $prog absolute. case $prog in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog=`pwd`/$prog ;; esac dirname=ylwrap$$ do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 mkdir $dirname || exit 1 cd $dirname case $# in 0) "$prog" "$input" ;; *) "$prog" "$@" "$input" ;; esac ret=$? if test $ret -eq 0; then for from in * do to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"` if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend '../'. case $to in [\\/]* | ?:[\\/]*) target=$to;; *) target=../$to;; esac # Do not overwrite unchanged header files to avoid useless # recompilations. Always update the parser itself: it is the # destination of the .y.c rule in the Makefile. Divert the # output of all other files to a temporary file so we can # compare them to existing versions. if test $from != $parser; then realtarget=$target target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'` fi # Munge "#line" or "#" directives. Don't let the resulting # debug information point at an absolute srcdir. Use the real # output file name, not yy.lex.c for instance. Adjust the # include guards too. sed -e "/^#/!b" \ -e "s|$input_rx|$input_sub_rx|" \ -e "$sed_fix_filenames" \ -e "$sed_fix_header_guards" \ "$from" >"$target" || ret=$? # Check whether files must be updated. if test "$from" != "$parser"; then if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then echo "$to is unchanged" rm -f "$target" else echo "updating $to" mv -f "$target" "$realtarget" fi fi else # A missing file is only an error for the parser. This is a # blatant hack to let us support using "yacc -d". If -d is not # specified, don't fail when the header file is "missing". if test "$from" = "$parser"; then ret=1 fi fi done fi # Remove the directory. cd .. rm -rf $dirname exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: cfengine-3.6.2/AUTHORS0000644000175100017510000001444312316547775014113 0ustar00a10038a1003800000000000000Authors list ============ The following lists were obtained from `git shortlog`. In case of any errors and omissions please fix them and submit a pull request. In order to fix an e-mail or a name, please adjust .mailmap file in top level directory. Authors (people with more than 10 commits registered), sorted alphabetically: Kristian Amlie Nick Anderson Dimitrios Apostolou Mark Burgess Mikhail Gusarov Volker Hilsheimer Maciej Mrowiec Geir Nygård Maciej Patucha Loic Pefferkorn Bryce Petrini Nakarin Phooripoom Bishwa Shrestha Eystein Måløy Stenberg Sigurd Teigen Shauna Thomas Carlos Manuel Duclos Vergara Bas van der Vlies Diego Zamboni Ted Zlatanov Contributors (people with less than 10 commits registered), sorted alphabetically: Trond Hasle Amundsen Cédric Cabessa Matthieu CERDA P. Christeas Jonathan CLARKE Jeramey Crawford Remi Debay dolanor Brian Bennett Franz Bettag Gonéri Le Bouder Bernard Brandl Melinda Fancsal George Gensure hicham Klaus Kämpf Daniel V. Klein jkrabbe Kuba David Lee Matt Lesko Riccardo Murri William Orr Michael V. Pelletier Russ Poyner Frerich Raabe Laurent Raufaste Jean Remond Andrew Stribblehill James Thompson Neil H Watson yac Copyright ========= The cfengine 3 design and code is by Cfengine AS and all rights are reserved. In order to offer commericial support of cfengine to customers it is important for Cfengine AS to have an uncomplicated ownership of rights to cfengine 3 code in future products. For that reason we will require that substantial code contrbutions (contributions of sufficient size to warrant copyright) be accompanied by a signed transfer of rights form to cfengine AS. Such a transfer will not take away any of your freedoms under the GNU public licence, but will guarantee that community contributions can be included in cfengine's commerical future, without the need to split cfengine into multiple versions i.e. this allows cfengine AS to make money on commerical versions of cfengine thus supporting future in-house development. ======================================================================== Cfengine AS Contributor statement The terms stated below apply to your contribution of computer code and other material to software or projects owned or managed by Cfengine AS (“project”), and set out the intellectual property rights in the contributed material you transfer to Cfengine. If this contribution is on behalf of a company, “you” will also mean the company you identify below. 1. "Material" and "contribution" shall mean any source code, object code, patch, tool, sample, graphic, specification, manual, documentation, or any other code or other material posted or submitted by you to the project or us. 2. Regarding any worldwide copyrights, or copyright applications and registrations, in your contribution: * You hereby assign to us joint ownership, and to the extent that such assignment is or becomes invalid, ineffective or unenforceable, you hereby grant to us a perpetual, irrevocable, non-exclusive, worldwide, no-charge, royalty-free, unrestricted license to exercise all rights under those copyrights. This includes, at our option, the right to sublicense these same rights to third parties through multiple levels of sublicensees or other licensing arrangements; * You agree that each of us can do all things in relation to your contribution as if each of us were the sole right holder, and if one of us makes a derivative work of your contribution, the one who makes the derivative work (or has it made) will be the sole owner of that derivative work, hereunder make, have made, use, sell, offer to sell, import, and otherwise transfer your contribution in whole or in part; * You agree that neither of us has any duty to consult with, obtain the consent of, pay or render an accounting to the other for any use or distribution of the material. 3. If you own or may license any patent without payment to any third party, you hereby grant us a perpetual, irrevocable, non-exclusive, worldwide, no-charge, royalty-free license to use, transfer and otherwise control such material, to the same extent as described above for copyright. 4. You keep all right, title, and interest in your contribution, exempted only as stated above. The rights that you grant to us under these terms are effective on the date you first submitted a contribution to us, even if your submission took place before the date you sign these terms. Any contribution we make available under any license will also be made available under a suitable FSF (Free Software Foundation) or OSI (Open Source Initiative) approved license. 5. With respect to your contribution, you represent that: * it is an original work and that you can legally grant the rights set out in these terms; * it does not to the best of your knowledge violate any third party's copyrights, trademarks, patents, or other intellectual property rights; and * you are authorized to sign this contract on behalf of your company (if identified below). 6. These terms will be governed by the laws of Norway. Legal venue is Oslo, Norway. If available, please list your cfengine.com username(s) and the name of the project(s) (or project website(s)) for which you would like to contribute materials. Your username: Project name (or project website) and nature of contribution: ______________ _____________________________________________________________ ______________ _____________________________________________________________ ______________ _____________________________________________________________ Your contact information (Please print clearly): Your name: _____________________________________________________________________ Your company's name (if relevant): _____________________________________________ Physical mail address: _________________________________________________________ Phone, fax and email address: __________________________________________________ ________________________________________________________________________________ Signature: _____________________________________________________________________ Date: __________________________________________________________________________ To send these terms to us, scan and email the signed agreement as PDF to contact@cfengine.com cfengine-3.6.2/config.sub0000755000175100017510000010535412403654565015021 0ustar00a10038a1003800000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-08-10' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfengine-3.6.2/cf-promises/0000775000175100017510000000000012413020723015237 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-promises/cf-promises.c0000664000175100017510000004106012411001073017626 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include static GenericAgentConfig *CheckOpts(int argc, char **argv); static void ShowContextsFormatted(EvalContext *ctx); static void ShowVariablesFormatted(EvalContext *ctx); /*******************************************************************/ /* Command line options */ /*******************************************************************/ static const char *const CF_PROMISES_SHORT_DESCRIPTION = "validate and analyze CFEngine policy code"; static const char *const CF_PROMISES_MANPAGE_LONG_DESCRIPTION = "cf-promises is a tool for checking CFEngine policy code. " "It operates by first parsing policy code checing for syntax errors. Second, it validates the integrity of " "policy consisting of multiple files. Third, it checks for semantic errors, e.g. specific attribute set rules. " "Finally, cf-promises attempts to expose errors by partially evaluating the policy, resolving as many variable and " "classes promise statements as possible. At no point does cf-promises make any changes to the system."; typedef enum { PROMISES_OPTION_EVAL_FUNCTIONS, PROMISES_OPTION_SHOW_CLASSES, PROMISES_OPTION_SHOW_VARIABLES } PromisesOptions; static const struct option OPTIONS[] = { [PROMISES_OPTION_EVAL_FUNCTIONS] = {"eval-functions", optional_argument, 0, 0 }, [PROMISES_OPTION_SHOW_CLASSES] = {"show-classes", no_argument, 0, 0 }, [PROMISES_OPTION_SHOW_VARIABLES] = {"show-vars", no_argument, 0, 0 }, {"help", no_argument, 0, 'h'}, {"bundlesequence", required_argument, 0, 'b'}, {"debug", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"dry-run", no_argument, 0, 'n'}, {"version", no_argument, 0, 'V'}, {"file", required_argument, 0, 'f'}, {"define", required_argument, 0, 'D'}, {"negate", required_argument, 0, 'N'}, {"inform", no_argument, 0, 'I'}, {"diagnostic", no_argument, 0, 'x'}, {"reports", no_argument, 0, 'r'}, {"policy-output-format", required_argument, 0, 'p'}, {"syntax-description", required_argument, 0, 's'}, {"full-check", no_argument, 0, 'c'}, {"warn", optional_argument, 0, 'W'}, {"legacy-output", no_argument, 0, 'l'}, {"color", optional_argument, 0, 'C'}, {"tag-release", required_argument, 0, 'T'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { [PROMISES_OPTION_EVAL_FUNCTIONS] = "Evaluate functions during syntax checking (may catch more run-time errors). Possible values: 'yes', 'no'. Default is 'yes'", [PROMISES_OPTION_SHOW_CLASSES] = "Show discovered classes, including those defined in common bundles in policy", [PROMISES_OPTION_SHOW_VARIABLES] = "Show discovered variables, including those defined without dependency to user-defined classes in policy", "Print the help message", "Use the specified bundlesequence for verification", "Enable debugging output", "Output verbose information about the behaviour of the agent", "All talk and no action mode - make no changes, only inform of promises not kept", "Output the version of the software", "Specify an alternative input file than the default", "Define a list of comma separated classes to be defined at the start of execution", "Define a list of comma separated classes to be undefined at the start of execution", "Print basic information about changes made to the system, i.e. promises repaired", "Activate internal diagnostics (developers only)", "Generate reports about configuration and insert into CFDB", "Output the parsed policy. Possible values: 'none', 'cf', 'json'. Default is 'none'. (experimental)", "Output a document describing the available syntax elements of CFEngine. Possible values: 'none', 'json'. Default is 'none'.", "Ensure full policy integrity checks", "Pass comma-separated |all to enable non-default warnings, or error=|all", "Use legacy output format", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", "Tag a directory with promises.cf with cf_promises_validated and cf_promises_release_id", NULL }; /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main(int argc, char *argv[]) { GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); Policy *policy = LoadPolicy(ctx, config); if (!policy) { Log(LOG_LEVEL_ERR, "Input files contain errors."); exit(EXIT_FAILURE); } if (NULL != config->tag_release_dir) { // write the validated file and the release ID bool tagged = GenericAgentTagReleaseDirectory(config, config->tag_release_dir, true, true); if (tagged) { Log(LOG_LEVEL_VERBOSE, "Release tagging done!"); } else { Log(LOG_LEVEL_ERR, "The given directory could not be tagged, sorry."); exit(EXIT_FAILURE); } } if (SHOWREPORTS) { ShowPromises(policy->bundles, policy->bodies); } switch (config->agent_specific.common.policy_output_format) { case GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF: { Policy *output_policy = ParserParseFile(AGENT_TYPE_COMMON, config->input_file, config->agent_specific.common.parser_warnings, config->agent_specific.common.parser_warnings_error); Writer *writer = FileWriter(stdout); PolicyToString(policy, writer); WriterClose(writer); PolicyDestroy(output_policy); } break; case GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON: { Policy *output_policy = ParserParseFile(AGENT_TYPE_COMMON, config->input_file, config->agent_specific.common.parser_warnings, config->agent_specific.common.parser_warnings_error); JsonElement *json_policy = PolicyToJson(output_policy); Writer *writer = FileWriter(stdout); JsonWrite(writer, json_policy, 2); WriterClose(writer); JsonDestroy(json_policy); PolicyDestroy(output_policy); } break; case GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE: break; } if(config->agent_specific.common.show_classes) { ShowContextsFormatted(ctx); } if(config->agent_specific.common.show_variables) { ShowVariablesFormatted(ctx); } PolicyDestroy(policy); GenericAgentFinalize(ctx, config); } /*******************************************************************/ /* Level 1 */ /*******************************************************************/ GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_COMMON); config->tag_release_dir = NULL; while ((c = getopt_long(argc, argv, "dvnIf:D:N:VSrxMb:i:p:s:cg:hW:lC::T:", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 0: switch (optindex) { case PROMISES_OPTION_EVAL_FUNCTIONS: if (!optarg) { optarg = "yes"; } config->agent_specific.common.eval_functions = strcmp("yes", optarg) == 0; break; case PROMISES_OPTION_SHOW_CLASSES: if (!optarg) { optarg = "yes"; } config->agent_specific.common.show_classes = strcmp("yes", optarg) == 0; break; case PROMISES_OPTION_SHOW_VARIABLES: if (!optarg) { optarg = "yes"; } config->agent_specific.common.show_variables = strcmp("yes", optarg) == 0; break; default: break; } case 'l': LEGACY_OUTPUT = true; break; case 'c': config->check_runnable = true; break; case 'f': GenericAgentConfigSetInputFile(config, GetInputDir(), optarg); MINUSF = true; break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case 'b': if (optarg) { Rlist *bundlesequence = RlistFromSplitString(optarg, ','); GenericAgentConfigSetBundleSequence(config, bundlesequence); RlistDestroy(bundlesequence); } break; case 'p': if (strcmp("none", optarg) == 0) { config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE; } else if (strcmp("cf", optarg) == 0) { config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF; } else if (strcmp("json", optarg) == 0) { config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON; } else { Log(LOG_LEVEL_ERR, "Invalid policy output format: '%s'. Possible values are 'none', 'cf', 'json'", optarg); exit(EXIT_FAILURE); } break; case 's': if (strcmp("none", optarg) == 0) { break; } else if (strcmp("json", optarg) == 0) { JsonElement *json_syntax = SyntaxToJson(); Writer *out = FileWriter(stdout); JsonWrite(out, json_syntax, 0); FileWriterDetach(out); JsonDestroy(json_syntax); exit(EXIT_SUCCESS); } else { Log(LOG_LEVEL_ERR, "Invalid syntax description output format: '%s'. Possible values are 'none', 'json'", optarg); exit(EXIT_FAILURE); } break; case 'K': config->ignore_locks = true; break; case 'D': config->heap_soft = StringSetFromString(optarg, ','); break; case 'N': config->heap_negated = StringSetFromString(optarg, ','); break; case 'I': LogSetGlobalLevel(LOG_LEVEL_INFO); break; case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); break; case 'n': DONTDO = true; config->ignore_locks = true; break; case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-promises", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-promises", time(NULL), CF_PROMISES_SHORT_DESCRIPTION, CF_PROMISES_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, true); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'r': SHOWREPORTS = true; break; case 'W': if (!GenericAgentConfigParseWarningOptions(config, optarg)) { Log(LOG_LEVEL_ERR, "Error parsing warning option"); exit(EXIT_FAILURE); } break; case 'x': Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired."); exit(EXIT_SUCCESS); case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; case 'T': GenericAgentConfigSetInputFile(config, optarg, "promises.cf"); MINUSF = true; config->tag_release_dir = xstrdup(optarg); break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-promises", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_FAILURE); } } if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind)) { Log(LOG_LEVEL_ERR, "Too many arguments"); exit(EXIT_FAILURE); } return config; } static void ShowContextsFormatted(EvalContext *ctx) { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; Seq *seq = SeqNew(1000, free); while ((cls = ClassTableIteratorNext(iter))) { char *class_name = ClassRefToString(cls->ns, cls->name); StringSet *tagset = EvalContextClassTags(ctx, cls->ns, cls->name); Buffer *tagbuf = StringSetToBuffer(tagset, ','); char *line; xasprintf(&line, "%-60s %-40s", class_name, BufferData(tagbuf)); SeqAppend(seq, line); BufferDestroy(tagbuf); free(class_name); } SeqSort(seq, (SeqItemComparator)strcmp, NULL); printf("%-60s %-40s\n", "Class name", "Meta tags"); for (size_t i = 0; i < SeqLength(seq); i++) { const char *context = SeqAt(seq, i); printf("%s\n", context); } SeqDestroy(seq); ClassTableIteratorDestroy(iter); } static void ShowVariablesFormatted(EvalContext *ctx) { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, NULL, NULL, NULL); Variable *v = NULL; Seq *seq = SeqNew(2000, free); while ((v = VariableTableIteratorNext(iter))) { char *varname = VarRefToString(v->ref, true); Writer *w = StringWriter(); RvalWrite(w, v->rval); StringSet *tagset = EvalContextVariableTags(ctx, v->ref); Buffer *tagbuf = StringSetToBuffer(tagset, ','); char *line; const char *var_value; if(StringIsPrintable(StringWriterData(w))) { var_value = StringWriterData(w); } else { var_value = ""; } xasprintf(&line, "%-40s %-60s %-40s", varname, var_value, BufferData(tagbuf)); SeqAppend(seq, line); BufferDestroy(tagbuf); WriterClose(w); free(varname); } SeqSort(seq, (SeqItemComparator)strcmp, NULL); printf("%-40s %-60s %-40s\n", "Variable name", "Variable value", "Meta tags"); for (size_t i = 0; i < SeqLength(seq); i++) { const char *variable = SeqAt(seq, i); printf("%s\n", variable); } SeqDestroy(seq); VariableTableIteratorDestroy(iter); } cfengine-3.6.2/cf-promises/Makefile.in0000664000175100017510000005660512412324463017327 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-promises$(EXEEXT) subdir = cf-promises DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcf_promises_la_DEPENDENCIES = ../libpromises/libpromises.la am_libcf_promises_la_OBJECTS = cf-promises.lo libcf_promises_la_OBJECTS = $(am_libcf_promises_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_cf_promises_OBJECTS = cf_promises_OBJECTS = $(am_cf_promises_OBJECTS) @BUILTIN_EXTENSIONS_FALSE@cf_promises_DEPENDENCIES = \ @BUILTIN_EXTENSIONS_FALSE@ libcf-promises.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_promises_la_SOURCES) $(cf_promises_SOURCES) DIST_SOURCES = $(libcf_promises_la_SOURCES) $(cf_promises_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-promises.la AM_CPPFLAGS = @CPPFLAGS@ -I$(srcdir)/../libpromises -I$(srcdir)/../libutils -I$(srcdir)/../libcfnet \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = @CFLAGS@ -I$(srcdir) \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_promises_la_LIBADD = ../libpromises/libpromises.la libcf_promises_la_SOURCES = cf-promises.c @BUILTIN_EXTENSIONS_FALSE@cf_promises_LDADD = libcf-promises.la @BUILTIN_EXTENSIONS_FALSE@cf_promises_SOURCES = CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-promises/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-promises/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-promises.la: $(libcf_promises_la_OBJECTS) $(libcf_promises_la_DEPENDENCIES) $(EXTRA_libcf_promises_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_promises_la_OBJECTS) $(libcf_promises_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-promises$(EXEEXT): $(cf_promises_OBJECTS) $(cf_promises_DEPENDENCIES) $(EXTRA_cf_promises_DEPENDENCIES) @rm -f cf-promises$(EXEEXT) $(AM_V_CCLD)$(LINK) $(cf_promises_OBJECTS) $(cf_promises_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-promises.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/cf-promises/Makefile.am0000664000175100017510000000113112411001073017262 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-promises.la AM_CPPFLAGS = @CPPFLAGS@ -I$(srcdir)/../libpromises -I$(srcdir)/../libutils -I$(srcdir)/../libcfnet \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = @CFLAGS@ -I$(srcdir) \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_promises_la_LIBADD = ../libpromises/libpromises.la libcf_promises_la_SOURCES = cf-promises.c if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-promises cf_promises_LDADD = libcf-promises.la cf_promises_SOURCES = endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/missing0000755000175100017510000001533012403654565014427 0ustar00a10038a1003800000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: cfengine-3.6.2/configure_flags.env.in0000644000175100017510000000132412316547775017311 0ustar00a10038a1003800000000000000CORE_CPPFLAGS="@CORE_CPPFLAGS@" CORE_CFLAGS="@CORE_CFLAGS@" CORE_LDFLAGS="@CORE_LDFLAGS@" CORE_LIBS="@CORE_LIBS@" AGENT_CPPFLAGS="@LIBVIRT_CPPFLAGS@ @POSTGRESQL_CPPFLAGS@ @MYSQL_CPPFLAGS@ @LIBXML2_CPPFLAGS@ @PAM_CPPFLAGS@" AGENT_CFLAGS="@LIBVIRT_CFLAGS@ @POSTGRESQL_CFLAGS@ @MYSQL_CFLAGS@ @LIBXML2_CFLAGS@ @PAM_CFLAGS@" AGENT_LDFLAGS="@LIBVIRT_LDFLAGS@ @POSTGRESQL_LDFLAGS@ @MYSQL_LDFLAGS@ @LIBXML2_LDFLAGS@ @PAM_LDFLAGS@" AGENT_LDADD="@LIBVIRT_LIBS@ @POSTGRESQL_LIBS@ @MYSQL_LIBS@ @LIBXML2_LIBS@ @PAM_LIBS@" hw_cv_func_mkdir_proper="@hw_cv_func_mkdir_proper@" hw_cv_func_stat_proper="@hw_cv_func_stat_proper@" hw_cv_func_rename_proper="@hw_cv_func_rename_proper@" enable_builtin_extensions="@enable_builtin_extensions@" cfengine-3.6.2/libpromises/0000775000175100017510000000000012413020722015337 5ustar00a10038a1003800000000000000cfengine-3.6.2/libpromises/mutex.h0000644000175100017510000000315412352022221016651 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MUTEX_H #define CFENGINE_MUTEX_H #include extern pthread_mutex_t *cft_lock; extern pthread_mutex_t *cft_count; extern pthread_mutex_t *cft_getaddr; extern pthread_mutex_t *cft_server_children; extern pthread_mutex_t *cft_server_filter; #define ThreadLock(m) __ThreadLock(m, __func__, __FILE__, __LINE__) #define ThreadUnlock(m) __ThreadUnlock(m, __func__, __FILE__, __LINE__) int __ThreadLock(pthread_mutex_t *name, const char *funcname, const char *filename, int lineno); int __ThreadUnlock(pthread_mutex_t *name, const char *funcname, const char *filename, int lineno); #endif cfengine-3.6.2/libpromises/audit.c0000664000175100017510000000536412411001073016615 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include int PR_KEPT = 0; /* GLOBAL_X */ int PR_REPAIRED = 0; /* GLOBAL_X */ int PR_NOTKEPT = 0; /* GLOBAL_X */ static bool END_AUDIT_REQUIRED = false; /* GLOBAL_X */ void BeginAudit() { END_AUDIT_REQUIRED = true; } void UpdatePromiseCounters(PromiseResult status) { switch (status) { case PROMISE_RESULT_CHANGE: PR_REPAIRED++; break; case PROMISE_RESULT_NOOP: PR_KEPT++; break; case PROMISE_RESULT_WARN: case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_DENIED: case PROMISE_RESULT_INTERRUPTED: PR_NOTKEPT++; break; default: ProgrammingError("Unexpected status '%c' has been passed to UpdatePromiseCounters", status); } } void EndAudit(const EvalContext *ctx, int background_tasks) { if (!END_AUDIT_REQUIRED) { return; } double total = (double) (PR_KEPT + PR_NOTKEPT + PR_REPAIRED) / 100.0; const char *version = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_VERSION); if (!version) { version = "(not specified)"; } if (total == 0) { Log(LOG_LEVEL_VERBOSE, "Outcome of version '%s', no checks were scheduled", version); return; } else { LogTotalCompliance(version, background_tasks); } } void FatalError(const EvalContext *ctx, char *s, ...) { if (s) { va_list ap; char buf[CF_BUFSIZE] = ""; va_start(ap, s); vsnprintf(buf, CF_BUFSIZE - 1, s, ap); va_end(ap); Log(LOG_LEVEL_ERR, "Fatal CFEngine error: %s", buf); } EndAudit(ctx, 0); #ifdef NDEBUG exit(EXIT_FAILURE); #else abort(); #endif } cfengine-3.6.2/libpromises/ornaments.c0000664000175100017510000001132312411001073017505 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include void PromiseBanner(const Promise *pp) { if (!LEGACY_OUTPUT) { if (pp->comment) { Log(LOG_LEVEL_VERBOSE, "Comment '%s'", pp->comment); } return; } char handle[CF_MAXVARSIZE]; const char *sp; if ((sp = PromiseGetHandle(pp)) || (sp = PromiseID(pp))) { strlcpy(handle, sp, CF_MAXVARSIZE); } else { strcpy(handle, "(enterprise only)"); } Log(LOG_LEVEL_VERBOSE, " ........................................................."); Log(LOG_LEVEL_VERBOSE, " Promise's handle: '%s'", handle); Log(LOG_LEVEL_VERBOSE, " Promise made by: '%s'", pp->promiser); if (pp->comment) { Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, " Comment: %s", pp->comment); } Log(LOG_LEVEL_VERBOSE, " ........................................................."); Log(LOG_LEVEL_VERBOSE, "\n"); } void BannerSubBundle(const Bundle *bp, const Rlist *params) { if (!LEGACY_OUTPUT) { return; } Log(LOG_LEVEL_VERBOSE, " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"); Log(LOG_LEVEL_VERBOSE, " BUNDLE %s", bp->name); if (params) { Writer *w = StringWriter(); RlistWrite(w, params); Log(LOG_LEVEL_VERBOSE, "(%s)", StringWriterData(w)); WriterClose(w); } Log(LOG_LEVEL_VERBOSE, " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"); } void Banner(const char *s) { if (!LEGACY_OUTPUT) { return; } Log(LOG_LEVEL_VERBOSE, "***********************************************************"); Log(LOG_LEVEL_VERBOSE, " %s ", s); Log(LOG_LEVEL_VERBOSE, "***********************************************************"); } void BannerPromiseType(const char *bundlename, const char *type, int pass) { if (!LEGACY_OUTPUT) { return; } Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, " ========================================================="); Log(LOG_LEVEL_VERBOSE, " %s in bundle %s (%d)", type, bundlename, pass); Log(LOG_LEVEL_VERBOSE, " ========================================================="); Log(LOG_LEVEL_VERBOSE, "\n"); } void BannerSubPromiseType(const EvalContext *ctx, const char *bundlename, const char *type) { if (!LEGACY_OUTPUT) { return; } if (strcmp(type, "processes") == 0) { { Log(LOG_LEVEL_VERBOSE, " ??? Local class context: "); ClassTableIterator *iter = EvalContextClassTableIteratorNewLocal(ctx); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { Log(LOG_LEVEL_VERBOSE, " %s", cls->name); } ClassTableIteratorDestroy(iter); Log(LOG_LEVEL_VERBOSE, "\n"); } } Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, " = = = = = = = = = = = = = = = = = = = = = = = = = = = = "); Log(LOG_LEVEL_VERBOSE, " %s in bundle %s", type, bundlename); Log(LOG_LEVEL_VERBOSE, " = = = = = = = = = = = = = = = = = = = = = = = = = = = = "); Log(LOG_LEVEL_VERBOSE, "\n"); } void BannerBundle(const Bundle *bp, const Rlist *params) { if (!LEGACY_OUTPUT) { return; } Log(LOG_LEVEL_VERBOSE, "*****************************************************************"); Log(LOG_LEVEL_VERBOSE, "BUNDLE %s", bp->name); if (params) { Writer *w = StringWriter(); RlistWrite(w, params); Log(LOG_LEVEL_VERBOSE, "(%s)", StringWriterData(w)); WriterClose(w); } Log(LOG_LEVEL_VERBOSE, "*****************************************************************"); } cfengine-3.6.2/libpromises/modes.c0000664000175100017510000002024312400110676016617 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include /***************************************************************/ enum modestate { wild, who, which }; enum modesort { unknown, numeric, symbolic }; /*******************************************************************/ static int CheckModeState(enum modestate stateA, enum modestate stateB, enum modesort modeA, enum modesort modeB, char ch); static int SetModeMask(char action, int value, int affected, mode_t *p, mode_t *m); /***************************************************************/ int ParseModeString(const char *modestring, mode_t *plusmask, mode_t *minusmask) { int affected = 0, value = 0, gotaction, no_error = true; char action = '='; enum modestate state = wild; enum modesort found_sort = unknown; /* Already found "sort" of mode */ enum modesort sort = unknown; /* Sort of started but not yet finished mode */ *plusmask = *minusmask = 0; if (modestring == NULL) { return true; } gotaction = false; for (const char *sp = modestring; true; sp++) { switch (*sp) { case 'a': no_error = CheckModeState(who, state, symbolic, sort, *sp); affected |= 07777; sort = symbolic; break; case 'u': no_error = CheckModeState(who, state, symbolic, sort, *sp); affected |= 04700; sort = symbolic; break; case 'g': no_error = CheckModeState(who, state, symbolic, sort, *sp); affected |= 02070; sort = symbolic; break; case 'o': no_error = CheckModeState(who, state, symbolic, sort, *sp); affected |= 00007; sort = symbolic; break; case '+': case '-': case '=': if (gotaction) { Log(LOG_LEVEL_ERR, "Too many +-= in mode string"); return false; } no_error = CheckModeState(who, state, symbolic, sort, *sp); action = *sp; state = which; gotaction = true; sort = unknown; break; case 'r': no_error = CheckModeState(which, state, symbolic, sort, *sp); value |= 0444 & affected; sort = symbolic; break; case 'w': no_error = CheckModeState(which, state, symbolic, sort, *sp); value |= 0222 & affected; sort = symbolic; break; case 'x': no_error = CheckModeState(which, state, symbolic, sort, *sp); value |= 0111 & affected; sort = symbolic; break; case 's': no_error = CheckModeState(which, state, symbolic, sort, *sp); value |= 06000 & affected; sort = symbolic; break; case 't': no_error = CheckModeState(which, state, symbolic, sort, *sp); value |= 01000; sort = symbolic; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': no_error = CheckModeState(which, state, numeric, sort, *sp); sort = numeric; gotaction = true; state = which; affected = 07777; /* TODO: Hard-coded; see below */ sscanf(sp, "%o", &value); if (value & S_IFMT) { Log(LOG_LEVEL_INFO, "Mode-Value is not entirely within the system's allowed permissions (octal %o) and will be filtered accordingly : %s", S_IFMT, modestring); } /* stat() returns the file types in the mode, but they * can't be set. So we clear the file-type as per POSIX * 2001 instead of erroring out, leaving just the * permissions. */ value &= ~S_IFMT; if (value > 07777) /* TODO: Hardcoded ! Is this correct for all sorts of Unix ? What about NT ? Any (POSIX)-constants ?? */ { Log(LOG_LEVEL_ERR, "Mode-Value too big : %s", modestring); return false; } while ((isdigit((int) *sp)) && (*sp != '\0')) { sp++; } sp--; break; case ',': if (!SetModeMask(action, value, affected, plusmask, minusmask)) { return false; } if ((found_sort != unknown) && (found_sort != sort)) { Log(LOG_LEVEL_INFO, "Symbolic and numeric form for modes mixed"); } found_sort = sort; sort = unknown; action = '='; affected = 0; value = 0; gotaction = false; state = who; break; case '\0': if ((state == who) || (value == 0)) { if ((strcmp(modestring, "0000") != 0) && (strcmp(modestring, "000") != 0)) { Log(LOG_LEVEL_ERR, "mode string is incomplete"); return false; } } if (!SetModeMask(action, value, affected, plusmask, minusmask)) { return false; } if ((found_sort != unknown) && (found_sort != sort)) { Log(LOG_LEVEL_INFO, "Symbolic and numeric form for modes mixed"); } Log(LOG_LEVEL_DEBUG, "Modestring [PLUS = %jo] [MINUS = %jo]", (uintmax_t) *plusmask, (uintmax_t) *minusmask); return true; default: Log(LOG_LEVEL_ERR, "Invalid mode string (%s)", modestring); return false; } } if (!no_error) { Log(LOG_LEVEL_ERR, "Error validating mode string %s", modestring); } return no_error; } /*********************************************************/ static int CheckModeState(enum modestate stateA, enum modestate stateB, enum modesort sortA, enum modesort sortB, char ch) { if ((stateA != wild) && (stateB != wild) && (stateA != stateB)) { Log(LOG_LEVEL_ERR, "Mode string constant (%c) used out of context", ch); return false; } if ((sortA != unknown) && (sortB != unknown) && (sortA != sortB)) { Log(LOG_LEVEL_ERR, "Symbolic and numeric filemodes mixed within expression"); return false; } return true; } /*********************************************************/ static int SetModeMask(char action, int value, int affected, mode_t *p, mode_t *m) { switch (action) { case '+': *p |= value; *m |= 0; return true; case '-': *p |= 0; *m |= value; return true; case '=': *p |= value; *m |= ((~value) & 07777 & affected); return true; default: Log(LOG_LEVEL_ERR, "Mode directive %c is unknown", action); return false; } } cfengine-3.6.2/libpromises/files_names.h0000664000175100017510000000466512400110676020014 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_NAMES_H #define CFENGINE_FILES_NAMES_H #include typedef enum { FILE_PATH_TYPE_ABSOLUTE, // /foo.cf FILE_PATH_TYPE_RELATIVE, // ./../foo.cf FILE_PATH_TYPE_NON_ANCHORED, // foo.cf } FilePathType; FilePathType FilePathGetType(const char *file_path); int IsNewerFileTree(const char *dir, time_t reftime); int CompareCSVName(const char *s1, const char *s2); int IsDir(const char *path); char *JoinPath(char *path, const char *leaf); char *JoinSuffix(char *path, const char *leaf); int IsAbsPath(const char *path); void AddSlash(char *str); char *GetParentDirectoryCopy(const char *path); void DeleteSlash(char *str); void DeleteRedundantSlashes(char *str); const char *FirstFileSeparator(const char *str); const char *LastFileSeparator(const char *str); bool ChopLastNode(char *str); char *CanonifyName(const char *str); void CanonifyNameInPlace(char *str); void TransformNameInPlace(char *s, char from, char to); char *CanonifyChar(const char *str, char ch); const char *ReadLastNode(const char *str); int CompressPath(char *dest, const char *src); bool IsFileOutsideDefaultRepository(const char *f); int RootDirLength(const char *f); const char *GetSoftwareCacheFilename(char *buffer); const char *GetSoftwarePatchesFilename(char *buffer); /** * Detect whether package manager starts with an env command instead of package manager, * and if so, return the real package manager. */ const char *RealPackageManager(const char *manager); #endif cfengine-3.6.2/libpromises/mod_report.c0000664000175100017510000000576412243421446017702 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax printfile_constraints[] = { ConstraintSyntaxNewString("file_to_print", CF_ABSPATHRANGE, "Path name to the file that is to be sent to standard output", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("number_of_lines", CF_VALRANGE, "Integer maximum number of lines to print from selected file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax printfile_body = BodySyntaxNew("printfile", printfile_constraints, NULL, SYNTAX_STATUS_NORMAL); const const ConstraintSyntax CF_REPORT_BODIES[] = { ConstraintSyntaxNewString("friend_pattern", "", "Regular expression to keep selected hosts from the friends report list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewReal("intermittency", "0,1", "Real number threshold [0,1] of intermittency about current peers, report above. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("lastseen", CF_VALRANGE, "Integer time threshold in hours since current peers were last seen, report absence", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("printfile", &printfile_body, "Quote part of a file to standard output", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("report_to_file", CF_ABSPATHRANGE, "The path and filename to which output should be appended", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("bundle_return_value_index", CF_IDRANGE, "The promiser is to be interpreted as a literal value that the caller can accept as a result for this bundle, i.e. a return value with array index defined by this attribute.", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("showstate", "", "List of services about which status reports should be reported to standard output", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_REPORT_PROMISE_TYPES[] = { /* Body lists belonging to "reports:" type in Agent */ PromiseTypeSyntaxNew("agent", "reports", CF_REPORT_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/attributes.h0000664000175100017510000001177512411001073017705 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ATTRIBUTES_H #define CFENGINE_ATTRIBUTES_H #include Attributes GetClassContextAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetColumnAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetDatabaseAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetDeletionAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetEnvironmentsAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetExecAttributes(const EvalContext *ctx, const Promise *pp); void ClearFilesAttributes(Attributes *whom); /* Every return from GetFilesAttributes() must be passed to * ClearFilesAttributes() when you're done with it. */ Attributes GetFilesAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetInferencesAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetInsertionAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetMeasurementAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetMethodAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetOccurrenceAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetPackageAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetUserAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetProcessAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetReplaceAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetReportsAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetServicesAttributes(const EvalContext *ctx, const Promise *pp); Attributes GetStorageAttributes(const EvalContext *ctx, const Promise *pp); Acl GetAclConstraints(const EvalContext *ctx, const Promise *pp); ContextConstraint GetContextConstraints(const EvalContext *ctx, const Promise *pp); Database GetDatabaseConstraints(const EvalContext *ctx, const Promise *pp); DefineClasses GetClassDefinitionConstraints(const EvalContext *ctx, const Promise *pp); EditColumn GetColumnConstraints(const EvalContext *ctx, const Promise *pp); EditDefaults GetEditDefaults(const EvalContext *ctx, const Promise *pp); EditLocation GetLocationAttributes(const Promise *pp); EditXml GetXmlConstraints(const Promise *pp); EditRegion GetRegionConstraints(const EvalContext *ctx, const Promise *pp); EditReplace GetReplaceConstraints(const Promise *pp); Environments GetEnvironmentsConstraints(const EvalContext *ctx, const Promise *pp); ExecContain GetExecContainConstraints(const EvalContext *ctx, const Promise *pp); ENTERPRISE_FUNC_0ARG_DECLARE(HashMethod, GetBestFileChangeHashMethod); FileChange GetChangeMgtConstraints(const EvalContext *ctx, const Promise *pp); FileCopy GetCopyConstraints(const EvalContext *ctx, const Promise *pp); FileDelete GetDeleteConstraints(const EvalContext *ctx, const Promise *pp); FileLink GetLinkConstraints(const EvalContext *ctx, const Promise *pp); FileRename GetRenameConstraints(const EvalContext *ctx, const Promise *pp); FileSelect GetSelectConstraints(const EvalContext *ctx, const Promise *pp); LineSelect GetDeleteSelectConstraints(const EvalContext *ctx, const Promise *pp); LineSelect GetInsertSelectConstraints(const EvalContext *ctx, const Promise *pp); Measurement GetMeasurementConstraint(const EvalContext *ctx, const Promise *pp); Packages GetPackageConstraints(const EvalContext *ctx, const Promise *pp); User GetUserConstraints(const EvalContext *ctx, const Promise *pp); ProcessCount GetMatchesConstraints(const EvalContext *ctx, const Promise *pp); ProcessSelect GetProcessFilterConstraints(const EvalContext *ctx, const Promise *pp); DirectoryRecursion GetRecursionConstraints(const EvalContext *ctx, const Promise *pp); Report GetReportConstraints(const EvalContext *ctx, const Promise *pp); Services GetServicesConstraints(const EvalContext *ctx, const Promise *pp); StorageMount GetMountConstraints(const EvalContext *ctx, const Promise *pp); StorageVolume GetVolumeConstraints(const EvalContext *ctx, const Promise *pp); TransactionContext GetTransactionConstraints(const EvalContext *ctx, const Promise *pp); #endif cfengine-3.6.2/libpromises/parser_state.h0000644000175100017510000000463412316547775020241 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PARSER_STATE_H #define CFENGINE_PARSER_STATE_H #include #include #include #define CF_MAX_NESTING 10 typedef struct { AgentType agent_type; char *block; // body/bundle char blocktype[CF_MAXVARSIZE]; char blockid[CF_MAXVARSIZE]; char filename[CF_MAXVARSIZE]; char *current_line; int line_pos; int line_no; int error_count; int warning_count; int warnings; // bitfield of warnings not considered to be an error int warnings_error; // bitfield of warnings considered to be an error int arg_nesting; int list_nesting; char lval[CF_MAXVARSIZE]; Rval rval; bool references_body; char *promiser; void *promisee; char *current_namespace; char currentid[CF_MAXVARSIZE]; char currenttype[CF_MAXVARSIZE]; char *currentstring; char *currentclasses; Policy *policy; Bundle *currentbundle; Body *currentbody; Promise *currentpromise; PromiseType *currentstype; Rlist *useargs; Rlist *currentRlist; char *currentfnid[CF_MAX_NESTING]; Rlist *giveargs[CF_MAX_NESTING]; FnCall *currentfncall[CF_MAX_NESTING]; struct OffsetState { size_t current; size_t last_id; size_t last_string; size_t last_block_id; size_t last_promise_type_id; size_t last_class_id; } offsets; } ParserState; extern ParserState P; #endif cfengine-3.6.2/libpromises/cf3lex.c0000664000175100017510000020720512405556127016713 0ustar00a10038a1003800000000000000 #line 3 "cf3lex.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 20 #define YY_END_OF_BUFFER 21 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_acclist[152] = { 0, 21, 19, 20, 17, 19, 20, 2, 20, 19, 20, 19, 20, 19, 20, 18, 19, 20, 19, 20, 19, 20, 13, 19, 20, 14, 19, 20, 19, 20, 5, 19, 20, 19, 20, 5, 19, 20, 19, 20, 5, 19, 20, 15, 19, 20, 16, 19, 20, 19, 20, 17, 19, 20, 1, 2, 20, 19, 20, 19, 20, 19, 20, 18, 19, 20, 19, 20, 19, 20, 13, 19, 20, 14, 19, 20, 19, 20, 5, 19, 20, 19, 20, 5, 19, 20, 19, 20, 5, 19, 20, 15, 19, 20, 16, 19, 20, 17, 2, 11, 18, 8, 5, 7, 10, 5, 5, 5, 1, 17, 1, 2, 1, 11, 18, 1, 8, 5, 7, 10, 5, 1, 5, 5, 9, 6, 5, 5, 9, 6, 5, 5, 12, 4, 5, 5, 12, 4, 5, 5, 12, 12, 5, 12, 12, 5, 3, 5, 3, 5, 12, 12 } ; static yyconst flex_int16_t yy_accept[143] = { 0, 1, 1, 1, 2, 4, 7, 9, 11, 13, 15, 18, 20, 22, 25, 28, 30, 33, 35, 38, 40, 43, 46, 49, 51, 54, 57, 59, 61, 63, 66, 68, 70, 73, 76, 78, 81, 83, 86, 88, 91, 94, 97, 98, 99, 99, 99, 99, 100, 100, 101, 101, 101, 101, 101, 102, 103, 103, 104, 105, 106, 106, 107, 108, 108, 109, 110, 112, 112, 112, 112, 113, 114, 114, 115, 115, 115, 115, 116, 116, 117, 118, 118, 119, 120, 121, 121, 122, 123, 124, 125, 125, 125, 125, 125, 126, 127, 128, 129, 129, 129, 129, 129, 130, 131, 132, 133, 133, 133, 135, 136, 137, 137, 137, 139, 140, 140, 141, 141, 141, 141, 142, 143, 143, 144, 144, 144, 144, 145, 146, 146, 146, 146, 146, 148, 148, 148, 148, 148, 150, 151, 152, 152 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 7, 8, 1, 5, 9, 10, 11, 1, 1, 1, 12, 13, 1, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 1, 1, 16, 17, 1, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 21, 22, 1, 19, 23, 19, 24, 19, 25, 26, 19, 19, 19, 19, 19, 19, 27, 19, 28, 29, 19, 19, 19, 19, 19, 30, 19, 19, 19, 31, 19, 32, 5, 33, 1, 1, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 } ; static yyconst flex_int32_t yy_meta[34] = { 0, 1, 1, 2, 1, 3, 1, 1, 4, 1, 5, 6, 1, 7, 7, 7, 1, 1, 1, 7, 8, 1, 9, 1, 7, 7, 7, 7, 7, 7, 7, 7, 4, 10 } ; static yyconst flex_int16_t yy_base[163] = { 0, 0, 33, 323, 720, 319, 720, 317, 304, 61, 0, 58, 60, 300, 290, 287, 86, 286, 97, 279, 108, 720, 720, 297, 68, 720, 296, 137, 71, 295, 73, 77, 0, 0, 70, 155, 72, 172, 81, 49, 284, 282, 280, 720, 266, 265, 79, 720, 0, 0, 73, 94, 85, 0, 720, 199, 210, 720, 221, 232, 245, 241, 235, 259, 720, 122, 720, 0, 246, 123, 82, 254, 253, 252, 245, 264, 150, 122, 251, 250, 0, 282, 249, 0, 0, 152, 228, 225, 221, 229, 138, 230, 95, 207, 224, 207, 210, 218, 134, 303, 156, 322, 215, 198, 203, 720, 348, 374, 0, 200, 216, 407, 440, 0, 190, 194, 186, 466, 172, 492, 171, 164, 515, 0, 156, 534, 151, 0, 146, 98, 119, 124, 155, 0, 202, 184, 189, 185, 0, 720, 69, 720, 565, 572, 582, 592, 600, 605, 612, 622, 632, 642, 652, 662, 666, 669, 676, 678, 681, 688, 695, 702, 709 } ; static yyconst flex_int16_t yy_def[163] = { 0, 141, 141, 141, 141, 141, 141, 141, 142, 143, 144, 141, 145, 142, 142, 141, 146, 141, 147, 148, 141, 141, 141, 149, 149, 141, 149, 149, 150, 151, 149, 152, 27, 27, 149, 27, 149, 35, 153, 37, 149, 149, 141, 141, 142, 142, 143, 141, 143, 144, 154, 155, 145, 145, 141, 146, 156, 141, 156, 147, 148, 59, 59, 149, 141, 149, 141, 27, 27, 150, 143, 149, 150, 151, 149, 74, 152, 145, 152, 149, 35, 35, 149, 81, 37, 153, 148, 37, 37, 142, 154, 157, 155, 158, 58, 59, 59, 27, 74, 74, 75, 75, 81, 37, 37, 141, 159, 160, 59, 59, 149, 141, 141, 37, 37, 161, 161, 159, 162, 160, 162, 59, 111, 122, 111, 112, 112, 125, 37, 141, 157, 141, 158, 59, 149, 99, 149, 101, 37, 141, 149, 0, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141 } ; static yyconst flex_int16_t yy_nxt[754] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 8, 16, 8, 17, 4, 11, 18, 4, 4, 4, 19, 20, 18, 18, 18, 18, 18, 18, 18, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 27, 35, 27, 36, 23, 30, 37, 23, 23, 23, 38, 39, 37, 37, 37, 37, 37, 37, 37, 40, 41, 47, 50, 47, 65, 64, 64, 64, 70, 64, 64, 71, 87, 88, 77, 53, 48, 74, 86, 47, 71, 79, 47, 82, 51, 44, 72, 91, 47, 91, 44, 44, 78, 44, 48, 56, 44, 48, 71, 75, 53, 44, 44, 105, 44, 55, 58, 44, 93, 107, 93, 93, 44, 44, 129, 44, 55, 58, 65, 64, 70, 59, 105, 71, 139, 47, 59, 59, 59, 59, 59, 61, 62, 59, 64, 130, 67, 53, 72, 110, 131, 67, 67, 105, 67, 67, 68, 77, 111, 86, 67, 105, 106, 71, 91, 67, 67, 67, 67, 67, 67, 67, 67, 80, 81, 78, 138, 137, 80, 71, 112, 132, 135, 80, 80, 80, 80, 80, 80, 80, 80, 83, 139, 110, 133, 84, 64, 131, 131, 140, 84, 84, 84, 84, 84, 84, 84, 84, 44, 64, 135, 137, 129, 44, 44, 136, 44, 110, 56, 44, 129, 128, 140, 64, 44, 44, 110, 44, 134, 89, 44, 121, 114, 113, 68, 44, 44, 97, 44, 109, 89, 44, 108, 45, 105, 105, 44, 44, 89, 44, 55, 58, 64, 104, 103, 47, 64, 64, 77, 64, 70, 64, 98, 98, 98, 97, 64, 96, 98, 99, 95, 99, 47, 98, 98, 98, 98, 98, 98, 98, 98, 100, 100, 100, 89, 45, 42, 100, 101, 64, 101, 64, 100, 100, 100, 100, 100, 100, 100, 100, 102, 97, 64, 66, 64, 102, 47, 57, 54, 45, 102, 102, 102, 102, 102, 102, 102, 102, 110, 45, 99, 99, 99, 45, 43, 42, 99, 141, 141, 141, 141, 99, 99, 99, 99, 99, 99, 99, 99, 101, 101, 101, 141, 141, 141, 101, 141, 141, 141, 141, 101, 101, 101, 101, 101, 101, 101, 101, 141, 110, 115, 141, 115, 116, 141, 141, 141, 141, 141, 141, 141, 141, 91, 141, 91, 141, 141, 141, 141, 141, 141, 141, 141, 141, 115, 115, 118, 141, 118, 118, 141, 141, 141, 141, 141, 141, 141, 141, 93, 141, 93, 141, 141, 141, 141, 141, 141, 141, 141, 141, 118, 120, 63, 63, 64, 63, 63, 63, 63, 122, 63, 122, 123, 63, 124, 124, 124, 63, 63, 63, 124, 99, 63, 99, 63, 124, 124, 124, 124, 124, 124, 124, 124, 122, 122, 63, 63, 64, 63, 63, 63, 63, 125, 63, 125, 125, 63, 126, 126, 126, 63, 63, 63, 126, 101, 63, 101, 63, 126, 126, 126, 126, 126, 126, 126, 126, 125, 127, 115, 141, 115, 116, 141, 141, 141, 141, 141, 141, 141, 141, 91, 141, 130, 141, 141, 141, 141, 141, 141, 141, 141, 141, 115, 115, 118, 141, 118, 118, 141, 141, 141, 141, 141, 141, 141, 141, 93, 141, 132, 141, 141, 141, 141, 141, 141, 141, 141, 141, 118, 120, 122, 141, 122, 122, 122, 141, 141, 141, 122, 63, 141, 134, 141, 122, 122, 122, 122, 122, 122, 122, 122, 125, 125, 125, 141, 141, 141, 125, 63, 141, 136, 141, 125, 125, 125, 125, 125, 125, 125, 125, 141, 125, 44, 141, 44, 44, 44, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 49, 141, 49, 49, 49, 49, 49, 49, 49, 49, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 55, 141, 55, 55, 55, 59, 141, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 90, 90, 90, 92, 92, 92, 94, 141, 94, 94, 94, 91, 91, 91, 91, 93, 93, 93, 93, 117, 117, 117, 117, 117, 117, 117, 119, 119, 119, 119, 119, 119, 119, 115, 115, 115, 115, 141, 115, 115, 118, 118, 118, 118, 141, 118, 118, 3, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141 } ; static yyconst flex_int16_t yy_chk[754] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 11, 12, 24, 24, 140, 34, 28, 36, 30, 28, 39, 39, 31, 12, 9, 30, 38, 46, 31, 34, 70, 36, 11, 16, 28, 50, 52, 50, 16, 16, 31, 16, 46, 16, 18, 70, 38, 30, 52, 18, 18, 129, 18, 18, 18, 20, 51, 92, 51, 92, 20, 20, 129, 20, 20, 20, 65, 65, 69, 20, 92, 69, 130, 77, 20, 20, 20, 20, 20, 20, 20, 20, 27, 130, 27, 77, 69, 98, 131, 27, 27, 90, 27, 27, 27, 76, 98, 85, 27, 131, 90, 76, 90, 27, 27, 27, 27, 27, 27, 27, 27, 35, 35, 76, 128, 126, 35, 85, 100, 132, 124, 35, 35, 35, 35, 35, 35, 35, 35, 37, 132, 100, 121, 37, 136, 120, 118, 135, 37, 37, 37, 37, 37, 37, 37, 37, 55, 134, 135, 137, 116, 55, 55, 136, 55, 134, 55, 56, 115, 114, 137, 110, 56, 56, 136, 56, 134, 56, 58, 109, 104, 103, 102, 58, 58, 97, 58, 96, 58, 59, 95, 94, 93, 91, 59, 59, 89, 59, 59, 59, 74, 88, 87, 86, 82, 79, 78, 73, 72, 71, 74, 74, 74, 68, 63, 62, 74, 74, 61, 74, 60, 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 45, 44, 42, 75, 75, 41, 75, 40, 75, 75, 75, 75, 75, 75, 75, 75, 81, 81, 29, 26, 23, 81, 19, 17, 15, 14, 81, 81, 81, 81, 81, 81, 81, 81, 99, 13, 99, 99, 99, 8, 7, 5, 99, 3, 0, 0, 0, 99, 99, 99, 99, 99, 99, 99, 99, 101, 101, 101, 0, 0, 0, 101, 0, 0, 0, 0, 101, 101, 101, 101, 101, 101, 101, 101, 0, 101, 106, 0, 106, 106, 0, 0, 0, 0, 0, 0, 0, 0, 106, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 106, 107, 0, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 107, 0, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 117, 0, 117, 117, 0, 0, 0, 0, 0, 0, 0, 0, 117, 0, 117, 0, 0, 0, 0, 0, 0, 0, 0, 0, 117, 117, 119, 0, 119, 119, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119, 119, 122, 0, 122, 122, 122, 0, 0, 0, 122, 122, 0, 122, 0, 122, 122, 122, 122, 122, 122, 122, 122, 125, 125, 125, 0, 0, 0, 125, 125, 0, 125, 0, 125, 125, 125, 125, 125, 125, 125, 125, 0, 125, 142, 0, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 144, 0, 144, 144, 144, 144, 144, 144, 144, 144, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 146, 0, 146, 146, 146, 147, 0, 147, 147, 147, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 154, 154, 154, 155, 155, 155, 156, 0, 156, 156, 156, 157, 157, 157, 157, 158, 158, 158, 158, 159, 159, 159, 159, 159, 159, 159, 160, 160, 160, 160, 160, 160, 160, 161, 161, 161, 161, 0, 161, 161, 162, 162, 162, 162, 0, 162, 162, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141 } ; extern int yy_flex_debug; int yy_flex_debug = 0; static yy_state_type *yy_state_buf=0, *yy_state_ptr=0; static char *yy_full_match; static int yy_lp; #define REJECT \ { \ *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \ yy_cp = (yy_full_match); /* restore poss. backed-over text */ \ ++(yy_lp); \ goto find_rule; \ } #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "cf3lex.l" #line 2 "cf3lex.l" /* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /*******************************************************************/ /* */ /* LEXER for cfengine 3 */ /* */ /*******************************************************************/ #include #include #include #include /* yyinput/input are generated and unused */ #if defined(__GNUC__) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION >= 40200 # pragma GCC diagnostic ignored "-Wunused-function" # endif #endif #undef malloc #undef realloc #define malloc xmalloc #define realloc xrealloc #define ParserDebug if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) printf static int DeEscapeQuotedString(const char *from, char *to); int yywrap(void) { return 1; } static void yyuseraction() { P.offsets.current += yyleng; } #define YY_USER_ACTION yyuseraction(); // Do not use lex - flex only /* * Three types of quoted strings: * * - string in double quotes, starts with double quote, runs until another * double quote, \" masks the double quote. * - string in single quotes, starts with single quote, runs until another * single quote, \' masks the single quote. * - string in backquotes, starts with backquote, runs until another backquote. * * The same rule formatted for the better readability: * * := \" \" | \' \' | ` ` * = * * = \\ | [^"\\] * = * * = \\ | [^'\\] * = * * = [^`] * = . | \n * */ #line 789 "cf3lex.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * in_str ); FILE *yyget_out (void ); void yyset_out (FILE * out_str ); int yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ if ( yyleng > 0 ) \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 130 "cf3lex.l" #line 982 "cf3lex.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif /* Create the reject buffer large enough to save one state per allowed character. */ if ( ! (yy_state_buf) ) (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE ); if ( ! (yy_state_buf) ) YY_FATAL_ERROR( "out of dynamic memory in yylex()" ); if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); (yy_state_ptr) = (yy_state_buf); *(yy_state_ptr)++ = yy_current_state; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 142 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; *(yy_state_ptr)++ = yy_current_state; ++yy_cp; } while ( yy_base[yy_current_state] != 720 ); yy_find_action: yy_current_state = *--(yy_state_ptr); (yy_lp) = yy_accept[yy_current_state]; find_rule: /* we branch to this label when backing up */ for ( ; ; ) /* until we find what rule we matched */ { if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] ) { yy_act = yy_acclist[(yy_lp)]; { (yy_full_match) = yy_cp; break; } } --yy_cp; yy_current_state = *--(yy_state_ptr); (yy_lp) = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 1: *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ (yy_c_buf_p) = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 132 "cf3lex.l" { free(P.current_line); P.current_line = xstrdup(yytext); ParserDebug("L:line %s\n", P.current_line); REJECT; } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 139 "cf3lex.l" { P.line_no++; P.line_pos = 0; } YY_BREAK case 3: YY_RULE_SETUP #line 144 "cf3lex.l" { /* Note this has to come before "id" since it is a subset of id */ if (P.currentclasses != NULL) { free(P.currentclasses); P.currentclasses = NULL; } P.line_pos += yyleng; ParserDebug("\tL:bundle %d\n", P.line_pos); return BUNDLE; } YY_BREAK case 4: YY_RULE_SETUP #line 157 "cf3lex.l" { /* Note this has to come before "id" since it is a subset of id */ if (P.currentclasses != NULL) { free(P.currentclasses); P.currentclasses = NULL; } P.line_pos += yyleng; ParserDebug("\tL:body %d\n", P.line_pos); return BODY; } YY_BREAK case 5: YY_RULE_SETUP #line 170 "cf3lex.l" { P.offsets.last_id = P.offsets.current - yyleng; P.line_pos += yyleng; ParserDebug("\tL:id %s %d\n", yytext, P.line_pos); if (yyleng > CF_MAXVARSIZE-1) { yyerror("identifier too long"); } strncpy(P.currentid, yytext, CF_MAXVARSIZE); return IDSYNTAX; } YY_BREAK case 6: YY_RULE_SETUP #line 183 "cf3lex.l" { P.offsets.last_id = P.offsets.current - yyleng; P.line_pos += yyleng; ParserDebug("\tL:symbol %s %d\n", yytext, P.line_pos); if (yyleng > CF_MAXVARSIZE-1) { yyerror("qualified identifier too long"); } strncpy(P.currentid, yytext, CF_MAXVARSIZE); return IDSYNTAX; } YY_BREAK case 7: YY_RULE_SETUP #line 196 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL:assign %d\n", P.line_pos); return ASSIGN; } YY_BREAK case 8: YY_RULE_SETUP #line 202 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL:arrow %d\n", P.line_pos); return ARROW; } YY_BREAK case 9: YY_RULE_SETUP #line 208 "cf3lex.l" { char *tmp = NULL; P.line_pos += yyleng; ParserDebug("\tL:class %s %d\n", yytext, P.line_pos); tmp = xstrdup(yytext); tmp[yyleng-2] = '\0'; if (P.currentclasses != NULL) { free(P.currentclasses); } P.currentclasses = xstrdup(tmp); free(tmp); return CLASS; } YY_BREAK case 10: YY_RULE_SETUP #line 228 "cf3lex.l" { char *tmp = NULL; P.line_pos += yyleng; ParserDebug("\tL:promise_type %s %d\n", yytext, P.line_pos); P.offsets.last_promise_type_id = P.offsets.current - yyleng; tmp = xstrdup(yytext); tmp[yyleng - 1] = '\0'; strncpy(P.currenttype, tmp, CF_MAXVARSIZE); if (P.currentclasses != NULL) { free(P.currentclasses); P.currentclasses = NULL; } free(tmp); return PROMISE_TYPE; } YY_BREAK case 11: /* rule 11 can match eol */ YY_RULE_SETUP #line 249 "cf3lex.l" { char *tmp = NULL; int less = 0; P.offsets.last_string = P.offsets.current - yyleng; P.line_pos += yyleng; ParserDebug("\tL:qstring %s %d\n", yytext, P.line_pos); for (char *c = yytext; *c; ++c) { if (*c == '\n') { P.line_no++; } } tmp = xmalloc(yyleng + 1); if ((less = DeEscapeQuotedString(yytext,tmp)) > 0) { yyless(less); P.offsets.current -= less; } if (P.currentstring) { free(P.currentstring); } P.currentstring = xstrdup(tmp); free(tmp); return QSTRING; } YY_BREAK case 12: YY_RULE_SETUP #line 285 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); if (P.currentstring) { free(P.currentstring); } P.currentstring = xstrdup(yytext); return NAKEDVAR; } YY_BREAK case 13: YY_RULE_SETUP #line 296 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return OP; } YY_BREAK case 14: YY_RULE_SETUP #line 302 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return CP; } YY_BREAK case 15: YY_RULE_SETUP #line 308 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return OB; } YY_BREAK case 16: YY_RULE_SETUP #line 314 "cf3lex.l" { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return CB; } YY_BREAK case 17: YY_RULE_SETUP #line 321 "cf3lex.l" { P.line_pos += yyleng; } YY_BREAK case 18: YY_RULE_SETUP #line 325 "cf3lex.l" { } YY_BREAK case 19: YY_RULE_SETUP #line 329 "cf3lex.l" { P.line_pos++; return yytext[0]; } YY_BREAK case 20: YY_RULE_SETUP #line 335 "cf3lex.l" ECHO; YY_BREAK #line 1339 "cf3lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); yy_current_state += YY_AT_BOL(); (yy_state_ptr) = (yy_state_buf); *(yy_state_ptr)++ = yy_current_state; for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 142 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; *(yy_state_ptr)++ = yy_current_state; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register YY_CHAR yy_c = 1; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 142 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 141); if ( ! yy_is_jam ) *(yy_state_ptr)++ = yy_current_state; return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param line_number * */ void yyset_lineno (int line_number ) { yylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str ) { yyin = in_str ; } void yyset_out (FILE * out_str ) { yyout = out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int bdebug ) { yy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; (yy_state_buf) = 0; (yy_state_ptr) = 0; (yy_full_match) = 0; (yy_lp) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; yyfree ( (yy_state_buf) ); (yy_state_buf) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 335 "cf3lex.l" static int DeEscapeQuotedString(const char *from, char *to) { char *cp; const char *sp; char start = *from; int len = strlen(from); if (len == 0) { return 0; } for (sp = from + 1, cp = to; (sp - from) < len; sp++, cp++) { if ((*sp == start)) { *(cp) = '\0'; if (*(sp + 1) != '\0') { return (2 + (sp - from)); } return 0; } if (*sp == '\\') { switch (*(sp + 1)) { case '\n': sp += 2; break; case ' ': break; case '\\': case '\"': case '\'': sp++; break; } } *cp = *sp; } yyerror("Runaway string"); *(cp) = '\0'; return 0; } /* EOF */ cfengine-3.6.2/libpromises/files_copy.c0000644000175100017510000001737112316547775017676 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include /* * Copy data jumping over areas filled by '\0', so files automatically become sparse if possible. */ static bool CopyData(const char *source, int sd, const char *destination, int dd, char *buf, size_t buf_size) { off_t n_read_total = 0; while (true) { ssize_t n_read = read(sd, buf, buf_size); if (n_read == -1) { if (errno == EINTR) { continue; } Log(LOG_LEVEL_ERR, "Unable to read source file while copying '%s' to '%s'. (read: %s)", source, destination, GetErrorStr()); return false; } if (n_read == 0) { /* * As the tail of file may contain of bytes '\0' (and hence * lseek(2)ed on destination instead of being written), do a * ftruncate(2) here to ensure the whole file is written to the * disc. */ if (ftruncate(dd, n_read_total) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying '%s' to '%s'. (ftruncate: %s)", source, destination, GetErrorStr()); return false; } return true; } n_read_total += n_read; /* Copy/seek */ void *cur = buf; void *end = buf + n_read; while (cur < end) { void *skip_span = MemSpan(cur, 0, end - cur); if (skip_span > cur) { if (lseek(dd, skip_span - cur, SEEK_CUR) < 0) { Log(LOG_LEVEL_ERR, "Failed while copying '%s' to '%s' (no space?). (lseek: %s)", source, destination, GetErrorStr()); return false; } cur = skip_span; } void *copy_span = MemSpanInverse(cur, 0, end - cur); if (copy_span > cur) { if (FullWrite(dd, cur, copy_span - cur) < 0) { Log(LOG_LEVEL_ERR, "Failed while copying '%s' to '%s' (no space?). (write: %s)", source, destination, GetErrorStr()); return false; } cur = copy_span; } } } } bool CopyRegularFileDisk(const char *source, const char *destination) { int sd; int dd = 0; char *buf = 0; bool result = false; if ((sd = safe_open(source, O_RDONLY | O_BINARY)) == -1) { Log(LOG_LEVEL_INFO, "Can't copy '%s'. (open: %s)", source, GetErrorStr()); goto end; } /* * We need to stat the file in order to get the right source permissions. */ struct stat statbuf; if (stat(source, &statbuf) == -1) { Log(LOG_LEVEL_INFO, "Can't copy '%s'. (stat: %s)", source, GetErrorStr()); goto end; } unlink(destination); /* To avoid link attacks */ if ((dd = safe_open(destination, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, statbuf.st_mode)) == -1) { Log(LOG_LEVEL_INFO, "Unable to open destination file while copying '%s' to '%s'. (open: %s)", source, destination, GetErrorStr()); goto end; } int buf_size = ST_BLKSIZE(dstat); buf = xmalloc(buf_size); result = CopyData(source, sd, destination, dd, buf, buf_size); if (!result) { goto end; } end: if (buf) { free(buf); } if (dd) { close(dd); } if (!result) { unlink(destination); } close(sd); return result; } bool CopyFilePermissionsDisk(const char *source, const char *destination) { struct stat statbuf; if (stat(source, &statbuf) == -1) { Log(LOG_LEVEL_INFO, "Can't copy permissions '%s'. (stat: %s)", source, GetErrorStr()); return false; } if (safe_chmod(destination, statbuf.st_mode) != 0) { Log(LOG_LEVEL_INFO, "Can't copy permissions '%s'. (chmod: %s)", source, GetErrorStr()); return false; } if (safe_chown(destination, statbuf.st_uid, statbuf.st_gid) != 0) { Log(LOG_LEVEL_INFO, "Can't copy permissions '%s'. (chown: %s)", source, GetErrorStr()); return false; } if (!CopyFileExtendedAttributesDisk(source, destination)) { return false; } return true; } #ifdef WITH_XATTR_EXTRA_ARGS #define listxattr(__arg1, __arg2, __arg3) \ listxattr((__arg1), (__arg2), (__arg3), 0) #define getxattr(__arg1, __arg2, __arg3, __arg4) \ getxattr((__arg1), (__arg2), (__arg3), (__arg4), 0, 0) #define setxattr(__arg1, __arg2, __arg3, __arg4, __arg5) \ setxattr((__arg1), (__arg2), (__arg3), (__arg4), 0, (__arg5)) #endif bool CopyFileExtendedAttributesDisk(const char *source, const char *destination) { #if defined(WITH_XATTR) // Extended attributes include both POSIX ACLs and SELinux contexts. ssize_t attr_raw_names_size; char attr_raw_names[CF_BUFSIZE]; attr_raw_names_size = listxattr(source, attr_raw_names, sizeof(attr_raw_names)); if (attr_raw_names_size < 0) { if (errno == ENOTSUP || errno == ENODATA) { return true; } else { Log(LOG_LEVEL_INFO, "Can't copy extended attributes from '%s' to '%s'. (listxattr: %s)", source, destination, GetErrorStr()); return false; } } int pos; for (pos = 0; pos < attr_raw_names_size;) { const char *current = attr_raw_names + pos; pos += strlen(current) + 1; char data[CF_BUFSIZE]; int datasize = getxattr(source, current, data, sizeof(data)); if (datasize < 0) { if (errno == ENOTSUP) { continue; } else { Log(LOG_LEVEL_INFO, "Can't copy extended attributes from '%s' to '%s'. (getxattr: %s: %s)", source, destination, GetErrorStr(), current); return false; } } int ret = setxattr(destination, current, data, datasize, 0); if (ret < 0) { if (errno == ENOTSUP) { continue; } else { Log(LOG_LEVEL_INFO, "Can't copy extended attributes from '%s' to '%s'. (setxattr: %s: %s)", source, destination, GetErrorStr(), current); return false; } } } #else // !WITH_XATTR // ACLs are included in extended attributes, but fall back to CopyACLs if xattr is not available. if (!CopyACLs(source, destination)) { return false; } #endif return true; } cfengine-3.6.2/libpromises/loading.c0000664000175100017510000003703412411001073017123 0ustar00a10038a1003800000000000000#include #include #include #include #include #include #include #include #include #include #include #include // TODO: remove #include #include static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files); /* * The difference between filename and input_input file is that the latter is the file specified by -f or * equivalently the file containing body common control. This will hopefully be squashed in later refactoring. */ static Policy *Cf3ParseFile(const GenericAgentConfig *config, const char *input_path) { struct stat statbuf; if (stat(input_path, &statbuf) == -1) { if (config->ignore_missing_inputs) { return PolicyNew(); } Log(LOG_LEVEL_ERR, "Can't stat file '%s' for parsing. (stat: %s)", input_path, GetErrorStr()); exit(EXIT_FAILURE); } else if (S_ISDIR(statbuf.st_mode)) { if (config->ignore_missing_inputs) { return PolicyNew(); } Log(LOG_LEVEL_ERR, "Can't parse directory '%s'.", input_path); exit(EXIT_FAILURE); } #ifndef _WIN32 if (config->check_not_writable_by_others && (statbuf.st_mode & (S_IWGRP | S_IWOTH))) { Log(LOG_LEVEL_ERR, "File %s (owner %ju) is writable by others (security exception)", input_path, (uintmax_t)statbuf.st_uid); exit(EXIT_FAILURE); } #endif Log(LOG_LEVEL_VERBOSE, "Parsing file '%s'", input_path); if (!FileCanOpen(input_path, "r")) { Log(LOG_LEVEL_ERR, "Can't open file '%s' for parsing", input_path); exit(EXIT_FAILURE); } Policy *policy = NULL; if (StringEndsWith(input_path, ".json")) { Writer *contents = FileRead(input_path, SIZE_MAX, NULL); if (!contents) { Log(LOG_LEVEL_ERR, "Error reading JSON input file '%s'", input_path); return NULL; } JsonElement *json_policy = NULL; const char *data = StringWriterData(contents); if (JsonParse(&data, &json_policy) != JSON_PARSE_OK) { Log(LOG_LEVEL_ERR, "Error parsing JSON input file '%s'", input_path); WriterClose(contents); return NULL; } policy = PolicyFromJson(json_policy); JsonDestroy(json_policy); WriterClose(contents); } else { if (config->agent_type == AGENT_TYPE_COMMON) { policy = ParserParseFile(config->agent_type, input_path, config->agent_specific.common.parser_warnings, config->agent_specific.common.parser_warnings_error); } else { policy = ParserParseFile(config->agent_type, input_path, 0, 0); } } return policy; } static Policy *LoadPolicyInputFiles(EvalContext *ctx, GenericAgentConfig *config, const Rlist *inputs, StringSet *parsed_files_and_checksums, StringSet *failed_files) { Policy *policy = PolicyNew(); for (const Rlist *rp = inputs; rp; rp = rp->next) { if (rp->val.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Non-file object in inputs list"); continue; } const char *unresolved_input = RlistScalarValue(rp); if (strcmp(CF_NULL_VALUE, unresolved_input) == 0) { continue; } if (IsExpandable(unresolved_input)) { PolicyResolve(ctx, policy, config); } Rval resolved_input = EvaluateFinalRval(ctx, policy, NULL, "sys", rp->val, true, NULL); Policy *aux_policy = NULL; switch (resolved_input.type) { case RVAL_TYPE_SCALAR: if (IsCf3VarString(RvalScalarValue(resolved_input))) { Log(LOG_LEVEL_ERR, "Unresolved variable '%s' in input list, cannot parse", RvalScalarValue(resolved_input)); break; } aux_policy = LoadPolicyFile(ctx, config, GenericAgentResolveInputPath(config, RvalScalarValue(resolved_input)), parsed_files_and_checksums, failed_files); break; case RVAL_TYPE_LIST: aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(resolved_input), parsed_files_and_checksums, failed_files); break; default: ProgrammingError("Unknown type in input list for parsing: %d", resolved_input.type); break; } if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } RvalDestroy(resolved_input); } return policy; } // TODO: should be replaced by something not complected with loading static void ShowContext(EvalContext *ctx) { Seq *hard_contexts = SeqNew(1000, NULL); Seq *soft_contexts = SeqNew(1000, NULL); { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { if (cls->is_soft) { SeqAppend(soft_contexts, cls->name); } else { SeqAppend(hard_contexts, cls->name); } } ClassTableIteratorDestroy(iter); } SeqSort(soft_contexts, (SeqItemComparator)strcmp, NULL); SeqSort(hard_contexts, (SeqItemComparator)strcmp, NULL); { Writer *w = NULL; if (LEGACY_OUTPUT) { w = FileWriter(stdout); WriterWriteF(w, "%s> -> Hard classes = {", VPREFIX); } else { w = StringWriter(); WriterWrite(w, "Discovered hard classes:"); } for (size_t i = 0; i < SeqLength(hard_contexts); i++) { const char *context = SeqAt(hard_contexts, i); WriterWriteF(w, " %s", context); } if (LEGACY_OUTPUT) { WriterWrite(w, "}\n"); FileWriterDetach(w); } else { Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w)); WriterClose(w); } } { Writer *w = NULL; if (LEGACY_OUTPUT) { w = FileWriter(stdout); WriterWriteF(w, "%s> -> Additional classes = {", VPREFIX); } else { w = StringWriter(); WriterWrite(w, "Additional classes:"); } for (size_t i = 0; i < SeqLength(soft_contexts); i++) { const char *context = SeqAt(soft_contexts, i); WriterWriteF(w, " %s", context); } if (LEGACY_OUTPUT) { WriterWrite(w, "}\n"); FileWriterDetach(w); } else { if (SeqLength(soft_contexts) > 0) { Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w)); } WriterClose(w); } } SeqDestroy(hard_contexts); SeqDestroy(soft_contexts); } static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files) { unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; char hashbuffer[CF_HOSTKEY_STRING_SIZE] = { 0 }; char hashprintbuffer[CF_BUFSIZE] = { 0 }; HashFile(policy_file, digest, CF_DEFAULT_DIGEST); snprintf(hashprintbuffer, CF_BUFSIZE - 1, "{checksum}%s", HashPrintSafe(hashbuffer, sizeof(hashbuffer), digest, CF_DEFAULT_DIGEST, true)); Log(LOG_LEVEL_DEBUG, "Hashed policy file %s to %s", policy_file, hashprintbuffer); if (StringSetContains(parsed_files_and_checksums, policy_file)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate policy file %s", policy_file); return NULL; } else if (StringSetContains(parsed_files_and_checksums, hashprintbuffer)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate (detected by hash) policy file %s", policy_file); return NULL; } else { Log(LOG_LEVEL_DEBUG, "Loading policy file %s", policy_file); } Policy *policy = Cf3ParseFile(config, policy_file); // we keep the checksum and the policy file name to help debugging StringSetAdd(parsed_files_and_checksums, xstrdup(policy_file)); StringSetAdd(parsed_files_and_checksums, xstrdup(hashprintbuffer)); if (policy) { Seq *errors = SeqNew(10, free); if (!PolicyCheckPartial(policy, errors)) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); SeqDestroy(errors); StringSetAdd(failed_files, xstrdup(policy_file)); PolicyDestroy(policy); return NULL; } SeqDestroy(errors); } else { StringSetAdd(failed_files, xstrdup(policy_file)); return NULL; } PolicyResolve(ctx, policy, config); Body *body_common_control = PolicyGetBody(policy, NULL, "common", "control"); Body *body_file_control = PolicyGetBody(policy, NULL, "file", "control"); if (body_common_control) { Seq *potential_inputs = BodyGetConstraint(body_common_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } if (body_file_control) { Seq *potential_inputs = BodyGetConstraint(body_file_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } return policy; } static bool VerifyBundleSequence(EvalContext *ctx, const Policy *policy, const GenericAgentConfig *config) { const Rlist *bundlesequence = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BUNDLESEQUENCE); if (!bundlesequence) { Log(LOG_LEVEL_ERR, " No bundlesequence in the common control body"); return false; } const char *name; int ok = true; for (const Rlist *rp = bundlesequence; rp != NULL; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: name = RlistScalarValue(rp); break; case RVAL_TYPE_FNCALL: name = RlistFnCallValue(rp)->name; break; default: name = NULL; ok = false; { Writer *w = StringWriter(); WriterWrite(w, "Illegal item found in bundlesequence '"); RvalWrite(w, rp->val); WriterWrite(w, "'"); Log(LOG_LEVEL_ERR, "%s", StringWriterData(w)); WriterClose(w); } continue; } if (strcmp(name, CF_NULL_VALUE) == 0) { continue; } if (!config->ignore_missing_bundles && !PolicyGetBundle(policy, NULL, NULL, name)) { Log(LOG_LEVEL_ERR, "Bundle '%s' listed in the bundlesequence is not a defined bundle", name); ok = false; } } return ok; } /** * @brief Reads the release_id file from inputs and return a JsonElement. */ static JsonElement *ReadReleaseIdFileFromInputs() { char filename[CF_MAXVARSIZE]; GetReleaseIdFile(GetInputDir(), filename, sizeof(filename)); struct stat sb; if (stat(filename, &sb) == -1) { return NULL; } JsonElement *validated_doc = NULL; JsonParseError err = JsonParseFile(filename, 4096, &validated_doc); if (err != JSON_PARSE_OK) { Log(LOG_LEVEL_WARNING, "Could not read release ID: '%s' did not contain valid JSON data. " "(JsonParseFile: '%s')", filename, JsonParseErrorToString(err)); } return validated_doc; } Policy *LoadPolicy(EvalContext *ctx, GenericAgentConfig *config) { StringSet *parsed_files_and_checksums = StringSetNew(); StringSet *failed_files = StringSetNew(); Policy *policy = LoadPolicyFile(ctx, config, config->input_file, parsed_files_and_checksums, failed_files); if (StringSetSize(failed_files) > 0) { Log(LOG_LEVEL_ERR, "There are syntax errors in policy files"); exit(EXIT_FAILURE); } StringSetDestroy(parsed_files_and_checksums); StringSetDestroy(failed_files); { Seq *errors = SeqNew(100, PolicyErrorDestroy); if (PolicyCheckPartial(policy, errors)) { if (!config->bundlesequence && (PolicyIsRunnable(policy) || config->check_runnable)) { Log(LOG_LEVEL_VERBOSE, "Running full policy integrity checks"); PolicyCheckRunnable(ctx, policy, errors, config->ignore_missing_bundles); } } if (SeqLength(errors) > 0) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); exit(EXIT_FAILURE); // TODO: do not exit } SeqDestroy(errors); } if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { ShowContext(ctx); } if (policy) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, CommonEvalPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); } PolicyResolve(ctx, policy, config); // TODO: need to move this inside PolicyCheckRunnable eventually. if (!config->bundlesequence && config->check_runnable) { // only verify policy-defined bundlesequence for cf-agent, cf-promises if ((config->agent_type == AGENT_TYPE_AGENT) || (config->agent_type == AGENT_TYPE_COMMON)) { if (!VerifyBundleSequence(ctx, policy, config)) { FatalError(ctx, "Errors in promise bundles: could not verify bundlesequence"); } } } } JsonElement *validated_doc = ReadReleaseIdFileFromInputs(); if (validated_doc) { const char *release_id = JsonObjectGetAsString(validated_doc, "releaseId"); if (release_id) { policy->release_id = xstrdup(release_id); } JsonDestroy(validated_doc); } return policy; } cfengine-3.6.2/libpromises/policy.h0000664000175100017510000002757112411001073017017 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_POLICY_H #define CFENGINE_POLICY_H #include #include #include #include #include typedef enum { POLICY_ELEMENT_TYPE_POLICY, POLICY_ELEMENT_TYPE_BUNDLE, POLICY_ELEMENT_TYPE_BODY, POLICY_ELEMENT_TYPE_PROMISE_TYPE, POLICY_ELEMENT_TYPE_PROMISE, POLICY_ELEMENT_TYPE_CONSTRAINT } PolicyElementType; typedef struct { PolicyElementType type; const void *subject; char *message; } PolicyError; struct Policy_ { char *release_id; Seq *bundles; Seq *bodies; }; typedef struct { size_t start; size_t end; size_t line; size_t context; } SourceOffset; struct Bundle_ { Policy *parent_policy; char *type; char *name; char *ns; Rlist *args; Seq *promise_types; char *source_path; SourceOffset offset; }; struct Body_ { Policy *parent_policy; char *type; char *name; char *ns; Rlist *args; Seq *conlist; char *source_path; SourceOffset offset; }; struct PromiseType_ { Bundle *parent_bundle; char *name; Seq *promises; SourceOffset offset; }; struct Promise_ { PromiseType *parent_promise_type; char *classes; char *comment; char *promiser; Rval promisee; Seq *conlist; bool has_subbundles; const Promise *org_pp; /* A ptr to the unexpanded raw promise */ SourceOffset offset; }; struct Constraint_ { PolicyElementType type; union { Promise *promise; Body *body; } parent; char *lval; Rval rval; char *classes; bool references_body; SourceOffset offset; }; const char *NamespaceDefault(void); Policy *PolicyNew(void); int PolicyCompare(const void *a, const void *b); void PolicyDestroy(Policy *policy); unsigned PolicyHash(const Policy *policy); StringSet *PolicySourceFiles(const Policy *policy); /** * @brief Merge two partial policy objects. The memory for the child objects of the original policies are transfered to the new parent. * @param a * @param b * @return Merged policy */ Policy *PolicyMerge(Policy *a, Policy *b); /** * @brief Query a policy for a body * @param policy The policy to query * @param ns Namespace filter (optionally NULL) * @param type Body type filter * @param name Body name filter * @return Body child object if found, otherwise NULL */ Body *PolicyGetBody(const Policy *policy, const char *ns, const char *type, const char *name); /** * @brief Query a policy for a bundle * @param policy The policy to query * @param ns Namespace filter (optionally NULL) * @param type Bundle type filter * @param name Bundle name filter * @return Bundle child object if found, otherwise NULL */ Bundle *PolicyGetBundle(const Policy *policy, const char *ns, const char *type, const char *name); /** * @brief Check to see if a policy is runnable (contains body common control) * @param policy Policy to check * @return True if policy is runnable */ bool PolicyIsRunnable(const Policy *policy); /** * @brief Convenience function to get the policy object associated with a promise * @param promise * @return Policy object */ const Policy *PolicyFromPromise(const Promise *promise); char *BundleQualifiedName(const Bundle *bundle); PolicyError *PolicyErrorNew(PolicyElementType type, const void *subject, const char *error_msg, ...); void PolicyErrorDestroy(PolicyError *error); void PolicyErrorWrite(Writer *writer, const PolicyError *error); /** * @brief Check a partial policy DOM for errors * @param policy Policy to check * @param errors Sequence of PolicyError to append errors to * @return True if no new errors are found */ bool PolicyCheckPartial(const Policy *policy, Seq *errors); /** * @brief Check a runnable policy DOM for errors * @param policy Policy to check * @param errors Sequence of PolicyError to append errors to * @param ignore_missing_bundles Whether to ignore missing bundle references * @return True if no new errors are found */ bool PolicyCheckRunnable(const EvalContext *ctx, const Policy *policy, Seq *errors, bool ignore_missing_bundles); Bundle *PolicyAppendBundle(Policy *policy, const char *ns, const char *name, const char *type, const Rlist *args, const char *source_path); Body *PolicyAppendBody(Policy *policy, const char *ns, const char *name, const char *type, Rlist *args, const char *source_path); /** * @brief Serialize a policy as JSON * @param policy The policy to serialize * @return A JsonElement representing the input policy */ JsonElement *PolicyToJson(const Policy *policy); /** * @brief Deserialize a policy from JSON * @param json_policy JSON to deserialize * @return A policy DOM */ Policy *PolicyFromJson(JsonElement *json_policy); /** * @brief Pretty-print a policy * @param policy The policy to print * @param writer Writer to write into */ void PolicyToString(const Policy *policy, Writer *writer); PromiseType *BundleAppendPromiseType(Bundle *bundle, const char *name); const PromiseType *BundleGetPromiseType(const Bundle *bp, const char *name); Constraint *BodyAppendConstraint(Body *body, const char *lval, Rval rval, const char *classes, bool references_body); /** * @brief A sequence of constraints matching the l-value. * @param body Body to query * @param lval l-value to match * @return Sequence of pointers to the constraints. Destroying it does not alter the DOM. */ Seq *BodyGetConstraint(Body *body, const char *lval); bool BodyHasConstraint(const Body *body, const char *lval); const char *ConstraintGetNamespace(const Constraint *cp); Promise *PromiseTypeAppendPromise(PromiseType *type, const char *promiser, Rval promisee, const char *classes); void PromiseTypeDestroy(PromiseType *promise_type); void PromiseDestroy(Promise *pp); Constraint *PromiseAppendConstraint(Promise *promise, const char *lval, Rval rval, bool references_body); const char *PromiseGetNamespace(const Promise *pp); const Bundle *PromiseGetBundle(const Promise *pp); const Policy *PromiseGetPolicy(const Promise *pp); /** * @brief Write a string describing the promise location in policy, e.g. /default/foo/packages/'emacs' */ void PromisePath(Writer *w, const Promise *pp); /** * @brief Return handle of the promise. * @param pp * @return Promise handle or NULL if no handle is provided */ const char *PromiseGetHandle(const Promise *pp); /** * @brief Get the int value of the first effective constraint found matching, from a promise * @param lval * @param pp * @return Int value, or CF_NOINT */ int PromiseGetConstraintAsInt(const EvalContext *ctx, const char *lval, const Promise *pp); /** * @brief Get the real value of the first effective constraint found matching, from a promise * @return true if value could be extracted */ bool PromiseGetConstraintAsReal(const EvalContext *ctx, const char *lval, const Promise *list, double *value_out); /** * @brief Get the octal value of the first effective constraint found matching, from a promise * @param lval * @param list * @return Double value, or 077 if not found */ mode_t PromiseGetConstraintAsOctal(const EvalContext *ctx, const char *lval, const Promise *list); /** * @brief Get the uid value of the first effective constraint found matching, from a promise * @param lval * @param pp * @return Uid value, or CF_SAME_OWNER if not found */ uid_t PromiseGetConstraintAsUid(const EvalContext *ctx, const char *lval, const Promise *pp); /** * @brief Get the uid value of the first effective constraint found matching, from a promise * @param lval * @param pp * @return Gid value, or CF_SAME_GROUP if not found */ gid_t PromiseGetConstraintAsGid(const EvalContext *ctx, char *lval, const Promise *pp); /** * @brief Get the Rlist value of the first effective constraint found matching, from a promise * @param lval * @param list * @return Rlist or NULL if not found (note: same as empty list) */ Rlist *PromiseGetConstraintAsList(const EvalContext *ctx, const char *lval, const Promise *pp); bool PromiseBundleConstraintExists(const EvalContext *ctx, const char *lval, const Promise *pp); void PromiseRecheckAllConstraints(const EvalContext *ctx, const Promise *pp); /** * @brief Get the trinary boolean value of the first effective constraint found matching, from a promise * @param lval * @param list * @return True/false, or CF_UNDEFINED if not found */ int PromiseGetConstraintAsBoolean(const EvalContext *ctx, const char *lval, const Promise *list); /** * @brief Get the first effective constraint from the promise, also does some checking * @param promise * @param lval * @return Effective constraint if found, otherwise NULL */ Constraint *PromiseGetConstraint(const Promise *promise, const char *lval); /** * @brief Get the first constraint from the promise. Checks that constraint does * not have any classes attached to it. * * Kill this function with fire once we have separated promise constraints and body constraints. * * @param promise * @param lval * @return Constraint if found, otherwise NULL */ Constraint *PromiseGetImmediateConstraint(const Promise *promise, const char *lval); void ConstraintDestroy(Constraint *cp); /** * @brief Get the context of the given constraint * @param cp * @return context. never returns NULL. */ const char *ConstraintContext(const Constraint *cp); /** * @brief Returns the first effective constraint from a list of candidates, depending on evaluation state. * @param constraints The list of potential candidates * @return The effective constraint, or NULL if none are found. */ Constraint *EffectiveConstraint(const EvalContext *ctx, Seq *constraints); /** * @brief Get the Rval value of the first effective constraint that matches the given type * @param lval * @param promise * @param type * @return Rval value if found, NULL otherwise */ void *PromiseGetConstraintAsRval(const Promise *promise, const char *lval, RvalType type); /** * @brief Get the Rval value of the first constraint that matches the given * type. Checks that this constraint does not have any contexts attached. * * Kill this function with fire once we have separated body constraints and bundle constraints. * * @param lval * @param promise * @param type * @return Rval value if found, NULL otherwise */ void *PromiseGetImmediateRvalValue(const char *lval, const Promise *pp, RvalType rtype); /** * @brief Get the trinary boolean value of the first effective constraint found matching * @param lval * @param constraints * @return True/false, or CF_UNDEFINED if not found */ int ConstraintsGetAsBoolean(const EvalContext *ctx, const char *lval, const Seq *constraints); /** * @return A copy of the namespace component of a qualified name, or NULL. e.g. "foo:bar" -> "foo" */ char *QualifiedNameNamespaceComponent(const char *qualified_name); /** * @return A copy of the symbol compoent of a qualified name, or NULL. e.g. "foo:bar" -> "bar" */ char *QualifiedNameScopeComponent(const char *qualified_name); /** * @brief Check whether the promise type is allowed one */ bool BundleTypeCheck(const char *name); #endif cfengine-3.6.2/libpromises/string_expressions.h0000664000175100017510000000573212243421446021500 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_STRING_EXPRESSIONS_H #define CFENGINE_STRING_EXPRESSIONS_H /* String expressions grammar: ::= ::= ::= [a-zA-Z0-9_:]+ ::= $( ) ${ } ::= . Subsequent s are concatenated during evaluation. */ typedef enum { CONCAT, LITERAL, VARREF } StringOp; typedef enum { VAR_REF_TYPE_SCALAR, VAR_REF_TYPE_LIST } VarRefType; typedef struct StringExpression_ StringExpression; struct StringExpression_ { StringOp op; union StringExpressionValue { struct { StringExpression *lhs; StringExpression *rhs; } concat; struct { char *literal; } literal; struct { StringExpression *name; VarRefType type; } varref; } val; }; /* Parsing and evaluation */ /* * Result of parsing. * * if succeeded, then result is the result of parsing and position is last * character consumed. * * if not succeded, then result is NULL and position is last character consumed * before the error. */ typedef struct { StringExpression *result; int position; } StringParseResult; StringParseResult ParseStringExpression(const char *expr, int start, int end); /* * Evaluator should return either heap-allocated string or NULL. In later case * evaluation will be aborted and NULL will be returned from * EvalStringExpression. */ typedef char *(*VarRefEvaluator) (const char *varname, VarRefType type, void *param); /* * Result is heap-allocated. In case evalfn() returns NULL whole * EvalStringExpression returns NULL as well. */ char *EvalStringExpression(const StringExpression *expr, VarRefEvaluator evalfn, void *param); /* * Frees StringExpression produced by ParseStringExpression. NULL-safe. */ void FreeStringExpression(StringExpression *expr); #endif cfengine-3.6.2/libpromises/systype.c0000664000175100017510000001533712411001073017230 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include /* Set in libenv/sysinfo.c::DetectEnvironment (called every time environment reload is performed). Utilized all over the place, usually to look up OS-specific command/option to call external utility */ PlatformContext VSYSTEMHARDCLASS; /* GLOBAL_E?, initialized_later */ /* Configure system name and system-specific details. */ const char *const CLASSTEXT[] = { [PLATFORM_CONTEXT_UNKNOWN] = "", [PLATFORM_CONTEXT_OPENVZ] = "virt_host_vz_vzps", [PLATFORM_CONTEXT_HP] = "hpux", [PLATFORM_CONTEXT_AIX] = "aix", [PLATFORM_CONTEXT_LINUX] = "linux", [PLATFORM_CONTEXT_SOLARIS] = "solaris", [PLATFORM_CONTEXT_SUN_SOLARIS] = "solaris", [PLATFORM_CONTEXT_FREEBSD] = "freebsd", [PLATFORM_CONTEXT_NETBSD] = "netbsd", [PLATFORM_CONTEXT_CRAYOS] = "cray", [PLATFORM_CONTEXT_WINDOWS_NT] = "windows", [PLATFORM_CONTEXT_SYSTEMV] = "unix_sv", [PLATFORM_CONTEXT_OPENBSD] = "openbsd", [PLATFORM_CONTEXT_CFSCO] = "sco", [PLATFORM_CONTEXT_DARWIN] = "darwin", [PLATFORM_CONTEXT_QNX] = "qnx", [PLATFORM_CONTEXT_DRAGONFLY] = "dragonfly", [PLATFORM_CONTEXT_MINGW] = "windows", [PLATFORM_CONTEXT_VMWARE] = "vmware", [PLATFORM_CONTEXT_ANDROID] = "android", }; const char *const VPSCOMM[] = { [PLATFORM_CONTEXT_UNKNOWN] = "", [PLATFORM_CONTEXT_OPENVZ] = "/bin/vzps", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/bin/ps", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/bin/ps", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/bin/ps", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/bin/ps", /* solaris >= 11 */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/usr/ucb/ps", /* solaris < 11 */ [PLATFORM_CONTEXT_FREEBSD] = "/bin/ps", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/bin/ps", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/bin/ps", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/bin/ps", /* NT - cygnus */ [PLATFORM_CONTEXT_SYSTEMV] = "/bin/ps", /* unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/bin/ps", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/bin/ps", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/bin/ps", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/bin/ps", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/bin/ps", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "mingw-invalid", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/bin/ps", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "/system/xbin/busybox ps", /* android */ }; // linux after rhel 3: ps -eo user,pid,ppid,pgid,%cpu,%mem,vsize,ni,rss,stat,nlwp,stime,time,args // solaris: ps -eo user,pid,ppid,pgid,pcpu,pmem,vsz,pri,rss,nlwp,stime,time,args const char *const VPSOPTS[] = { [PLATFORM_CONTEXT_UNKNOWN] = "", [PLATFORM_CONTEXT_OPENVZ] = "-E 0 -o user,pid,ppid,pgid,pcpu,pmem,vsz,ni,rss,nlwp,stime,time,args", /* virt_host_vz_vzps (with vzps, the -E 0 replace the -e) */ [PLATFORM_CONTEXT_HP] = "-ef", /* hpux */ [PLATFORM_CONTEXT_AIX] = "-N -eo user,pid,ppid,pgid,pcpu,pmem,vsz,ni,stat,st=STIME,time,args", /* aix */ [PLATFORM_CONTEXT_LINUX] = "-eo user,pid,ppid,pgid,pcpu,pmem,vsz,ni,rss:9,nlwp,stime,etime,time,args",/* linux */ [PLATFORM_CONTEXT_SOLARIS] = "auxww", /* solaris >= 11 */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "auxww", /* solaris < 11 */ [PLATFORM_CONTEXT_FREEBSD] = "auxw", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "-axo user,pid,ppid,pgid,pcpu,pmem,vsz,ni,rss,nlwp,start,time,args", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "-elyf", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "-aW", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "-ef", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "-axo user,pid,ppid,pgid,pcpu,pmem,vsz,ni,rss,start,time,args", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "-ef", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "auxw", /* darwin */ [PLATFORM_CONTEXT_QNX] = "-elyf", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "auxw", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "mingw-invalid", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "?", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "", /* android */ }; const char *const VFSTAB[] = { [PLATFORM_CONTEXT_UNKNOWN] = "-", [PLATFORM_CONTEXT_OPENVZ] = "/etc/fstab", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/etc/fstab", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/etc/filesystems", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/etc/fstab", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/etc/vfstab", /* solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/etc/vfstab", /* solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/etc/fstab", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/etc/fstab", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/etc/fstab", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/etc/fstab", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "/etc/vfstab", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/etc/fstab", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/etc/default/filesys",/* sco */ [PLATFORM_CONTEXT_DARWIN] = "/etc/fstab", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/etc/fstab", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/etc/fstab", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/etc/fstab", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "", /* android */ }; cfengine-3.6.2/libpromises/assoc.c0000664000175100017510000000303012243421446016620 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include CfAssoc *NewAssoc(const char *lval, Rval rval, DataType dt) { CfAssoc *ap; ap = xmalloc(sizeof(CfAssoc)); /* Make a private copy because promises are ephemeral in expansion phase */ ap->lval = xstrdup(lval); ap->rval = RvalCopy(rval); ap->dtype = dt; return ap; } /*******************************************************************/ void DeleteAssoc(CfAssoc *ap) { if (ap == NULL) { return; } free(ap->lval); RvalDestroy(ap->rval); free(ap); } cfengine-3.6.2/libpromises/scope.c0000664000175100017510000002632712411001073016622 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*******************************************************************/ const char *SpecialScopeToString(SpecialScope scope) { switch (scope) { case SPECIAL_SCOPE_CONST: return "const"; case SPECIAL_SCOPE_EDIT: return "edit"; case SPECIAL_SCOPE_MATCH: return "match"; case SPECIAL_SCOPE_MON: return "mon"; case SPECIAL_SCOPE_SYS: return "sys"; case SPECIAL_SCOPE_THIS: return "this"; case SPECIAL_SCOPE_BODY: return "body"; default: ProgrammingError("Unhandled special scope"); } } SpecialScope SpecialScopeFromString(const char *scope) { if (strcmp("const", scope) == 0) { return SPECIAL_SCOPE_CONST; } else if (strcmp("edit", scope) == 0) { return SPECIAL_SCOPE_EDIT; } else if (strcmp("match", scope) == 0) { return SPECIAL_SCOPE_MATCH; } else if (strcmp("mon", scope) == 0) { return SPECIAL_SCOPE_MON; } else if (strcmp("sys", scope) == 0) { return SPECIAL_SCOPE_SYS; } else if (strcmp("this", scope) == 0) { return SPECIAL_SCOPE_THIS; } else if (strcmp("body", scope) == 0) { return SPECIAL_SCOPE_BODY; } else { return SPECIAL_SCOPE_NONE; } } void ScopeAugment(EvalContext *ctx, const Bundle *bp, const Promise *pp, const Rlist *arguments) { if (RlistLen(bp->args) != RlistLen(arguments)) { Log(LOG_LEVEL_ERR, "While constructing scope '%s'", bp->name); fprintf(stderr, "Formal = "); { Writer *w = FileWriter(stderr); RlistWrite(w, bp->args); FileWriterDetach(w); } fprintf(stderr, ", Actual = "); { Writer *w = FileWriter(stderr); RlistWrite(w, arguments); FileWriterDetach(w); } fprintf(stderr, "\n"); FatalError(ctx, "Augment scope, formal and actual parameter mismatch is fatal"); } const Bundle *pbp = NULL; if (pp != NULL) { pbp = PromiseGetBundle(pp); } for (const Rlist *rpl = bp->args, *rpr = arguments; rpl != NULL; rpl = rpl->next, rpr = rpr->next) { const char *lval = RlistScalarValue(rpl); Log(LOG_LEVEL_VERBOSE, "Augment scope '%s' with variable '%s' (type: %c)", bp->name, lval, rpr->val.type); // CheckBundleParameters() already checked that there is no namespace collision // By this stage all functions should have been expanded, so we only have scalars left if (rpr->val.type == RVAL_TYPE_SCALAR && IsNakedVar(RlistScalarValue(rpr), '@')) { char naked[CF_BUFSIZE]; GetNaked(naked, RlistScalarValue(rpr)); DataType value_type = CF_DATA_TYPE_NONE; const void *value = NULL; if (pbp != NULL) { VarRef *ref = VarRefParseFromBundle(naked, pbp); value = EvalContextVariableGet(ctx, ref, &value_type); VarRefDestroy(ref); } else { VarRef *ref = VarRefParseFromBundle(naked, bp); value = EvalContextVariableGet(ctx, ref, &value_type); VarRefDestroy(ref); } switch (value_type) { case CF_DATA_TYPE_STRING_LIST: case CF_DATA_TYPE_INT_LIST: case CF_DATA_TYPE_REAL_LIST: { VarRef *ref = VarRefParseFromBundle(lval, bp); EvalContextVariablePut(ctx, ref, value, CF_DATA_TYPE_STRING_LIST, "source=promise"); VarRefDestroy(ref); } break; case CF_DATA_TYPE_CONTAINER: { VarRef *ref = VarRefParseFromBundle(lval, bp); EvalContextVariablePut(ctx, ref, value, CF_DATA_TYPE_CONTAINER, "source=promise"); VarRefDestroy(ref); } break; default: { Log(LOG_LEVEL_ERR, "List or container parameter '%s' not found while constructing scope '%s' - use @(scope.variable) in calling reference", naked, bp->name); VarRef *ref = VarRefParseFromBundle(lval, bp); EvalContextVariablePut(ctx, ref, RlistScalarValue(rpr), CF_DATA_TYPE_STRING, "source=promise"); VarRefDestroy(ref); } break; } } else { switch(rpr->val.type) { case RVAL_TYPE_SCALAR: { VarRef *ref = VarRefParseFromBundle(lval, bp); EvalContextVariablePut(ctx, ref, RvalScalarValue(rpr->val), CF_DATA_TYPE_STRING, "source=promise"); VarRefDestroy(ref); } break; case RVAL_TYPE_FNCALL: { FnCall *subfp = RlistFnCallValue(rpr); Rval rval = FnCallEvaluate(ctx, PromiseGetPolicy(pp), subfp, pp).rval; if (rval.type == RVAL_TYPE_SCALAR) { VarRef *ref = VarRefParseFromBundle(lval, bp); EvalContextVariablePut(ctx, ref, RvalScalarValue(rval), CF_DATA_TYPE_STRING, "source=promise"); VarRefDestroy(ref); } else { Log(LOG_LEVEL_ERR, "Only functions returning scalars can be used as arguments"); } RvalDestroy(rval); } break; default: ProgrammingError("An argument neither a scalar nor a list seemed to appear. Impossible"); } } } /* Check that there are no danglers left to evaluate in the hash table itself */ return; } void ScopeMapBodyArgs(EvalContext *ctx, const Body *body, const Rlist *args) { const Rlist *arg = NULL; const Rlist *param = NULL; for (arg = args, param = body->args; arg != NULL && param != NULL; arg = arg->next, param = param->next) { DataType arg_type = CF_DATA_TYPE_NONE; switch (arg->val.type) { case RVAL_TYPE_SCALAR: arg_type = StringDataType(ctx, RlistScalarValue(arg)); break; case RVAL_TYPE_FNCALL: { const FnCallType *fn = FnCallTypeGet(RlistFnCallValue(arg)->name); if (!fn) { FatalError(ctx, "Argument '%s' given to body '%s' is not a valid function", RlistFnCallValue(arg)->name, body->name); } arg_type = fn->dtype; } break; default: FatalError(ctx, "Cannot derive data type from Rval type %c", arg->val.type); } switch (arg->val.type) { case RVAL_TYPE_SCALAR: { const char *lval = RlistScalarValue(param); VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.'); EvalContextVariablePut(ctx, ref, RvalScalarValue(arg->val), arg_type, "source=body"); VarRefDestroy(ref); } break; case RVAL_TYPE_LIST: { const char *lval = RlistScalarValue(param); VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.'); EvalContextVariablePut(ctx, ref, RvalRlistValue(arg->val), arg_type, "source=body"); VarRefDestroy(ref); } break; case RVAL_TYPE_FNCALL: { FnCall *fp = RlistFnCallValue(arg); arg_type = CF_DATA_TYPE_NONE; { const FnCallType *fncall_type = FnCallTypeGet(fp->name); if (fncall_type) { arg_type = fncall_type->dtype; } } FnCallResult res = FnCallEvaluate(ctx, body->parent_policy, fp, NULL); if (res.status == FNCALL_FAILURE && THIS_AGENT_TYPE != AGENT_TYPE_COMMON) { Log(LOG_LEVEL_VERBOSE, "Embedded function argument does not resolve to a name - probably too many evaluation levels for '%s'", fp->name); } else { const char *lval = RlistScalarValue(param); void *rval = res.rval.item; VarRef *ref = VarRefParseFromNamespaceAndScope(lval, NULL, "body", CF_NS, '.'); EvalContextVariablePut(ctx, ref, rval, arg_type, "source=body"); VarRefDestroy(ref); } RvalDestroy(res.rval); } break; default: /* Nothing else should happen */ ProgrammingError("Software error: something not a scalar/function in argument literal"); } } } /*******************************************************************/ /* Utility functions */ /*******************************************************************/ void SplitScopeName(const char *scope, char ns_out[CF_MAXVARSIZE], char bundle_out[CF_MAXVARSIZE]) { assert(scope); char *split_point = strchr(scope, CF_NS); if (split_point) { strncpy(ns_out, scope, split_point - scope); strlcpy(bundle_out, split_point + 1, CF_MAXVARSIZE); } else { strlcpy(bundle_out, scope, CF_MAXVARSIZE); } } /*******************************************************************/ void JoinScopeName(const char *ns, const char *bundle, char scope_out[CF_MAXVARSIZE]) { assert(bundle); if (ns) { snprintf(scope_out, CF_MAXVARSIZE, "%s%c%s", ns, CF_NS, bundle); } else { snprintf(scope_out, CF_MAXVARSIZE, "%s", bundle); } } cfengine-3.6.2/libpromises/dbm_quick.c0000644000175100017510000002040612352022221017437 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* * Implementation using QDBM */ #include #include #include #include #ifdef QDB # include struct DBPriv_ { /* * This mutex controls the access to depot, which is not thread-aware */ pthread_mutex_t lock; /* * This mutex prevents two cursors to be active on depot at same time, as * cursors are internal for QDBM. 'cursor_lock' is always taken before * 'lock' to avoid deadlocks. */ pthread_mutex_t cursor_lock; DEPOT *depot; }; struct DBCursorPriv_ { DBPriv *db; char *curkey; int curkey_size; char *curval; }; /******************************************************************************/ static bool Lock(DBPriv *db) { int ret = pthread_mutex_lock(&db->lock); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to lock QDBM database. (pthread_mutex_lock: %s)", GetErrorStr()); return false; } return true; } static void Unlock(DBPriv *db) { int ret = pthread_mutex_unlock(&db->lock); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to unlock QDBM database. (pthread_mutex_unlock: %s)", GetErrorStr()); } } static bool LockCursor(DBPriv *db) { int ret = pthread_mutex_lock(&db->cursor_lock); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to obtain cursor lock for QDBM database. (pthread_mutex_lock: %s)", GetErrorStr()); return false; } return true; } static void UnlockCursor(DBPriv *db) { int ret = pthread_mutex_unlock(&db->cursor_lock); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to release cursor lock for QDBM database. (pthread_mutex_unlock: %s)", GetErrorStr()); } } const char *DBPrivGetFileExtension(void) { return "qdbm"; } DBPriv *DBPrivOpenDB(const char *filename, ARG_UNUSED dbid id) { DBPriv *db = xcalloc(1, sizeof(DBPriv)); pthread_mutex_init(&db->lock, NULL); pthread_mutex_init(&db->cursor_lock, NULL); db->depot = dpopen(filename, DP_OWRITER | DP_OCREAT, -1); if ((db->depot == NULL) && (dpecode == DP_EBROKEN)) { Log(LOG_LEVEL_ERR, "Database '%s' is broken, trying to repair...", filename); if (dprepair(filename)) { Log(LOG_LEVEL_INFO, "Successfully repaired database '%s'", filename); } else { Log(LOG_LEVEL_ERR, "Failed to repair database '%s', recreating...", filename); return DB_PRIV_DATABASE_BROKEN; } db->depot = dpopen(filename, DP_OWRITER | DP_OCREAT, -1); } if (db->depot == NULL) { Log(LOG_LEVEL_ERR, "dpopen: Opening database '%s' failed. (dpopen: %s)", filename, dperrmsg(dpecode)); pthread_mutex_destroy(&db->cursor_lock); pthread_mutex_destroy(&db->lock); free(db); return NULL; } return db; } void DBPrivCloseDB(DBPriv *db) { int ret; if ((ret = pthread_mutex_destroy(&db->lock)) != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Lock is still active during QDBM database handle close. (pthread_mutex_destroy: %s)", GetErrorStr()); } if ((ret = pthread_mutex_destroy(&db->cursor_lock)) != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Cursor lock is still active during QDBM database handle close. (pthread_mutex_destroy: %s)", GetErrorStr()); } if (!dpclose(db->depot)) { Log(LOG_LEVEL_ERR, "Unable to close QDBM database. (dpclose: %s)", dperrmsg(dpecode)); } free(db); } void DBPrivCommit(ARG_UNUSED DBPriv *db) { } bool DBPrivRead(DBPriv *db, const void *key, int key_size, void *dest, int dest_size) { if (!Lock(db)) { return false; } if (dpgetwb(db->depot, key, key_size, 0, dest_size, dest) == -1) { // FIXME: distinguish between "entry not found" and "failure to read" Log(LOG_LEVEL_DEBUG, "QDBM DBPrivRead: Could not read '%s', (dpgetwb: %s)", (const char *)key, dperrmsg(dpecode)); Unlock(db); return false; } Unlock(db); return true; } bool DBPrivWrite(DBPriv *db, const void *key, int key_size, const void *value, int value_size) { if (!Lock(db)) { return false; } if (!dpput(db->depot, key, key_size, value, value_size, DP_DOVER)) { char *db_name = dpname(db->depot); Log(LOG_LEVEL_ERR, "Could not write key to DB '%s'. (dpput: %s)", db_name, dperrmsg(dpecode)); free(db_name); Unlock(db); return false; } Unlock(db); return true; } bool DBPrivHasKey(DBPriv *db, const void *key, int key_size) { if (!Lock(db)) { return false; } int ret = dpvsiz(db->depot, key, key_size) != -1; Unlock(db); return ret; } int DBPrivGetValueSize(DBPriv *db, const void *key, int key_size) { if (!Lock(db)) { return false; } int ret = dpvsiz(db->depot, key, key_size); Unlock(db); return ret; } bool DBPrivDelete(DBPriv *db, const void *key, int key_size) { if (!Lock(db)) { return false; } /* dpout returns false both for error and if key is not found */ if (!dpout(db->depot, key, key_size) && dpecode != DP_ENOITEM) { Unlock(db); return false; } Unlock(db); return true; } DBCursorPriv *DBPrivOpenCursor(DBPriv *db) { if (!LockCursor(db)) { return NULL; } if (!Lock(db)) { UnlockCursor(db); return NULL; } if (!dpiterinit(db->depot)) { Log(LOG_LEVEL_ERR, "Could not initialize QuickDB iterator. (dpiterinit: %s)", dperrmsg(dpecode)); Unlock(db); UnlockCursor(db); return NULL; } DBCursorPriv *cursor = xcalloc(1, sizeof(DBCursorPriv)); cursor->db = db; Unlock(db); /* Cursor remains locked */ return cursor; } bool DBPrivAdvanceCursor(DBCursorPriv *cursor, void **key, int *ksize, void **value, int *vsize) { if (!Lock(cursor->db)) { return false; } free(cursor->curkey); free(cursor->curval); cursor->curkey = NULL; cursor->curval = NULL; *key = dpiternext(cursor->db->depot, ksize); if (*key == NULL) { /* Reached the end of database */ Unlock(cursor->db); return false; } *value = dpget(cursor->db->depot, *key, *ksize, 0, -1, vsize); // keep pointers for later free cursor->curkey = *key; cursor->curkey_size = *ksize; cursor->curval = *value; Unlock(cursor->db); return true; } bool DBPrivDeleteCursorEntry(DBCursorPriv *cursor) { return DBPrivDelete(cursor->db, cursor->curkey, cursor->curkey_size); } bool DBPrivWriteCursorEntry(DBCursorPriv *cursor, const void *value, int value_size) { return DBPrivWrite(cursor->db, cursor->curkey, cursor->curkey_size, value, value_size); } void DBPrivCloseCursor(DBCursorPriv *cursor) { DBPriv *db = cursor->db; /* FIXME: communicate the deadlock if happens */ Lock(db); free(cursor->curkey); free(cursor->curval); free(cursor); Unlock(db); /* Cursor lock was obtained in DBPrivOpenCursor */ UnlockCursor(db); } char *DBPrivDiagnose(const char *dbpath) { return StringFormat("Unable to diagnose QuickDB file (not implemented) for '%s'", dbpath); } #endif cfengine-3.6.2/libpromises/parser.c0000644000175100017510000001055112352557236017020 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include int yyparse(void); ParserState P = { 0 }; /* GLOBAL_X */ extern FILE *yyin; static void ParserStateReset(ParserState *p, bool discard) { p->agent_type = AGENT_TYPE_COMMON; p->warnings = PARSER_WARNING_ALL; p->policy = NULL; int i = CF_MAX_NESTING; while (i-- > 0) /* Clear stacks from top down */ { if (discard) { free(p->currentfnid[i]); RlistDestroy(p->giveargs[i]); FnCallDestroy(p->currentfncall[i]); } else { assert(!p->currentfnid[i]); assert(!p->giveargs[i]); assert(!p->currentfncall[i]); } p->currentfnid[i] = NULL; p->giveargs[i] = NULL; p->currentfncall[i] = NULL; } free(p->current_line); p->current_line = NULL; p->line_no = 1; p->line_pos = 1; p->error_count = 0; p->warning_count = 0; p->list_nesting = 0; p->arg_nesting = 0; free(p->current_namespace); p->current_namespace = xstrdup("default"); p->currentid[0] = '\0'; if (p->currentstring) { free(p->currentstring); } p->currentstring = NULL; p->currenttype[0] = '\0'; if (p->currentclasses) { free(p->currentclasses); } p->currentclasses = NULL; p->currentRlist = NULL; p->currentpromise = NULL; p->currentbody = NULL; if (p->promiser) { free(p->promiser); } p->promiser = NULL; p->blockid[0] = '\0'; p->blocktype[0] = '\0'; p->rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } static void ParserStateClean(ParserState *p) { free(p->current_namespace); p->current_namespace = NULL; } Policy *ParserParseFile(AgentType agent_type, const char *path, unsigned int warnings, unsigned int warnings_error) { ParserStateReset(&P, false); P.agent_type = agent_type; P.policy = PolicyNew(); P.warnings = warnings; P.warnings_error = warnings_error; strlcpy(P.filename, path, CF_MAXVARSIZE); yyin = safe_fopen(path, "rt"); if (yyin == NULL) { Log(LOG_LEVEL_ERR, "While opening file '%s' for parsing. (fopen: %s)", path, GetErrorStr()); exit(EXIT_FAILURE); } while (!feof(yyin)) { yyparse(); if (ferror(yyin)) { perror("cfengine"); exit(EXIT_FAILURE); } } fclose(yyin); if (P.error_count > 0) { PolicyDestroy(P.policy); ParserStateReset(&P, true); ParserStateClean(&P); return NULL; } Policy *policy = P.policy; ParserStateReset(&P, false); ParserStateClean(&P); return policy; } int ParserWarningFromString(const char *warning_str) { if (strcmp("deprecated", warning_str) == 0) { return PARSER_WARNING_DEPRECATED; } else if (strcmp("removed", warning_str) == 0) { return PARSER_WARNING_REMOVED; } else if (strcmp("all", warning_str) == 0) { return PARSER_WARNING_ALL; } else { return -1; } } const char *ParserWarningToString(unsigned int warning) { switch (warning) { case PARSER_WARNING_DEPRECATED: return "deprecated"; case PARSER_WARNING_REMOVED: return "removed"; default: ProgrammingError("Invalid parser warning: %u", warning); } } cfengine-3.6.2/libpromises/extensions_template.h0000644000175100017510000050037612352022221021611 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ BEGIN_MARKER // Do not include this file directly! Build process should replace XextensionX occurrences. /******************************************************************************* * Note: This shared library calling mechanism should only be used for private * shared libraries, such as the Enterprise plugins for CFEngine. ******************************************************************************/ /******************************************************************************* * How to use the Extension calling API: * * In the application: * * - Declare function prototypes using the xEXTENSIONx_FUNC_xARG_DECLARE macros. * Replace x with the number of arguments to the function. * * - Define a stub function using the xEXTENSIONx_FUNC_xARG_DEFINE_STUB macros. * * In the xExtensionX plugin: * * - Include the same prototype as you used in the application. * * - Define the xExtensionX function with the xEXTENSIONx_FUNC_xARG_DEFINE * macros. * * IMPORTANT: * * - For functions returning void, you need to use the VOID_FUNC version of the * macros. * * - Due to macro limitations, for each function argument, you need to put the * type and the name as separate arguments, so instead of (int par), use * (int, par). * * - You can use the function normally in your code. If the xExtensionX plugin * is available, it will call that function, if not, it will call the stub * function. * * - The lookup is more expensive than a normal function call. Don't use it in * a tight loop. * * - Be careful when changing the function signature. The plugin needs * to stay binary compatible, otherwise the it will not work, and may even * crash. Signature changes should only happen between major releases. * * Examples: * * - int xExtensionXOnlyInt(const char *str, int num) becomes * xEXTENSIONx_FUNC_2ARG_DECLARE(int, xExtensionXOnlyInt, * const char *, str, int, num) * xEXTENSIONx_FUNC_2ARG_DEFINE_STUB(int, xExtensionXOnlyInt, * const char *, str, int, num) * xEXTENSIONx_FUNC_2ARG_DEFINE(int, xExtensionXOnlyInt, * const char *, str, int, num) * * - void xExtensionXFunc(int num) becomes * xEXTENSIONx_VOID_FUNC_1ARG_DECLARE(void, xExtensionXFunc, int, num) * xEXTENSIONx_VOID_FUNC_1ARG_DEFINE_STUB(void, xExtensionXFunc, int, num) * xEXTENSIONx_VOID_FUNC_1ARG_DEFINE(void, xExtensionXFunc, int, num) ******************************************************************************/ /******************************************************************************* * It may be easier to understand the implementation below by looking at the * output it actually produces. gcc -E is your friend. ******************************************************************************/ #ifndef xEXTENSIONx_EXTENSION_H #define xEXTENSIONx_EXTENSION_H #include #include #ifndef BUILTIN_EXTENSIONS #define xEXTENSIONx_CANARY_VALUE 0x10203040 #define xEXTENSIONx_LIBRARY_NAME "cfengine-XextensionX.so" void *XextensionX_library_open(); void XextensionX_library_close(void *handle); #ifndef BUILDING_xEXTENSIONx_EXTENSION # define xEXTENSIONx_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ __ret __func() # define xEXTENSIONx_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func(__t1 __p1) # define xEXTENSIONx_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func(__t1 __p1, __t2 __p2) # define xEXTENSIONx_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3) # define xEXTENSIONx_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define xEXTENSIONx_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define xEXTENSIONx_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define xEXTENSIONx_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define xEXTENSIONx_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define xEXTENSIONx_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define xEXTENSIONx_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define xEXTENSIONx_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define xEXTENSIONx_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define xEXTENSIONx_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define xEXTENSIONx_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define xEXTENSIONx_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) # define xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) \ __ret __func##__stub() # define xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__stub(__t1 __p1) # define xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__stub(__t1 __p1, __t2 __p2) # define xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3) # define xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) #else // BUILDING_xEXTENSIONx_EXTENSION # define xEXTENSIONx_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, int32_t __end_canary) # define xEXTENSIONx_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, int32_t __end_canary) # define xEXTENSIONx_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, int32_t __end_canary) # define xEXTENSIONx_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, int32_t __end_canary) # define xEXTENSIONx_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, int32_t __end_canary) # define xEXTENSIONx_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, int32_t __end_canary) # define xEXTENSIONx_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, int32_t __end_canary) # define xEXTENSIONx_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, int32_t __end_canary) # define xEXTENSIONx_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, int32_t __end_canary) # define xEXTENSIONx_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, int32_t __end_canary) # define xEXTENSIONx_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, int32_t __end_canary) # define xEXTENSIONx_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, int32_t __end_canary) # define xEXTENSIONx_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, int32_t __end_canary) # define xEXTENSIONx_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, int32_t __end_canary) # define xEXTENSIONx_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, int32_t __end_canary) # define xEXTENSIONx_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15, int32_t __end_canary) # define xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) \ __ret __func##__real() # define xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__real(__t1 __p1) # define xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__real(__t1 __p1, __t2 __p2) # define xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3) # define xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) # define xEXTENSIONx_FUNC_0ARG_INLINE_SIGNATURE(__ret, __func) \ inline static __ret __func() # define xEXTENSIONx_FUNC_1ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1) \ inline static __ret __func(__t1 __p1) # define xEXTENSIONx_FUNC_2ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ inline static __ret __func(__t1 __p1, __t2 __p2) # define xEXTENSIONx_FUNC_3ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3) # define xEXTENSIONx_FUNC_4ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define xEXTENSIONx_FUNC_5ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define xEXTENSIONx_FUNC_6ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define xEXTENSIONx_FUNC_7ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define xEXTENSIONx_FUNC_8ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define xEXTENSIONx_FUNC_9ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define xEXTENSIONx_FUNC_10ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define xEXTENSIONx_FUNC_11ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define xEXTENSIONx_FUNC_12ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define xEXTENSIONx_FUNC_13ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define xEXTENSIONx_FUNC_14ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define xEXTENSIONx_FUNC_15ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) #endif // BUILDING_xEXTENSIONx_EXTENSION #ifndef BUILDING_xEXTENSIONx_EXTENSION # define xEXTENSIONx_FUNC_0ARG_DECLARE_IMPL(__ret, __func) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, int32_t __end_canary); \ xEXTENSIONx_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func); \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define xEXTENSIONx_FUNC_1ARG_DECLARE_IMPL(__ret, __func, __t1, __p1) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, int32_t __end_canary); \ xEXTENSIONx_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1); \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define xEXTENSIONx_FUNC_2ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, int32_t __end_canary); \ xEXTENSIONx_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2); \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define xEXTENSIONx_FUNC_3ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, int32_t __end_canary); \ xEXTENSIONx_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3); \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define xEXTENSIONx_FUNC_4ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, int32_t __end_canary); \ xEXTENSIONx_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4); \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define xEXTENSIONx_FUNC_5ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, int32_t __end_canary); \ xEXTENSIONx_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5); \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define xEXTENSIONx_FUNC_6ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, int32_t __end_canary); \ xEXTENSIONx_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6); \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define xEXTENSIONx_FUNC_7ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, int32_t __end_canary); \ xEXTENSIONx_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7); \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define xEXTENSIONx_FUNC_8ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, int32_t __end_canary); \ xEXTENSIONx_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8); \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define xEXTENSIONx_FUNC_9ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, int32_t __end_canary); \ xEXTENSIONx_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9); \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define xEXTENSIONx_FUNC_10ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, int32_t __end_canary); \ xEXTENSIONx_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10); \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define xEXTENSIONx_FUNC_11ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, int32_t __end_canary); \ xEXTENSIONx_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11); \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define xEXTENSIONx_FUNC_12ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, int32_t __end_canary); \ xEXTENSIONx_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12); \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define xEXTENSIONx_FUNC_13ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, int32_t __end_canary); \ xEXTENSIONx_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13); \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define xEXTENSIONx_FUNC_14ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, int32_t __end_canary); \ xEXTENSIONx_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14); \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define xEXTENSIONx_FUNC_15ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15, int32_t __end_canary); \ xEXTENSIONx_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15); \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) # define xEXTENSIONx_FUNC_0ARG_DECLARE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_DECLARE_IMPL(__ret, __func) # define xEXTENSIONx_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_DECLARE_IMPL(__ret, __func, __t1, __p1) # define xEXTENSIONx_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2) # define xEXTENSIONx_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define xEXTENSIONx_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define xEXTENSIONx_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define xEXTENSIONx_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define xEXTENSIONx_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define xEXTENSIONx_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define xEXTENSIONx_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define xEXTENSIONx_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define xEXTENSIONx_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define xEXTENSIONx_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define xEXTENSIONx_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define xEXTENSIONx_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define xEXTENSIONx_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) # define xEXTENSIONx_VOID_FUNC_0ARG_DECLARE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_DECLARE_IMPL(__ret, __func) # define xEXTENSIONx_VOID_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_DECLARE_IMPL(__ret, __func, __t1, __p1) # define xEXTENSIONx_VOID_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2) # define xEXTENSIONx_VOID_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define xEXTENSIONx_VOID_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define xEXTENSIONx_VOID_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define xEXTENSIONx_VOID_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define xEXTENSIONx_VOID_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define xEXTENSIONx_VOID_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define xEXTENSIONx_VOID_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define xEXTENSIONx_VOID_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define xEXTENSIONx_VOID_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define xEXTENSIONx_VOID_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define xEXTENSIONx_VOID_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define xEXTENSIONx_VOID_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define xEXTENSIONx_VOID_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #else // BUILDING_xEXTENSIONx_EXTENSION # define xEXTENSIONx_FUNC_0ARG_DECLARE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func); \ xEXTENSIONx_FUNC_0ARG_INLINE_SIGNATURE(__ret, __func) \ { \ return __func##__real(); \ } \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define xEXTENSIONx_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1); \ xEXTENSIONx_FUNC_1ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1) \ { \ return __func##__real(__p1); \ } \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define xEXTENSIONx_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2); \ xEXTENSIONx_FUNC_2ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ { \ return __func##__real(__p1, __p2); \ } \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define xEXTENSIONx_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3); \ xEXTENSIONx_FUNC_3ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ { \ return __func##__real(__p1, __p2, __p3); \ } \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define xEXTENSIONx_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4); \ xEXTENSIONx_FUNC_4ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ { \ return __func##__real(__p1, __p2, __p3, __p4); \ } \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define xEXTENSIONx_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5); \ xEXTENSIONx_FUNC_5ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5); \ } \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define xEXTENSIONx_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6); \ xEXTENSIONx_FUNC_6ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6); \ } \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define xEXTENSIONx_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7); \ xEXTENSIONx_FUNC_7ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7); \ } \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define xEXTENSIONx_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8); \ xEXTENSIONx_FUNC_8ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8); \ } \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define xEXTENSIONx_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9); \ xEXTENSIONx_FUNC_9ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9); \ } \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define xEXTENSIONx_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10); \ xEXTENSIONx_FUNC_10ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10); \ } \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define xEXTENSIONx_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11); \ xEXTENSIONx_FUNC_11ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11); \ } \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define xEXTENSIONx_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12); \ xEXTENSIONx_FUNC_12ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12); \ } \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define xEXTENSIONx_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13); \ xEXTENSIONx_FUNC_13ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13); \ } \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define xEXTENSIONx_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14); \ xEXTENSIONx_FUNC_14ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14); \ } \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define xEXTENSIONx_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15); \ xEXTENSIONx_FUNC_15ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15); \ } \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) # define xEXTENSIONx_VOID_FUNC_0ARG_DECLARE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func); \ xEXTENSIONx_FUNC_0ARG_INLINE_SIGNATURE(__ret, __func) \ { \ return __func##__real(); \ } \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define xEXTENSIONx_VOID_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1); \ xEXTENSIONx_FUNC_1ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1) \ { \ return __func##__real(__p1); \ } \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define xEXTENSIONx_VOID_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2); \ xEXTENSIONx_FUNC_2ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ { \ return __func##__real(__p1, __p2); \ } \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define xEXTENSIONx_VOID_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3); \ xEXTENSIONx_FUNC_3ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ { \ return __func##__real(__p1, __p2, __p3); \ } \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define xEXTENSIONx_VOID_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4); \ xEXTENSIONx_FUNC_4ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ { \ return __func##__real(__p1, __p2, __p3, __p4); \ } \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define xEXTENSIONx_VOID_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5); \ xEXTENSIONx_FUNC_5ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5); \ } \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define xEXTENSIONx_VOID_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6); \ xEXTENSIONx_FUNC_6ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6); \ } \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define xEXTENSIONx_VOID_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7); \ xEXTENSIONx_FUNC_7ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7); \ } \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define xEXTENSIONx_VOID_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8); \ xEXTENSIONx_FUNC_8ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8); \ } \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define xEXTENSIONx_VOID_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9); \ xEXTENSIONx_FUNC_9ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9); \ } \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define xEXTENSIONx_VOID_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10); \ xEXTENSIONx_FUNC_10ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10); \ } \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define xEXTENSIONx_VOID_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11); \ xEXTENSIONx_FUNC_11ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11); \ } \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define xEXTENSIONx_VOID_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12); \ xEXTENSIONx_FUNC_12ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12); \ } \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define xEXTENSIONx_VOID_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13); \ xEXTENSIONx_FUNC_13ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13); \ } \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define xEXTENSIONx_VOID_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14); \ xEXTENSIONx_FUNC_14ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14); \ } \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define xEXTENSIONx_VOID_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15); \ xEXTENSIONx_FUNC_15ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15); \ } \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #endif // BUILDING_xEXTENSIONx_EXTENSION #ifndef BUILDING_xEXTENSIONx_EXTENSION // The __ret__assign and __ret_ref parameters are to work around functions returning void. #define xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, __real__func__par, __stub__func__par) \ { \ void *__handle = XextensionX_library_open(); \ if (__handle) \ { \ static __func##__type func_ptr = NULL; \ if (!func_ptr) \ { \ func_ptr = shlib_load(__handle, #__func "__wrapper"); \ } \ if (func_ptr) \ { \ int __successful = 0; \ __ret__assign func_ptr __real__func__par; \ if (__successful) \ { \ XextensionX_library_close(__handle); \ return __ret__ref; \ } \ } \ XextensionX_library_close(__handle); \ } \ return __func##__stub __stub__func__par; \ } # define xEXTENSIONx_FUNC_0ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref) \ xEXTENSIONx_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, xEXTENSIONx_CANARY_VALUE), \ ()) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define xEXTENSIONx_FUNC_1ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, xEXTENSIONx_CANARY_VALUE), \ (__p1)) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define xEXTENSIONx_FUNC_2ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2)) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define xEXTENSIONx_FUNC_3ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3)) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define xEXTENSIONx_FUNC_4ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4)) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define xEXTENSIONx_FUNC_5ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5)) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define xEXTENSIONx_FUNC_6ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6)) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define xEXTENSIONx_FUNC_7ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7)) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define xEXTENSIONx_FUNC_8ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8)) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define xEXTENSIONx_FUNC_9ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9)) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define xEXTENSIONx_FUNC_10ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10)) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define xEXTENSIONx_FUNC_11ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11)) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define xEXTENSIONx_FUNC_12ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12)) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define xEXTENSIONx_FUNC_13ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13)) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define xEXTENSIONx_FUNC_14ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14)) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define xEXTENSIONx_FUNC_15ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (xEXTENSIONx_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15, xEXTENSIONx_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15)) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value) #define xEXTENSIONx_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1) #define xEXTENSIONx_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2) #define xEXTENSIONx_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_VOID_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_DEFINE_STUB_IMPL(__ret, __func, , ) #define xEXTENSIONx_VOID_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1) #define xEXTENSIONx_VOID_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2) #define xEXTENSIONx_VOID_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_VOID_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_VOID_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_VOID_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_VOID_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_VOID_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_VOID_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_VOID_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_VOID_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_VOID_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_VOID_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_VOID_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_VOID_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_FUNC_DEFINE_REAL_INVALID In_core_code_you_need_to_use_DEFINE_STUB func() #define xEXTENSIONx_FUNC_0ARG_DEFINE(__ret, __func) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_0ARG_DEFINE(__ret, __func) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #define xEXTENSIONx_VOID_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_DEFINE_REAL_INVALID #else // BUILDING_xEXTENSIONx_EXTENSION #define xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL_RET_VALUE(__ret, __func, __real__func__par, __ret__expr) \ { \ if (__start_canary != xEXTENSIONx_CANARY_VALUE || __end_canary != xEXTENSIONx_CANARY_VALUE) \ { \ Log(LOG_LEVEL_ERR, "Function '%s %s%s' failed stack consistency check. Most likely this means the plugin containing the " \ "function is incompatible with this version of CFEngine.", #__ret, #__func, #__real__func__par); \ __ret__expr; \ } \ *__successful = 1; \ return __func __real__func__par; \ } #define xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, __real__func__par) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL_RET_VALUE(__ret, __func, __real__func__par, \ __ret __ret_value = (__ret)0; \ (void)__ret_value; \ return __ret_value) #define xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, __real__func__par) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL_RET_VALUE(__ret, __func, __real__func__par, return) #define xEXTENSIONx_FUNC_DEFINE_INLINE_IMPL(__ret, __func, __real__func__par) \ { \ return __func##__real __real__func__par; \ } #define xEXTENSIONx_FUNC_0ARG_DEFINE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ ()) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define xEXTENSIONx_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1)) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2)) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3)) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4)) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5)) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6)) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7)) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8)) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9)) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10)) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11)) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12)) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13)) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14)) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15)) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_VOID_FUNC_0ARG_DEFINE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ ()) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define xEXTENSIONx_VOID_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1)) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_VOID_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2)) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_VOID_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3)) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_VOID_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4)) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_VOID_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5)) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_VOID_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6)) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_VOID_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7)) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_VOID_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8)) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_VOID_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9)) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_VOID_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10)) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_VOID_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11)) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_VOID_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12)) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_VOID_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13)) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_VOID_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14)) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_VOID_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15)) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_FUNC_DEFINE_STUB_INVALID In_extension_code_you_cannot_define_a_STUB func() #define xEXTENSIONx_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #define xEXTENSIONx_VOID_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_DEFINE_STUB_INVALID #endif // BUILDING_xEXTENSIONx_EXTENSION #else // BUILTIN_EXTENSIONS // In this case just map to real function calls. // BUILTIN_EXTENSIONS is for Windows binaries and debugging. # define xEXTENSIONx_FUNC_0ARG_STUB_SIGNATURE(__ret, __func) \ __ret __func##__stub() # define xEXTENSIONx_FUNC_1ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__stub(__t1 __p1) # define xEXTENSIONx_FUNC_2ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__stub(__t1 __p1, __t2 __p2) # define xEXTENSIONx_FUNC_3ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3) # define xEXTENSIONx_FUNC_4ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define xEXTENSIONx_FUNC_5ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define xEXTENSIONx_FUNC_6ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define xEXTENSIONx_FUNC_7ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define xEXTENSIONx_FUNC_8ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define xEXTENSIONx_FUNC_9ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define xEXTENSIONx_FUNC_10ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define xEXTENSIONx_FUNC_11ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define xEXTENSIONx_FUNC_12ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define xEXTENSIONx_FUNC_13ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define xEXTENSIONx_FUNC_14ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define xEXTENSIONx_FUNC_15ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) # define xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) \ __ret __func() # define xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func(__t1 __p1) # define xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func(__t1 __p1, __t2 __p2) # define xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3) # define xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) #define xEXTENSIONx_FUNC_0ARG_DECLARE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define xEXTENSIONx_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_VOID_FUNC_0ARG_DECLARE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define xEXTENSIONx_VOID_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_VOID_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_VOID_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_VOID_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_VOID_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_VOID_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_VOID_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_VOID_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_VOID_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_VOID_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_VOID_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_VOID_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_VOID_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_VOID_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_VOID_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_FUNC_0ARG_DEFINE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define xEXTENSIONx_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_VOID_FUNC_0ARG_DEFINE(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define xEXTENSIONx_VOID_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_VOID_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_VOID_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_VOID_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_VOID_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_VOID_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_VOID_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_VOID_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_VOID_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_VOID_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_VOID_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_VOID_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_VOID_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_VOID_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_VOID_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_STUB_SIGNATURE(__ret, __func) #define xEXTENSIONx_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define xEXTENSIONx_VOID_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ xEXTENSIONx_FUNC_0ARG_STUB_SIGNATURE(__ret, __func) #define xEXTENSIONx_VOID_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ xEXTENSIONx_FUNC_1ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1) #define xEXTENSIONx_VOID_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ xEXTENSIONx_FUNC_2ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define xEXTENSIONx_VOID_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ xEXTENSIONx_FUNC_3ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define xEXTENSIONx_VOID_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ xEXTENSIONx_FUNC_4ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define xEXTENSIONx_VOID_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ xEXTENSIONx_FUNC_5ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define xEXTENSIONx_VOID_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ xEXTENSIONx_FUNC_6ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define xEXTENSIONx_VOID_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ xEXTENSIONx_FUNC_7ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define xEXTENSIONx_VOID_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ xEXTENSIONx_FUNC_8ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define xEXTENSIONx_VOID_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ xEXTENSIONx_FUNC_9ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define xEXTENSIONx_VOID_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ xEXTENSIONx_FUNC_10ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define xEXTENSIONx_VOID_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ xEXTENSIONx_FUNC_11ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define xEXTENSIONx_VOID_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ xEXTENSIONx_FUNC_12ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define xEXTENSIONx_VOID_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ xEXTENSIONx_FUNC_13ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define xEXTENSIONx_VOID_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ xEXTENSIONx_FUNC_14ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define xEXTENSIONx_VOID_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ xEXTENSIONx_FUNC_15ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #endif // BUILTIN_EXTENSIONS #endif // xEXTENSIONx_EXTENSION_H cfengine-3.6.2/libpromises/solaris_ifaddrs.c0000664000175100017510000001655212400110676020670 0ustar00a10038a1003800000000000000/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * CDDL HEADER END */ /* *Portions Copyright 2013 CFEngine AS */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include int getallifaddrs(sa_family_t , struct ifaddrs **, int64_t); int getallifs(int, sa_family_t, struct lifreq **, int *, int64_t); /* * Create a linked list of `struct ifaddrs' structures, one for each * address that is UP. If successful, store the list in *ifap and * return 0. On errors, return -1 and set `errno'. * * The storage returned in *ifap is allocated dynamically and can * only be properly freed by passing it to `freeifaddrs'. */ int solaris_getifaddrs(struct ifaddrs **ifap) { int err; char *cp; struct ifaddrs *curr; if (ifap == NULL) { errno = EINVAL; return (-1); } *ifap = NULL; err = getallifaddrs(AF_UNSPEC, ifap, LIFC_ENABLED); if (err == 0) { for (curr = *ifap; curr != NULL; curr = curr->ifa_next) { if ((cp = strchr(curr->ifa_name, ':')) != NULL) *cp = '\0'; } } return (err); } void solaris_freeifaddrs(struct ifaddrs *ifa) { struct ifaddrs *curr; while (ifa != NULL) { curr = ifa; ifa = ifa->ifa_next; free(curr->ifa_name); free(curr->ifa_addr); free(curr->ifa_netmask); free(curr->ifa_dstaddr); free(curr); } } /* * Returns all addresses configured on the system. If flags contain * LIFC_ENABLED, only the addresses that are UP are returned. * Address list that is returned by this function must be freed * using freeifaddrs(). */ int getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags) { struct lifreq *buf = NULL; struct lifreq *lifrp; struct lifreq lifrl; int ret; int s, n, numifs; struct ifaddrs *curr, *prev; sa_family_t lifr_af; int sock4; int sock6; int err; if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (-1); if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { err = errno; close(sock4); errno = err; return (-1); } retry: /* Get all interfaces from SIOCGLIFCONF */ ret = getallifs(sock4, af, &buf, &numifs, (flags & ~LIFC_ENABLED)); if (ret != 0) goto fail; /* * Loop through the interfaces obtained from SIOCGLIFCOMF * and retrieve the addresses, netmask and flags. */ prev = NULL; lifrp = buf; *ifap = NULL; for (n = 0; n < numifs; n++, lifrp++) { /* Prepare for the ioctl call */ (void) strlcpy(lifrl.lifr_name, lifrp->lifr_name, sizeof(lifrl.lifr_name)); lifr_af = lifrp->lifr_addr.ss_family; if (af != AF_UNSPEC && lifr_af != af) continue; s = (lifr_af == AF_INET ? sock4 : sock6); if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0) goto fail; if ((flags & LIFC_ENABLED) && !(lifrl.lifr_flags & IFF_UP)) continue; /* * Allocate the current list node. Each node contains data * for one ifaddrs structure. */ curr = calloc(1, sizeof (struct ifaddrs)); if (curr == NULL) goto fail; if (prev != NULL) { prev->ifa_next = curr; } else { /* First node in the linked list */ *ifap = curr; } prev = curr; curr->ifa_flags = lifrl.lifr_flags; if ((curr->ifa_name = strdup(lifrp->lifr_name)) == NULL) goto fail; curr->ifa_addr = malloc(sizeof (struct sockaddr_storage)); if (curr->ifa_addr == NULL) goto fail; (void) memcpy(curr->ifa_addr, &lifrp->lifr_addr, sizeof (struct sockaddr_storage)); /* Get the netmask */ if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifrl) < 0) goto fail; curr->ifa_netmask = malloc(sizeof (struct sockaddr_storage)); if (curr->ifa_netmask == NULL) goto fail; (void) memcpy(curr->ifa_netmask, &lifrl.lifr_addr, sizeof (struct sockaddr_storage)); /* Get the destination for a pt-pt interface */ if (curr->ifa_flags & IFF_POINTOPOINT) { if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifrl) < 0) goto fail; curr->ifa_dstaddr = malloc( sizeof (struct sockaddr_storage)); if (curr->ifa_dstaddr == NULL) goto fail; (void) memcpy(curr->ifa_dstaddr, &lifrl.lifr_addr, sizeof (struct sockaddr_storage)); } else if (curr->ifa_flags & IFF_BROADCAST) { if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifrl) < 0) goto fail; curr->ifa_broadaddr = malloc( sizeof (struct sockaddr_storage)); if (curr->ifa_broadaddr == NULL) goto fail; (void) memcpy(curr->ifa_broadaddr, &lifrl.lifr_addr, sizeof (struct sockaddr_storage)); } } free(buf); close(sock4); close(sock6); return (0); fail: err = errno; free(buf); solaris_freeifaddrs(*ifap); *ifap = NULL; if (err == ENXIO) goto retry; close(sock4); close(sock6); errno = err; return (-1); } /* * Do a SIOCGLIFCONF and store all the interfaces in `buf'. */ int getallifs(int s, sa_family_t af, struct lifreq **lifr, int *numifs, int64_t lifc_flags) { struct lifnum lifn; struct lifconf lifc; size_t bufsize; char *tmp; caddr_t *buf = (caddr_t *)lifr; lifn.lifn_family = af; lifn.lifn_flags = lifc_flags; *buf = NULL; retry: if (ioctl(s, SIOCGLIFNUM, &lifn) < 0) goto fail; /* * When calculating the buffer size needed, add a small number * of interfaces to those we counted. We do this to capture * the interface status of potential interfaces which may have * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. */ bufsize = (lifn.lifn_count + 4) * sizeof (struct lifreq); if ((tmp = realloc(*buf, bufsize)) == NULL) goto fail; *buf = tmp; lifc.lifc_family = af; lifc.lifc_flags = lifc_flags; lifc.lifc_len = bufsize; lifc.lifc_buf = *buf; if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) goto fail; *numifs = lifc.lifc_len / sizeof (struct lifreq); if (*numifs >= (lifn.lifn_count + 4)) { /* * If every entry was filled, there are probably * more interfaces than (lifn.lifn_count + 4). * Redo the ioctls SIOCGLIFNUM and SIOCGLIFCONF to * get all the interfaces. */ goto retry; } return (0); fail: free(*buf); *buf = NULL; return (-1); } cfengine-3.6.2/libpromises/patches.c0000644000175100017510000001415512352557236017157 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* Contains any fixes which need to be made because of lack of OS support on a given platform These are conditionally compiled, pending extensions or developments in the OS concerned. FIXME: move to the libcompat/ directory or to the apropriate source file. */ #include #include static char *cf_format_strtimestamp(struct tm *tm, char *buf); /*********************************************************/ #ifndef HAVE_SETNETGRENT #if SETNETGRENT_RETURNS_INT int #else void #endif setnetgrent(const char *netgroup) { #if SETNETGRENT_RETURNS_INT return 0; #endif } #endif /**********************************************************/ #ifndef HAVE_GETNETGRENT int getnetgrent(char **machinep, char **userp, char **domainp) { *machinep = NULL; *userp = NULL; *domainp = NULL; return 0; } #endif /***********************************************************/ #ifndef HAVE_ENDNETGRENT #if ENDNETGRENT_RETURNS_INT int #else void #endif endnetgrent(void) { #if ENDNETGRENT_RETURNS_INT return 1; #endif } #endif #ifndef HAVE_SETEUID # if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif # endif int seteuid(uid_t uid) { # ifdef HAVE_SETREUID return setreuid(-1, uid); # else Log(LOG_LEVEL_VERBOSE, "(This system does not have setreuid (patches.c)"); return -1; # endif } #endif /***********************************************************/ #ifndef HAVE_SETEGID int setegid(gid_t gid) { # ifdef HAVE_SETREGID return setregid(-1, gid); # else Log(LOG_LEVEL_VERBOSE, "(This system does not have setregid (patches.c)"); return -1; # endif } #endif /*******************************************************************/ int IsPrivileged() { #ifdef _WIN32 return true; #else return (getuid() == 0); #endif } /* * This function converts passed time_t value to string timestamp used * throughout the system. By sheer coincidence this timestamp has the same * format as ctime(3) output on most systems (but NT differs in definition of * ctime format, so those are not identical there). * * Buffer passed should be at least 26 bytes long (including the trailing zero). * * Please use this function instead of (non-portable and deprecated) ctime_r or * (non-threadsafe) ctime. */ /*******************************************************************/ char *cf_strtimestamp_local(const time_t time, char *buf) { struct tm tm; if (localtime_r(&time, &tm) == NULL) { Log(LOG_LEVEL_VERBOSE, "Unable to parse passed timestamp. (localtime_r: %s)", GetErrorStr()); return NULL; } return cf_format_strtimestamp(&tm, buf); } /*******************************************************************/ char *cf_strtimestamp_utc(const time_t time, char *buf) { struct tm tm; if (gmtime_r(&time, &tm) == NULL) { Log(LOG_LEVEL_VERBOSE, "Unable to parse passed timestamp. (gmtime_r: %s)", GetErrorStr()); return NULL; } return cf_format_strtimestamp(&tm, buf); } /*******************************************************************/ static char *cf_format_strtimestamp(struct tm *tm, char *buf) { /* Security checks */ if ((tm->tm_year < -2899) || (tm->tm_year > 8099)) { Log(LOG_LEVEL_ERR, "Unable to format timestamp: passed year is out of range: %d", tm->tm_year + 1900); return NULL; } /* There is no easy way to replicate ctime output by using strftime */ if (snprintf(buf, 26, "%3.3s %3.3s %2d %02d:%02d:%02d %04d", DAY_TEXT[tm->tm_wday ? (tm->tm_wday - 1) : 6], MONTH_TEXT[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900) >= 26) { Log(LOG_LEVEL_ERR, "Unable to format timestamp: passed values are out of range"); return NULL; } return buf; } /*******************************************************************/ int cf_closesocket(int sd) { int res; #ifdef __MINGW32__ res = closesocket(sd); #else res = close(sd); #endif if (res != 0) { Log(LOG_LEVEL_ERR, "Could not close socket. (cf_closesocket: %s)", GetErrorStr()); } return res; } int LinkOrCopy(const char *from, const char *to, int sym) /** * Creates symlink to file on platforms supporting it, copies on * others. **/ { #ifdef __MINGW32__ // only copy on Windows for now if (!CopyFile(from, to, TRUE)) { return false; } #else /* !__MINGW32__ */ if (sym) { if (symlink(from, to) == -1) { return false; } } else // hardlink { if (link(from, to) == -1) { return false; } } #endif /* !__MINGW32__ */ return true; } #if !defined(__MINGW32__) int ExclusiveLockFile(int fd) { struct flock lock = { .l_type = F_WRLCK, .l_whence = SEEK_SET, }; while (fcntl(fd, F_SETLKW, &lock) == -1) { if (errno != EINTR) { return -1; } } return 0; } int ExclusiveUnlockFile(int fd) { return close(fd); } #endif cfengine-3.6.2/libpromises/storage_tools.c0000664000175100017510000000635012400110676020377 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #ifdef HAVE_SYS_STATFS_H # include #endif #ifdef HAVE_SYS_VFS_H # include #endif #ifdef HAVE_SYS_STATVFS_H # include #endif /************************************************************************/ #ifndef __MINGW32__ off_t GetDiskUsage(char *file, CfSize type) { # if defined __sun || defined sco || defined __OpenBSD__ || (defined(__NetBSD__) && __NetBSD_Version__ >= 200040000) struct statvfs buf; # else struct statfs buf; # endif off_t used = 0, avail = 0; int capacity = 0; memset(&buf, 0, sizeof(buf)); # if defined __sun || defined sco || defined __OpenBSD__ || (defined(__NetBSD__) && __NetBSD_Version__ >= 200040000) if (statvfs(file, &buf) != 0) { Log(LOG_LEVEL_ERR, "statvfs", "Couldn't get filesystem info for %s", file); return CF_INFINITY; } # elif defined __SCO_DS || defined _CRAY || (defined(__NetBSD__) && __NetBSD_Version__ >= 200040000) if (statfs(file, &buf, sizeof(struct statfs), 0) != 0) { Log(LOG_LEVEL_ERR, "statfs", "Couldn't get filesystem info for %s", file); return CF_INFINITY; } # else if (statfs(file, &buf) != 0) { Log(LOG_LEVEL_ERR, "Couldn't get filesystem info for '%s'. (statfs: %s)", file, GetErrorStr()); return CF_INFINITY; } # endif # if defined __sun used = (buf.f_blocks - buf.f_bfree) * buf.f_frsize; avail = buf.f_bavail * buf.f_frsize; # endif # if defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __hpux || defined __APPLE__ used = (buf.f_blocks - buf.f_bfree) * buf.f_bsize; avail = buf.f_bavail * buf.f_bsize; # endif # if defined _AIX || defined __SCO_DS || defined _CRAY used = (buf.f_blocks - buf.f_bfree) * (float) buf.f_bsize; avail = buf.f_bfree * (float) buf.f_bsize; # endif # if defined __linux__ used = (buf.f_blocks - buf.f_bfree) * (float) buf.f_bsize; avail = buf.f_bavail * (float) buf.f_bsize; # endif capacity = (double) (avail) / (double) (avail + used) * 100; Log(LOG_LEVEL_DEBUG, "GetDiskUsage(%s) = %jd/%jd", file, (intmax_t) avail, (intmax_t) capacity); if (type == CF_SIZE_ABS) { return avail; } else { return capacity; } } #endif /* __MINGW32__ */ cfengine-3.6.2/libpromises/process_unix_priv.h0000664000175100017510000000312212243421446021300 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROCESS_PRIV_H #define CFENGINE_PROCESS_PRIV_H /* * Unix-like OS should provide implementations of the following functions. */ /* * GetProcessStartTime (see process_lib.h) */ typedef enum { PROCESS_STATE_RUNNING, PROCESS_STATE_STOPPED, PROCESS_STATE_DOES_NOT_EXIST } ProcessState; /* * Obtain process state. * * @return PROCESS_STATE_RUNNING if process exists and is running, * @return PROCESS_STATE_STOPPED if process exists and has been stopped by SIGSTOP signal, * @return PROCESS_STATE_DOES_NOT_EXIST if process cannot be found. */ ProcessState GetProcessState(pid_t pid); #endif cfengine-3.6.2/libpromises/extensions_template.c0000664000175100017510000000440412243421446021610 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ BEGIN_MARKER // Do not include this file directly! Build process should replace XextensionX occurrences. #include #include #include #ifndef BUILTIN_EXTENSIONS static pthread_once_t XextensionX_library_once = PTHREAD_ONCE_INIT; static void *XextensionX_library_handle = NULL; static void XextensionX_library_assign(); void *XextensionX_library_open() { if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") != NULL) { return extension_library_open(xEXTENSIONx_LIBRARY_NAME); } int ret = pthread_once(&XextensionX_library_once, &XextensionX_library_assign); if (ret != 0) { Log(LOG_LEVEL_ERR, "Could not initialize Extension Library: %s: %s", xEXTENSIONx_LIBRARY_NAME, strerror(ret)); return NULL; } return XextensionX_library_handle; } static void XextensionX_library_assign() { XextensionX_library_handle = extension_library_open(xEXTENSIONx_LIBRARY_NAME); } void XextensionX_library_close(void *handle) { if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") != NULL) { return extension_library_close(handle); } // Normally we don't ever close the extension library, because we may have // pointer references to it. } #endif // BUILTIN_EXTENSIONS cfengine-3.6.2/libpromises/process_unix.c0000664000175100017510000001503512403637345020246 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #define SLEEP_POLL_TIMEOUT_NS 10000000 /* * Wait until process specified by #pid is stopped due to SIGSTOP signal. * * @returns true if process has come to stop during #timeout_ns nanoseconds, * false if the process cannot be found or failed to stop during #timeout_ns * nanoseconds. * * FIXME: Only timeouts < 1s are supported */ static bool ProcessWaitUntilStopped(pid_t pid, long timeout_ns) { while (timeout_ns > 0) { switch (GetProcessState(pid)) { case PROCESS_STATE_RUNNING: break; case PROCESS_STATE_STOPPED: return true; case PROCESS_STATE_DOES_NOT_EXIST: return false; default: ProgrammingError("Unexpected value returned from GetProcessState"); } struct timespec ts = { .tv_sec = 0, .tv_nsec = MIN(SLEEP_POLL_TIMEOUT_NS, timeout_ns), }; while (nanosleep(&ts, &ts) < 0) { if (errno != EINTR) { ProgrammingError("Invalid timeout for nanosleep"); } } timeout_ns = MAX(0, timeout_ns - SLEEP_POLL_TIMEOUT_NS); } return false; } /* * FIXME: Only timeouts < 1s are supported */ static bool ProcessWaitUntilExited(pid_t pid, long timeout_ns) { while (timeout_ns > 0) { if (kill(pid, 0) < 0 && errno == ESRCH) { return true; } struct timespec ts = { .tv_sec = 0, .tv_nsec = MIN(SLEEP_POLL_TIMEOUT_NS, timeout_ns), }; while (nanosleep(&ts, &ts) < 0) { if (errno != EINTR) { ProgrammingError("Invalid timeout for nanosleep"); } } timeout_ns = MAX(0, timeout_ns - SLEEP_POLL_TIMEOUT_NS); } return false; } /* A timeout to wait for process to stop (pause) or exit. Note that * it's important that it not over-flow 32 bits; no more than nine 9s * in a row ! */ #define STOP_WAIT_TIMEOUT 999999999L /* * Safely kill process by checking that the process is the right one by matching * process start time. * * The algorithm: * * 1. Check that the process has the same start time as stored in lock. If it * is not, return, as we know for sure this is a wrong process. (This step * is an optimization to avoid sending SIGSTOP/SIGCONT to wrong processes). * * 2. Send SIGSTOP to the process. * * 3. Poll process state until it is stopped. * * Now the process is stopped, so we may examine it and not be afraid that it * will exit and another one with the same PID will appear. * * 4. Check that the process has the same start time as provided. * If it is, send the signal to the process. * * 5. Send SIGCONT to the process, so it may continue. * * * Returns 0 on success, -1 on error. Error code is signalled through errno. * * ERRORS * * EINVAL An invalid signal was specified. * EPERM The process does not have permission to send the signal. * ESRCH The pid does not exist or its start time does not match expected one. */ static int SafeKill(pid_t pid, time_t expected_start_time, int signal) { /* Preliminary check: in case process start time is different already, we * are sure we don't want to STOP it or kill it. */ time_t pid_start_time = GetProcessStartTime(pid); if (pid_start_time != expected_start_time) { errno = ESRCH; return -1; } /* Now to avoid race conditions we need to stop process so it won't exit * voluntarily while we are working on it */ if (kill(pid, SIGSTOP) < 0) { return -1; } if (!ProcessWaitUntilStopped(pid, STOP_WAIT_TIMEOUT)) { /* Ensure the process is started again in case of timeout or error, so * we don't leave SIGSTOP'ed processes around on overloaded or * misconfigured machine */ kill(pid, SIGCONT); errno = ESRCH; return -1; } /* Here process has stopped, so we may interrogate it without race conditions */ pid_start_time = GetProcessStartTime(pid); if (pid_start_time != expected_start_time) { /* This is a wrong process, let it continue */ kill(pid, SIGCONT); errno = ESRCH; return -1; } /* We've got a right process, signal it and let it continue */ int ret = kill(pid, signal); int saved_errno = errno; /* * We don't check return value of SIGCONT, as the proces may have been * terminated already by previous kill. Moreover, what would we do with the * return code? */ kill(pid, SIGCONT); errno = saved_errno; return ret; } static int Kill(pid_t pid, time_t process_start_time, int signal) { if (process_start_time == PROCESS_START_TIME_UNKNOWN) { /* We don't know when the process has started, do a plain kill(2) */ return kill(pid, signal); } else { return SafeKill(pid, process_start_time, signal); } } int GracefulTerminate(pid_t pid, time_t process_start_time) { if (Kill(pid, process_start_time, SIGINT) < 0) { return errno == ESRCH; } if (ProcessWaitUntilExited(pid, STOP_WAIT_TIMEOUT)) { return true; } if (Kill(pid, process_start_time, SIGTERM) < 0) { return errno == ESRCH; } if (ProcessWaitUntilExited(pid, STOP_WAIT_TIMEOUT)) { return true; } if (Kill(pid, process_start_time, SIGKILL) < 0) { return errno == ESRCH; } return true; } cfengine-3.6.2/libpromises/process_solaris.c0000664000175100017510000000527212243421446020734 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include /* * procfs.h is not 64-bit off_t clean, but the only affected structure is * priovec, which we don't use. Hence we may work around #error in sys/procfs.h * by lying that we are not compiling with large file support (while we do). */ #define _FILE_OFFSET_BITS 32 #include static bool GetProcessPsinfo(pid_t pid, psinfo_t *psinfo) { char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "/proc/%d/psinfo", (int)pid); int fd = open(filename, O_RDONLY); if (fd == -1) { return false; } int res = FullRead(fd, psinfo, sizeof(*psinfo)); close(fd); return res == sizeof(*psinfo); } time_t GetProcessStartTime(pid_t pid) { psinfo_t psinfo; if (GetProcessPsinfo(pid, &psinfo)) { return psinfo.pr_start.tv_sec; } else { return PROCESS_START_TIME_UNKNOWN; } } static bool GetProcessPstatus(pid_t pid, pstatus_t *pstatus) { char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "/proc/%d/status", (int)pid); int fd = open(filename, O_RDONLY); if (fd == -1) { return false; } int res = FullRead(fd, pstatus, sizeof(*pstatus)); close(fd); return res == sizeof(*pstatus); } ProcessState GetProcessState(pid_t pid) { pstatus_t pstatus; if (GetProcessPstatus(pid, &pstatus)) { if ((pstatus.pr_lwp.pr_flags & PR_STOPPED) && (pstatus.pr_lwp.pr_why == PR_SIGNALLED)) { return PROCESS_STATE_STOPPED; } else { return PROCESS_STATE_RUNNING; } } else { return PROCESS_STATE_DOES_NOT_EXIST; } } cfengine-3.6.2/libpromises/dbm_api.c0000644000175100017510000002767712353264455017137 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* ThreadLock */ #include #include #include #include #include #include static int DBPathLock(const char *filename); static void DBPathUnLock(int fd); static void DBPathMoveBroken(const char *filename); struct DBHandle_ { /* Filename of database file */ char *filename; /* Actual database-specific data */ DBPriv *priv; int refcount; /* This lock protects initialization of .priv element, and .refcount manipulation */ pthread_mutex_t lock; }; struct DBCursor_ { DBCursorPriv *cursor; }; /******************************************************************************/ /* * This lock protects on-demand initialization of db_handles[i].lock and * db_handles[i].name. */ static pthread_mutex_t db_handles_lock = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; /* GLOBAL_T */ static DBHandle db_handles[dbid_max] = { { 0 } }; /* GLOBAL_X */ static pthread_once_t db_shutdown_once = PTHREAD_ONCE_INIT; /* GLOBAL_T */ /******************************************************************************/ static const char *const DB_PATHS[] = { [dbid_classes] = "cf_classes", [dbid_variables] = "state/cf_variables", [dbid_performance] = "performance", [dbid_checksums] = "checksum_digests", [dbid_filestats] = "stats", [dbid_changes] = "state/cf_changes", [dbid_observations] = "state/cf_observations", [dbid_state] = "state/cf_state", [dbid_lastseen] = "cf_lastseen", [dbid_audit] = "cf_audit", [dbid_locks] = "state/cf_lock", [dbid_history] = "state/history", [dbid_measure] = "state/nova_measures", [dbid_static] = "state/nova_static", [dbid_scalars] = "state/nova_pscalar", [dbid_windows_registry] = "mswin", [dbid_cache] = "nova_cache", [dbid_license] = "nova_track", [dbid_value] = "nova_value", [dbid_agent_execution] = "nova_agent_execution", [dbid_bundles] = "bundles", }; /******************************************************************************/ char *DBIdToPath(const char *workdir, dbid id) { assert(DB_PATHS[id] != NULL); char *filename; if (xasprintf(&filename, "%s/%s.%s", workdir, DB_PATHS[id], DBPrivGetFileExtension()) == -1) { ProgrammingError("Unable to construct database filename for file %s", DB_PATHS[id]); } char *native_filename = MapNameCopy(filename); free(filename); return native_filename; } static DBHandle *DBHandleGet(int id) { assert(id >= 0 && id < dbid_max); ThreadLock(&db_handles_lock); if (db_handles[id].filename == NULL) { db_handles[id].filename = DBIdToPath(CFWORKDIR, id); /* Initialize mutexes as error-checking ones. */ pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); pthread_mutex_init(&db_handles[id].lock, &attr); pthread_mutexattr_destroy(&attr); } ThreadUnlock(&db_handles_lock); return &db_handles[id]; } /** * @brief Wait for all users of all databases to close the DBs. Then acquire * the mutexes *AND KEEP THEM LOCKED* so that no background thread can open * any database. So make sure you exit soon... * * @warning This is usually register with atexit(), however you have to make * sure no other DB-cleaning exit hook was registered before, so that this is * called last. **/ void CloseAllDBExit() { ThreadLock(&db_handles_lock); for (int i = 0; i < dbid_max; i++) { if (db_handles[i].filename) { /* Wait until all DB users are served, or a threshold is reached */ int count = 0; ThreadLock(&db_handles[i].lock); while (db_handles[i].refcount > 0 && count < 1000) { ThreadUnlock(&db_handles[i].lock); struct timespec sleeptime = { .tv_sec = 0, .tv_nsec = 10000000 /* 10 ms */ }; nanosleep(&sleeptime, NULL); count++; ThreadLock(&db_handles[i].lock); } /* Keep mutex locked. */ /* If we exited because of timeout make sure we Log() it. */ if (db_handles[i].refcount != 0) { Log(LOG_LEVEL_ERR, "Database %s refcount is still not zero (%d), forcing CloseDB()!", db_handles[i].filename, db_handles[i].refcount); DBPrivCloseDB(db_handles[i].priv); } else /* TODO: can we clean this up unconditionally ? */ { free(db_handles[i].filename); db_handles[i].filename = NULL; } } } } static void RegisterShutdownHandler(void) { RegisterAtExitFunction(&CloseAllDBExit); } bool OpenDB(DBHandle **dbp, dbid id) { DBHandle *handle = DBHandleGet(id); ThreadLock(&handle->lock); if (handle->refcount == 0) { int lock_fd = DBPathLock(handle->filename); if(lock_fd != -1) { handle->priv = DBPrivOpenDB(handle->filename, id); if (handle->priv == DB_PRIV_DATABASE_BROKEN) { DBPathMoveBroken(handle->filename); handle->priv = DBPrivOpenDB(handle->filename, id); if (handle->priv == DB_PRIV_DATABASE_BROKEN) { handle->priv = NULL; } } DBPathUnLock(lock_fd); } if (handle->priv) { if (!DBMigrate(handle, id)) { DBPrivCloseDB(handle->priv); handle->priv = NULL; } } } if (handle->priv) { handle->refcount++; *dbp = handle; /* Only register shutdown handler if any database was opened * correctly. Otherwise this shutdown caller may be called too early, * and shutdown handler installed by the database library may end up * being called before CloseAllDB function */ pthread_once(&db_shutdown_once, RegisterShutdownHandler); } else { *dbp = NULL; } ThreadUnlock(&handle->lock); return *dbp != NULL; } void CloseDB(DBHandle *handle) { ThreadLock(&handle->lock); DBPrivCommit(handle->priv); if (handle->refcount < 1) { Log(LOG_LEVEL_ERR, "Trying to close database %s which is not open", handle->filename); } else if (--handle->refcount == 0) { DBPrivCloseDB(handle->priv); } ThreadUnlock(&handle->lock); } /*****************************************************************************/ bool ReadComplexKeyDB(DBHandle *handle, const char *key, int key_size, void *dest, int dest_size) { return DBPrivRead(handle->priv, key, key_size, dest, dest_size); } bool WriteComplexKeyDB(DBHandle *handle, const char *key, int key_size, const void *value, int value_size) { return DBPrivWrite(handle->priv, key, key_size, value, value_size); } bool DeleteComplexKeyDB(DBHandle *handle, const char *key, int key_size) { return DBPrivDelete(handle->priv, key, key_size); } bool ReadDB(DBHandle *handle, const char *key, void *dest, int destSz) { return DBPrivRead(handle->priv, key, strlen(key) + 1, dest, destSz); } bool WriteDB(DBHandle *handle, const char *key, const void *src, int srcSz) { return DBPrivWrite(handle->priv, key, strlen(key) + 1, src, srcSz); } bool HasKeyDB(DBHandle *handle, const char *key, int key_size) { return DBPrivHasKey(handle->priv, key, key_size); } int ValueSizeDB(DBHandle *handle, const char *key, int key_size) { return DBPrivGetValueSize(handle->priv, key, key_size); } bool DeleteDB(DBHandle *handle, const char *key) { return DBPrivDelete(handle->priv, key, strlen(key) + 1); } bool NewDBCursor(DBHandle *handle, DBCursor **cursor) { DBCursorPriv *priv = DBPrivOpenCursor(handle->priv); if (!priv) { return false; } *cursor = xcalloc(1, sizeof(DBCursor)); (*cursor)->cursor = priv; return true; } bool NextDB(DBCursor *cursor, char **key, int *ksize, void **value, int *vsize) { return DBPrivAdvanceCursor(cursor->cursor, (void **)key, ksize, value, vsize); } bool DBCursorDeleteEntry(DBCursor *cursor) { return DBPrivDeleteCursorEntry(cursor->cursor); } bool DBCursorWriteEntry(DBCursor *cursor, const void *value, int value_size) { return DBPrivWriteCursorEntry(cursor->cursor, value, value_size); } bool DeleteDBCursor(DBCursor *cursor) { DBPrivCloseCursor(cursor->cursor); free(cursor); return true; } static int DBPathLock(const char *filename) { char *filename_lock; if (xasprintf(&filename_lock, "%s.lock", filename) == -1) { ProgrammingError("Unable to construct lock database filename for file %s", filename); } int fd = open(filename_lock, O_CREAT | O_RDWR, 0666); if(fd == -1) { Log(LOG_LEVEL_ERR, "Unable to open database lock file '%s'. (flock: %s)", filename_lock, GetErrorStr()); free(filename_lock); return -1; } if (ExclusiveLockFile(fd) == -1) { Log(LOG_LEVEL_ERR, "Unable to lock database lock file '%s'. (fcntl(F_SETLK): %s)", filename_lock, GetErrorStr()); free(filename_lock); close(fd); return -1; } free(filename_lock); return fd; } static void DBPathUnLock(int fd) { if(ExclusiveUnlockFile(fd) != 0) { Log(LOG_LEVEL_ERR, "Could not close db lock-file. (close: %s)", GetErrorStr()); } } static void DBPathMoveBroken(const char *filename) { char *filename_broken; if (xasprintf(&filename_broken, "%s.broken", filename) == -1) { ProgrammingError("Unable to construct broken database filename for file '%s'", filename); } if(rename(filename, filename_broken) != 0) { Log(LOG_LEVEL_ERR, "Failed moving broken db out of the way"); } free(filename_broken); } StringMap *LoadDatabaseToStringMap(dbid database_id) { CF_DB *db_conn = NULL; CF_DBC *db_cursor = NULL; char *key = NULL; void *value = NULL; int key_size = 0; int value_size = 0; if (!OpenDB(&db_conn, database_id)) { return NULL; } if (!NewDBCursor(db_conn, &db_cursor)) { Log(LOG_LEVEL_ERR, "Unable to scan db"); CloseDB(db_conn); return NULL; } StringMap *db_map = StringMapNew(); while (NextDB(db_cursor, &key, &key_size, &value, &value_size)) { if (!key) { continue; } if (!value) { Log(LOG_LEVEL_VERBOSE, "Invalid entry (key='%s') in database.", key); continue; } void *val = xcalloc(1, value_size); val = memcpy(val, value, value_size); StringMapInsert(db_map, xstrdup(key), val); } DeleteDBCursor(db_cursor); CloseDB(db_conn); return db_map; } cfengine-3.6.2/libpromises/processes_select.h0000644000175100017510000000241012316547775021100 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROCESSES_SELECT_H #define CFENGINE_PROCESSES_SELECT_H #include int LoadProcessTable(Item **procdata); Item *SelectProcesses(const Item *processes, const char *process_name, ProcessSelect a, bool attrselect); bool IsProcessNameRunning(char *procNameRegex); #endif cfengine-3.6.2/libpromises/addr_lib.c0000644000175100017510000003471012352022221017244 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #define CF_ADDRSIZE 128 /* Match two IP strings - with : or . in hex or decimal s1 is the test string, and s2 is the reference e.g. FuzzySetMatch("128.39.74.10/23","128.39.75.56") == 0 Returns 0 on match. */ /* TODO rename to AddrSubnetMatch() */ int FuzzySetMatch(const char *s1, const char *s2) { short isCIDR = false, isrange = false, isv6 = false, isv4 = false; char address[CF_ADDRSIZE]; if (strcmp(s1, s2) == 0) { return 0; } if (strstr(s1, "/") != 0) { isCIDR = true; } if (strstr(s1, "-") != 0) { isrange = true; } if (strstr(s1, ".") != 0) { isv4 = true; } if (strstr(s1, ":") != 0) { isv6 = true; } if (strstr(s2, ".") != 0) { isv4 = true; } if (strstr(s2, ":") != 0) { isv6 = true; } if (isv4 && isv6) { /* This is just wrong */ return -1; } if (isCIDR && isrange) { Log(LOG_LEVEL_ERR, "Cannot mix CIDR notation with xxx-yyy range notation '%s'", s1); return -1; } if (!(isv6 || isv4)) { Log(LOG_LEVEL_ERR, "Not a valid address range - or not a fully qualified name '%s'", s1); return -1; } if (!(isrange || isCIDR)) { if (strlen(s2) > strlen(s1)) { if (*(s2 + strlen(s1)) != '.') { return -1; // Because xxx.1 should not match xxx.12 in the same octet } } return strncmp(s1, s2, strlen(s1)); /* do partial string match */ } if (isv4) { if (isCIDR) { struct sockaddr_in addr1, addr2; unsigned long mask; address[0] = '\0'; int ret = sscanf(s1, "%16[^/]/%lu", address, &mask); if (ret != 2 || mask > 32) { Log(LOG_LEVEL_ERR, "Invalid IPv4 CIDR: %s", s1); return -1; } else if (mask == 0) { return 0; /* /0 CIDR matches everything */ } inet_pton(AF_INET, address, &addr1.sin_addr); inet_pton(AF_INET, s2, &addr2.sin_addr); unsigned long a1 = htonl(addr1.sin_addr.s_addr); unsigned long a2 = htonl(addr2.sin_addr.s_addr); unsigned long shift = 32 - mask; assert(shift < 32); /* Undefined behaviour if 32 */ a1 = a1 >> shift; a2 = a2 >> shift; if (a1 == a2) { return 0; } else { return -1; } } else { long i, from = -1, to = -1, cmp = -1; char buffer1[CF_MAX_IP_LEN], buffer2[CF_MAX_IP_LEN]; const char *sp1 = s1; const char *sp2 = s2; for (i = 0; i < 4; i++) { buffer1[0] = '\0'; sscanf(sp1, "%[^.]", buffer1); if (strlen(buffer1) == 0) { break; } sp1 += strlen(buffer1) + 1; sscanf(sp2, "%[^.]", buffer2); sp2 += strlen(buffer2) + 1; if (strstr(buffer1, "-")) { sscanf(buffer1, "%ld-%ld", &from, &to); sscanf(buffer2, "%ld", &cmp); if ((from < 0) || (to < 0)) { Log(LOG_LEVEL_DEBUG, "Couldn't read range"); return -1; } if ((from > cmp) || (cmp > to)) { Log(LOG_LEVEL_DEBUG, "Out of range %ld > %ld > %ld, range '%s'", from, cmp, to, buffer2); return -1; } } else { sscanf(buffer1, "%ld", &from); sscanf(buffer2, "%ld", &cmp); if (from != cmp) { Log(LOG_LEVEL_DEBUG, "Unequal"); return -1; } } Log(LOG_LEVEL_DEBUG, "Matched octet '%s' with '%s'", buffer1, buffer2); } Log(LOG_LEVEL_DEBUG, "Matched IP range"); return 0; } } if (isv6) { int i; if (isCIDR) { int blocks; struct sockaddr_in6 addr1 = {0}; struct sockaddr_in6 addr2 = {0}; unsigned long mask; address[0] = '\0'; int ret = sscanf(s1, "%40[^/]/%lu", address, &mask); if (ret != 2 || mask > 128) { Log(LOG_LEVEL_ERR, "Invalid IPv6 CIDR: %s", s1); return -1; } blocks = mask / 8; if (mask % 8 != 0) { Log(LOG_LEVEL_ERR, "Cannot handle ipv6 masks which are not 8 bit multiples (fix me)"); return -1; } addr1.sin6_family = AF_INET6; inet_pton(AF_INET6, address, &addr1.sin6_addr); addr2.sin6_family = AF_INET6; inet_pton(AF_INET6, s2, &addr2.sin6_addr); for (i = 0; i < blocks; i++) /* blocks < 16 */ { if (addr1.sin6_addr.s6_addr[i] != addr2.sin6_addr.s6_addr[i]) { return -1; } } return 0; } else { long i, from = -1, to = -1, cmp = -1; char buffer1[CF_MAX_IP_LEN], buffer2[CF_MAX_IP_LEN]; const char *sp1 = s1; const char *sp2 = s2; for (i = 0; i < 8; i++) { sscanf(sp1, "%[^:]", buffer1); sp1 += strlen(buffer1) + 1; sscanf(sp2, "%[^:]", buffer2); sp2 += strlen(buffer2) + 1; if (strstr(buffer1, "-")) { sscanf(buffer1, "%lx-%lx", &from, &to); sscanf(buffer2, "%lx", &cmp); if (from < 0 || to < 0) { return -1; } if ((from >= cmp) || (cmp > to)) { Log(LOG_LEVEL_DEBUG, "%lx < %lx < %lx", from, cmp, to); return -1; } } else { sscanf(buffer1, "%ld", &from); sscanf(buffer2, "%ld", &cmp); if (from != cmp) { return -1; } } } return 0; } } return -1; } bool FuzzyHostParse(const char *arg2) { long start = -1, end = -1; int n; n = sscanf(arg2, "%ld-%ld", &start, &end); if (n != 2) { Log(LOG_LEVEL_ERR, "HostRange syntax error: second arg should have X-Y format where X and Y are decimal numbers"); return false; } return true; } int FuzzyHostMatch(const char *arg0, const char *arg1, const char *refhost) { char *sp, refbase[CF_MAXVARSIZE]; long cmp = -1, start = -1, end = -1; char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE]; strlcpy(refbase, refhost, CF_MAXVARSIZE); sp = refbase + strlen(refbase) - 1; while (isdigit((int) *sp)) { sp--; } sp++; sscanf(sp, "%ld", &cmp); *sp = '\0'; if (cmp < 0) { return 1; } if (strlen(refbase) == 0) { return 1; } sscanf(arg1, "%ld-%ld", &start, &end); if ((cmp < start) || (cmp > end)) { return 1; } strlcpy(buf1, refbase, CF_BUFSIZE); strlcpy(buf2, arg0, CF_BUFSIZE); ToLowerStrInplace(buf1); ToLowerStrInplace(buf2); if (strcmp(buf1, buf2) != 0) { return 1; } return 0; } bool FuzzyMatchParse(const char *s) { short isCIDR = false, isrange = false, isv6 = false, isv4 = false, isADDR = false; char address[CF_ADDRSIZE]; int mask, count = 0; for (const char *sp = s; *sp != '\0'; sp++) /* Is this an address or hostname */ { if (!isxdigit((int) *sp)) { isADDR = false; break; } if (*sp == ':') /* Catches any ipv6 address */ { isADDR = true; break; } if (isdigit((int) *sp)) /* catch non-ipv4 address - no more than 3 digits */ { count++; if (count > 3) { isADDR = false; break; } } else { count = 0; } } if (!isADDR) { return true; } if (strstr(s, "/") != 0) { isCIDR = true; } if (strstr(s, "-") != 0) { isrange = true; } if (strstr(s, ".") != 0) { isv4 = true; } if (strstr(s, ":") != 0) { isv6 = true; } if (isv4 && isv6) { Log(LOG_LEVEL_ERR, "Mixture of IPv6 and IPv4 addresses"); return false; } if (isCIDR && isrange) { Log(LOG_LEVEL_ERR, "Cannot mix CIDR notation with xx-yy range notation"); return false; } if (isv4 && isCIDR) { if (strlen(s) > 4 + 3 * 4 + 1 + 2) /* xxx.yyy.zzz.mmm/cc */ { Log(LOG_LEVEL_ERR, "IPv4 address looks too long"); return false; } address[0] = '\0'; mask = 0; sscanf(s, "%16[^/]/%d", address, &mask); if (mask < 8) { Log(LOG_LEVEL_ERR, "Mask value %d in '%s' is less than 8", mask, s); return false; } if (mask > 30) { Log(LOG_LEVEL_ERR, "Mask value %d in '%s' is silly (> 30)", mask, s); return false; } } if (isv4 && isrange) { long i, from = -1, to = -1; char buffer1[CF_MAX_IP_LEN]; const char *sp1 = s; for (i = 0; i < 4; i++) { buffer1[0] = '\0'; sscanf(sp1, "%[^.]", buffer1); sp1 += strlen(buffer1) + 1; if (strstr(buffer1, "-")) { sscanf(buffer1, "%ld-%ld", &from, &to); if ((from < 0) || (to < 0)) { Log(LOG_LEVEL_ERR, "Error in IP range - looks like address, or bad hostname"); return false; } if (to < from) { Log(LOG_LEVEL_ERR, "Bad IP range"); return false; } } } } if (isv6 && isCIDR) { char address[CF_ADDRSIZE]; int mask; if (strlen(s) < 20) { Log(LOG_LEVEL_ERR, "IPv6 address looks too short"); return false; } if (strlen(s) > 42) { Log(LOG_LEVEL_ERR, "IPv6 address looks too long"); return false; } address[0] = '\0'; mask = 0; sscanf(s, "%40[^/]/%d", address, &mask); if (mask % 8 != 0) { Log(LOG_LEVEL_ERR, "Cannot handle ipv6 masks which are not 8 bit multiples (fix me)"); return false; } if (mask > 15) { Log(LOG_LEVEL_ERR, "IPv6 CIDR mask is too large"); return false; } } return true; } /* FIXME: handle 127.0.0.2, 127.255.255.254, ::1, * 0000:0000:0000:0000:0000:0000:0000:0001, 0:00:000:0000:000:00:0:1, 0::1 and * other variants */ bool IsLoopbackAddress(const char *address) { if(strcmp(address, "localhost") == 0) { return true; } if(strcmp(address, "127.0.0.1") == 0) { return true; } return false; } bool IsInterfaceAddress(const Item *ip_addresses, const char *adr) /* Does this address belong to a local interface */ { for (const Item *ip = ip_addresses; ip != NULL; ip = ip->next) { if (strncasecmp(adr, ip->name, strlen(adr)) == 0) { Log(LOG_LEVEL_DEBUG, "Identifying '%s' as one of my interfaces", adr); return true; } } Log(LOG_LEVEL_DEBUG, "'%s' is not one of my interfaces", adr); return false; } /** * Parses "hostname:port" or "[hostname]:port", where hostname may also be * IPv4 or IPv6 address string. * * @param hostname will point to the hostname, or NULL if no or empty hostname * @param port will point to the port, or NULL if no or empty port * @WARNING modifies #s to '\0' terminate hostname if followed by port. */ void ParseHostPort(char *s, char **hostname, char **port) { char *h, *p; /* hostname, port temporaries */ if (s[0] == '[') /* IPv6 form: [address]:port */ { h = s + 1; p = strchr(h, ']'); if (p != NULL) { *p = '\0'; /* '\0'-terminate hostname */ p = (p[1] == ':') ? p+2 : NULL; } } else /* normal form: address:port */ { h = s; p = strchr(h, ':'); if (p != NULL) { *p = '\0'; /* '\0'-terminate hostname */ p++; } } *hostname = (h[0] != '\0') ? h : NULL; *port = (p != NULL && p[0] != '\0') ? p : NULL; } cfengine-3.6.2/libpromises/promises.h0000644000175100017510000000245012332665147017370 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROMISES_H #define CFENGINE_PROMISES_H #include #include #include Promise *DeRefCopyPromise(EvalContext *ctx, const Promise *pp); Promise *ExpandDeRefPromise(EvalContext *ctx, const Promise *pp, bool *excluded); void PromiseRef(LogLevel level, const Promise *pp); #endif cfengine-3.6.2/libpromises/signals.c0000664000175100017510000001175212406603052017156 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include static bool PENDING_TERMINATION = false; /* GLOBAL_X */ /********************************************************************/ bool IsPendingTermination(void) { return PENDING_TERMINATION; } /********************************************************************/ static int SIGNAL_PIPE[2] = { -1, -1 }; /* GLOBAL_C */ static void CloseSignalPipe(void) { int c = 2; while (c > 0) { c--; if (SIGNAL_PIPE[c] >= 0) { close(SIGNAL_PIPE[c]); SIGNAL_PIPE[c] = -1; } } } /** * Make a pipe that can be used to flag that a signal has arrived. * Using a pipe avoids race conditions, since it saves its values until emptied. * Use GetSignalPipe() to get the pipe. * Note that we use a real socket as the pipe, because Windows only supports * using select() with real sockets. This means also using send() and recv() * instead of write() and read(). */ void MakeSignalPipe(void) { if (socketpair(AF_UNIX, SOCK_STREAM, 0, SIGNAL_PIPE) != 0) { Log(LOG_LEVEL_CRIT, "Could not create internal communication pipe. Cannot continue. (socketpair: '%s')", GetErrorStr()); exit(EXIT_FAILURE); } for (int c = 0; c < 2; c++) { #ifndef __MINGW32__ if (fcntl(SIGNAL_PIPE[c], F_SETFL, O_NONBLOCK) != 0) { Log(LOG_LEVEL_CRIT, "Could not create internal communication pipe. Cannot continue. (fcntl: '%s')", GetErrorStr()); exit(EXIT_FAILURE); } #else // __MINGW32__ u_long enable = 1; if (ioctlsocket(SIGNAL_PIPE[c], FIONBIO, &enable) != 0) { Log(LOG_LEVEL_CRIT, "Could not create internal communication pipe. Cannot continue. (ioctlsocket: '%s')", GetErrorStr()); exit(EXIT_FAILURE); } #endif // __MINGW32__ } atexit(&CloseSignalPipe); } /** * Gets the signal pipe, which is non-blocking. * Each byte read corresponds to one arrived signal. * Note: Use recv() to read from the pipe, not read(). */ int GetSignalPipe(void) { return SIGNAL_PIPE[0]; } static void SignalNotify(int signum) { unsigned char sig = (unsigned char)signum; if (SIGNAL_PIPE[1] >= 0) { // send() is async-safe, according to POSIX. if (send(SIGNAL_PIPE[1], &sig, 1, 0) < 0) { // These signal contention. Everything else is an error. if (errno != EAGAIN #ifndef __MINGW32__ && errno != EWOULDBLOCK #endif ) { // This is not async safe, but if we get in here there's something really weird // going on. Log(LOG_LEVEL_CRIT, "Could not write to signal pipe. Unsafe to continue. (write: '%s')", GetErrorStr()); _exit(EXIT_FAILURE); } } } } void HandleSignalsForAgent(int signum) { switch (signum) { case SIGTERM: case SIGINT: /* TODO don't exit from the signal handler, just set a flag. Reason is * that all the atexit() hooks we register are not reentrant. */ exit(0); case SIGUSR1: LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case SIGUSR2: LogSetGlobalLevel(LOG_LEVEL_NOTICE); break; default: /* No action */ break; } SignalNotify(signum); /* Reset the signal handler */ signal(signum, HandleSignalsForAgent); } /********************************************************************/ void HandleSignalsForDaemon(int signum) { switch (signum) { case SIGTERM: case SIGINT: case SIGHUP: case SIGSEGV: case SIGKILL: PENDING_TERMINATION = true; break; case SIGUSR1: LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case SIGUSR2: LogSetGlobalLevel(LOG_LEVEL_NOTICE); break; case SIGPIPE: default: /* No action */ break; } SignalNotify(signum); /* Reset the signal handler */ signal(signum, HandleSignalsForDaemon); } cfengine-3.6.2/libpromises/iteration.c0000664000175100017510000003074312411001073017504 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include struct PromiseIterator_ { bool started; Seq *vars; Seq *var_states; }; static bool EndOfIterationInternal(const PromiseIterator *iter, size_t index); static bool NullIteratorsInternal(PromiseIterator *iter, size_t index); static void RlistAppendContainerPrimitive(Rlist **list, const JsonElement *primitive) { assert(JsonGetElementType(primitive) == JSON_ELEMENT_TYPE_PRIMITIVE); switch (JsonGetPrimitiveType(primitive)) { case JSON_PRIMITIVE_TYPE_BOOL: RlistAppendScalar(list, JsonPrimitiveGetAsBool(primitive) ? "true" : "false"); break; case JSON_PRIMITIVE_TYPE_INTEGER: { char *str = StringFromLong(JsonPrimitiveGetAsInteger(primitive)); RlistAppendScalar(list, str); free(str); } break; case JSON_PRIMITIVE_TYPE_REAL: { char *str = StringFromDouble(JsonPrimitiveGetAsReal(primitive)); RlistAppendScalar(list, str); free(str); } break; case JSON_PRIMITIVE_TYPE_STRING: RlistAppendScalar(list, JsonPrimitiveGetAsString(primitive)); break; case JSON_PRIMITIVE_TYPE_NULL: break; } } static Rlist *ContainerToRlist(const JsonElement *container) { Rlist *list = NULL; switch (JsonGetElementType(container)) { case JSON_ELEMENT_TYPE_PRIMITIVE: RlistAppendContainerPrimitive(&list, container); break; case JSON_ELEMENT_TYPE_CONTAINER: { JsonIterator iter = JsonIteratorInit(container); const JsonElement *child; while (NULL != (child = JsonIteratorNextValue(&iter))) { if (JsonGetElementType(child) == JSON_ELEMENT_TYPE_PRIMITIVE) { RlistAppendContainerPrimitive(&list, child); } } } break; } return list; } static void AppendIterationVariable(PromiseIterator *iter, CfAssoc *new_var) { SeqAppend(iter->vars, new_var); Rlist *list_value = RvalRlistValue(new_var->rval); Rlist *state = new_var->rval.item = RlistPrepend(&list_value, CF_NULL_VALUE, RVAL_TYPE_SCALAR); RlistAppendScalar(&list_value, CF_NULL_VALUE); while (state && state->val.type == RVAL_TYPE_SCALAR && strcmp(RlistScalarValue(state), CF_NULL_VALUE) == 0) { state = state->next; } SeqAppend(iter->var_states, state); } PromiseIterator *PromiseIteratorNew(EvalContext *ctx, const Promise *pp, const Rlist *lists, const Rlist *containers) { PromiseIterator *iter = xmalloc(sizeof(PromiseIterator)); iter->vars = SeqNew(RlistLen(lists), DeleteAssoc); iter->var_states = SeqNew(RlistLen(lists), NULL); iter->started = false; for (const Rlist *rp = lists; rp != NULL; rp = rp->next) { VarRef *ref = VarRefParseFromBundle(RlistScalarValue(rp), PromiseGetBundle(pp)); DataType dtype = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &dtype); if (!value) { Log(LOG_LEVEL_ERR, "Couldn't locate variable '%s' apparently in '%s'", RlistScalarValue(rp), PromiseGetBundle(pp)->name); VarRefDestroy(ref); continue; } VarRefDestroy(ref); CfAssoc *new_var = NewAssoc(RlistScalarValue(rp), (Rval) { (void *)value, DataTypeToRvalType(dtype) }, dtype); AppendIterationVariable(iter, new_var); } for (const Rlist *rp = containers; rp; rp = rp->next) { VarRef *ref = VarRefParseFromBundle(RlistScalarValue(rp), PromiseGetBundle(pp)); DataType dtype = CF_DATA_TYPE_NONE; const JsonElement *value = EvalContextVariableGet(ctx, ref, &dtype); if (!value) { Log(LOG_LEVEL_ERR, "Couldn't locate variable '%s' apparently in '%s'", RlistScalarValue(rp), PromiseGetBundle(pp)->name); VarRefDestroy(ref); continue; } VarRefDestroy(ref); assert(dtype == CF_DATA_TYPE_CONTAINER); /* Mimics NewAssoc() but bypassing extra copying of ->rval: */ CfAssoc *new_var = xmalloc(sizeof(CfAssoc)); new_var->lval = xstrdup(RlistScalarValue(rp)); new_var->rval = (Rval) { ContainerToRlist(value), RVAL_TYPE_LIST }; new_var->dtype = CF_DATA_TYPE_STRING_LIST; AppendIterationVariable(iter, new_var); } // We now have a control list of list-variables, with internal state in state_ptr return iter; } void PromiseIteratorDestroy(PromiseIterator *iter) { if (iter) { for (size_t i = 0; i < SeqLength(iter->vars); i++) { CfAssoc *var = SeqAt(iter->vars, i); void *state = SeqAt(iter->var_states, i); if (var->rval.type == RVAL_TYPE_CONTAINER) { free(state); } } SeqDestroy(iter->var_states); SeqDestroy(iter->vars); free(iter); } } /*****************************************************************************/ static bool NullIteratorsInternal(PromiseIterator *iter, size_t index) { if (index >= SeqLength(iter->vars)) { return false; } for (size_t i = index; i < SeqLength(iter->var_states); i++) { const CfAssoc *var = SeqAt(iter->vars, i); if (var->rval.type == RVAL_TYPE_LIST) { const Rlist *state = SeqAt(iter->var_states, i); if (state) { switch (state->val.type) { case RVAL_TYPE_SCALAR: if (strcmp(RlistScalarValue(state), CF_NULL_VALUE) == 0) { return true; } break; case RVAL_TYPE_FNCALL: if (strcmp(RlistFnCallValue(state)->name, CF_NULL_VALUE) == 0) { return true; } break; default: ProgrammingError("Unexpected rval type %d in iterator", state->val.type); } } } } return false; } static void VariableStateIncrement(PromiseIterator *iter, size_t index) { assert(index < SeqLength(iter->var_states)); CfAssoc *var = SeqAt(iter->vars, index); switch (var->rval.type) { case RVAL_TYPE_LIST: { Rlist *state = SeqAt(iter->var_states, index); SeqSet(iter->var_states, index, state->next); } break; default: ProgrammingError("Unhandled case in switch"); } } static void VariableStateReset(PromiseIterator *iter, size_t index) { assert(index < SeqLength(iter->var_states)); CfAssoc *var = SeqAt(iter->vars, index); switch (var->rval.type) { case RVAL_TYPE_LIST: { Rlist *state = RvalRlistValue(var->rval); state = state->next; SeqSet(iter->var_states, index, state); } break; default: ProgrammingError("Unhandled case in switch"); } } static bool VariableStateHasMore(const PromiseIterator *iter, size_t index) { CfAssoc *var = SeqAt(iter->vars, index); switch (var->rval.type) { case RVAL_TYPE_LIST: { const Rlist *state = SeqAt(iter->var_states, index); return state && state->next; } case RVAL_TYPE_CONTAINER: case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: case RVAL_TYPE_SCALAR: ProgrammingError("Unhandled case in switch %d", var->rval.type); } return false; } static bool IncrementIterationContextInternal(PromiseIterator *iter, size_t index) { if (index == SeqLength(iter->vars)) { return false; } // Go ahead and increment if (!VariableStateHasMore(iter, index)) { /* This wheel has come to full revolution, so move to next */ if (index < (SeqLength(iter->vars) - 1)) { /* Increment next wheel */ if (IncrementIterationContextInternal(iter, index + 1)) { /* Not at end yet, so reset this wheel */ VariableStateReset(iter, index); return true; } else { /* Reached last variable wheel - pass up */ return false; } } else { /* Reached last variable wheel - waiting for end detection */ return false; } } else { /* Update the current wheel */ VariableStateIncrement(iter, index); while (NullIteratorsInternal(iter, index)) { if (IncrementIterationContextInternal(iter, index + 1)) { // If we are at the end of this wheel, we need to shift to next wheel VariableStateReset(iter, index); return true; } else { // Otherwise increment this wheel VariableStateIncrement(iter, index); break; } } if (EndOfIterationInternal(iter, index)) { return false; } return true; } } bool PromiseIteratorNext(PromiseIterator *iter_ctx) { iter_ctx->started = true; return IncrementIterationContextInternal(iter_ctx, 0); } static bool EndOfIterationInternal(const PromiseIterator *iter, size_t index) { if (index >= SeqLength(iter->vars)) { return true; } for (size_t i = index; i < SeqLength(iter->var_states); i++) { CfAssoc *var = SeqAt(iter->vars, i); switch (var->rval.type) { case RVAL_TYPE_LIST: { const Rlist *state = SeqAt(iter->var_states, i); if (!state) { continue; } else if (state->next) { return false; } } break; default: ProgrammingError("Unhandled value in switch %d", var->rval.type); } } return true; } bool PromiseIteratorHasMore(const PromiseIterator *iter) { if (SeqLength(iter->vars) > 0) { return !EndOfIterationInternal(iter, 0); } else { return !iter->started; } } void PromiseIteratorUpdateVariable(EvalContext *ctx, const PromiseIterator *iter) { for (size_t i = 0; i < SeqLength(iter->vars); i++) { CfAssoc *iter_var = SeqAt(iter->vars, i); const Rlist *state = SeqAt(iter->var_states, i); if (!state || state->val.type == RVAL_TYPE_FNCALL) { continue; } assert(state->val.type == RVAL_TYPE_SCALAR); switch (iter_var->dtype) { case CF_DATA_TYPE_STRING_LIST: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_STRING, "source=promise"); break; case CF_DATA_TYPE_INT_LIST: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_INT, "source=promise"); break; case CF_DATA_TYPE_REAL_LIST: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_REAL, "source=promise"); break; default: assert(false); break; } } } cfengine-3.6.2/libpromises/lastseen.c0000664000175100017510000004074012400110676017332 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #ifdef LMDB #include #endif void UpdateLastSawHost(const char *hostkey, const char *address, bool incoming, time_t timestamp); /* * Lastseen database schema (version 1): * * Version entry * * key: "version\0" * value: "1\0" * * "Quality of connection" entries * * key: q (direction: 'i' for incoming, 'o' for outgoing) * value: struct KeyHostSeen * * "Hostkey" entries * * key: k ("MD5-ffffefefeefef..." or "SHA-abacabaca...") * value:
    (IPv4 or IPv6) * * "Address", or reverse, entries (auxiliary) * * key: a
    (IPv6 or IPv6) * value: * * * * Schema version 0 mapped direction + hostkey to address + quality of * connection. This approach had a number of drawbacks: * - There were two potentially conflicting addresses for given hostkey. * - There was no way to quickly lookup hostkey by address. * - Address update required traversal of the whole database. * * In order to overcome these limitations, new schema normalized (in relational * algebra sense) the data relations. */ /*****************************************************************************/ /** * @brief Same as LastSaw() but the digest parameter is the hash as a * "SHA=..." string, to avoid converting twice. */ void LastSaw1(const char *ipaddress, const char *hashstr, LastSeenRole role) { const char *mapip = MapAddress(ipaddress); UpdateLastSawHost(hashstr, mapip, role == LAST_SEEN_ROLE_ACCEPT, time(NULL)); } void LastSaw(const char *ipaddress, const char *digest, LastSeenRole role) { char databuf[CF_HOSTKEY_STRING_SIZE]; if (strlen(ipaddress) == 0) { Log(LOG_LEVEL_INFO, "LastSeen registry for empty IP with role %d", role); return; } HashPrintSafe(databuf, sizeof(databuf), digest, CF_DEFAULT_DIGEST, true); const char *mapip = MapAddress(ipaddress); UpdateLastSawHost(databuf, mapip, role == LAST_SEEN_ROLE_ACCEPT, time(NULL)); } /*****************************************************************************/ void UpdateLastSawHost(const char *hostkey, const char *address, bool incoming, time_t timestamp) { DBHandle *db = NULL; if (!OpenDB(&db, dbid_lastseen)) { Log(LOG_LEVEL_ERR, "Unable to open last seen db"); return; } /* Update quality-of-connection entry */ char quality_key[CF_BUFSIZE]; snprintf(quality_key, CF_BUFSIZE, "q%c%s", incoming ? 'i' : 'o', hostkey); KeyHostSeen newq = { .lastseen = timestamp }; KeyHostSeen q; if (ReadDB(db, quality_key, &q, sizeof(q))) { newq.Q = QAverage(q.Q, newq.lastseen - q.lastseen, 0.4); } else { /* FIXME: more meaningful default value? */ newq.Q = QDefinite(0); } WriteDB(db, quality_key, &newq, sizeof(newq)); /* Update forward mapping */ char hostkey_key[CF_BUFSIZE]; snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey); WriteDB(db, hostkey_key, address, strlen(address) + 1); /* Update reverse mapping */ char address_key[CF_BUFSIZE]; snprintf(address_key, CF_BUFSIZE, "a%s", address); WriteDB(db, address_key, hostkey, strlen(hostkey) + 1); CloseDB(db); } /*****************************************************************************/ static bool Address2HostkeyInDB(DBHandle *db, const char *address, char *result) { char address_key[CF_BUFSIZE]; char hostkey[CF_BUFSIZE]; /* Address key: "a" + address */ snprintf(address_key, CF_BUFSIZE, "a%s", address); if (!ReadDB(db, address_key, &hostkey, sizeof(hostkey))) { return false; } char hostkey_key[CF_BUFSIZE]; char back_address[CF_BUFSIZE]; /* Hostkey key: "k" + hostkey */ snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey); if (!ReadDB(db, hostkey_key, &back_address, sizeof(back_address))) { /* There is no key -> address mapping. Remove reverse mapping and return failure. */ DeleteDB(db, address_key); return false; } if (strcmp(address, back_address) != 0) { /* Forward and reverse mappings do not match. Remove reverse mapping and return failure. */ DeleteDB(db, address_key); return false; } strlcpy(result, hostkey, CF_BUFSIZE); return true; } /*****************************************************************************/ bool Address2Hostkey(char *dst, size_t dst_size, const char *address) { dst[0] = '\0'; if ((strcmp(address, "127.0.0.1") == 0) || (strcmp(address, "::1") == 0) || (strcmp(address, VIPADDRESS) == 0)) { if (PUBKEY) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); HashPrintSafe(dst, dst_size, digest, CF_DEFAULT_DIGEST, true); return true; } else { return false; } } DBHandle *db; if (!OpenDB(&db, dbid_lastseen)) { return false; } bool ret = Address2HostkeyInDB(db, address, dst); CloseDB(db); return ret; } /** * @brief detects whether input is a host/ip name or a key digest * * @param[in] key digest (SHA/MD5 format) or free host name string * (character '=' is optional but recommended) * @retval true if a key digest, false otherwise */ static bool IsDigestOrHost(const char *input) { if (strncmp(input, "SHA=", 3) == 0) { return true; } else if (strncmp(input, "MD5=", 3) == 0) { return true; } else { return false; } } /** * @brief check whether the lastseen DB is coherent or not * * A DB is coherent mainly if all the entries are valid and if there is * a strict one-to-one correspondance between hosts and key digests * (whether in MD5 or SHA1 format). * * @retval true if the lastseen DB is coherent, false otherwise */ bool IsLastSeenCoherent(void) { DBHandle *db; DBCursor *cursor; bool res = true; if (!OpenDB(&db, dbid_lastseen)) { Log(LOG_LEVEL_ERR, "Unable to open lastseen database"); return false; } if (!NewDBCursor(db, &cursor)) { Log(LOG_LEVEL_ERR, "Unable to create lastseen database cursor"); CloseDB(db); return false; } char *key; void *value; int ksize, vsize; Item *qkeys=NULL; Item *akeys=NULL; Item *kkeys=NULL; Item *ahosts=NULL; Item *khosts=NULL; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { if (key[0] != 'k' && key[0] != 'q' && key[0] != 'a' ) { continue; } if (key[0] == 'q' ) { if (strncmp(key,"qiSHA=",5)==0 || strncmp(key,"qoSHA=",5)==0 || strncmp(key,"qiMD5=",5)==0 || strncmp(key,"qoMD5=",5)==0) { if (IsItemIn(qkeys, key+2)==false) { PrependItem(&qkeys, key+2, NULL); } } } if (key[0] == 'k' ) { if (strncmp(key, "kSHA=", 4)==0 || strncmp(key, "kMD5=", 4)==0) { if (IsItemIn(kkeys, key+1)==false) { PrependItem(&kkeys, key+1, NULL); } if (IsItemIn(khosts, value)==false) { PrependItem(&khosts, value, NULL); } } } if (key[0] == 'a' ) { if (IsItemIn(ahosts, key+1)==false) { PrependItem(&ahosts, key+1, NULL); } if (IsItemIn(akeys, value)==false) { PrependItem(&akeys, value, NULL); } } } DeleteDBCursor(cursor); CloseDB(db); if (ListsCompare(ahosts, khosts) == false) { res = false; goto clean; } if (ListsCompare(akeys, kkeys) == false) { res = false; goto clean; } clean: DeleteItemList(qkeys); DeleteItemList(akeys); DeleteItemList(kkeys); DeleteItemList(ahosts); DeleteItemList(khosts); return res; } /** * @brief removes all traces of host 'ip' from lastseen DB * * @param[in] ip : either in (SHA/MD5 format) * @param[in,out] digest: return corresponding digest of input host. * If NULL, return nothing * @retval true if entry was deleted, false otherwise */ bool DeleteIpFromLastSeen(const char *ip, char *digest) { DBHandle *db; bool res = false; if (!OpenDB(&db, dbid_lastseen)) { Log(LOG_LEVEL_ERR, "Unable to open lastseen database"); return false; } char bufkey[CF_BUFSIZE + 1]; char bufhost[CF_BUFSIZE + 1]; strcpy(bufhost, "a"); strlcat(bufhost, ip, CF_BUFSIZE); char key[CF_BUFSIZE]; if (ReadDB(db, bufhost, &key, sizeof(key)) == true) { strcpy(bufkey, "k"); strlcat(bufkey, key, CF_BUFSIZE); if (HasKeyDB(db, bufkey, strlen(bufkey) + 1) == false) { res = false; goto clean; } else { if (digest != NULL) { strcpy(digest, bufkey + 1); } DeleteDB(db, bufkey); DeleteDB(db, bufhost); res = true; } } else { res = false; goto clean; } strcpy(bufkey, "qi"); strlcat(bufkey, key, CF_BUFSIZE); DeleteDB(db, bufkey); strcpy(bufkey, "qo"); strlcat(bufkey, key, CF_BUFSIZE); DeleteDB(db, bufkey); clean: CloseDB(db); return res; } /** * @brief removes all traces of key digest 'key' from lastseen DB * * @param[in] key : either in (SHA/MD5 format) * @param[in,out] ip : return the key corresponding host. * If NULL, return nothing * @retval true if entry was deleted, false otherwise */ bool DeleteDigestFromLastSeen(const char *key, char *ip) { DBHandle *db; bool res = false; if (!OpenDB(&db, dbid_lastseen)) { Log(LOG_LEVEL_ERR, "Unable to open lastseen database"); return false; } char bufkey[CF_BUFSIZE + 1]; char bufhost[CF_BUFSIZE + 1]; strcpy(bufkey, "k"); strlcat(bufkey, key, CF_BUFSIZE); char host[CF_BUFSIZE]; if (ReadDB(db, bufkey, &host, sizeof(host)) == true) { strcpy(bufhost, "a"); strlcat(bufhost, host, CF_BUFSIZE); if (HasKeyDB(db, bufhost, strlen(bufhost) + 1) == false) { res = false; goto clean; } else { if (ip != NULL) { strcpy(ip, host); } DeleteDB(db, bufhost); DeleteDB(db, bufkey); res = true; } } else { res = false; goto clean; } strcpy(bufkey, "qi"); strlcat(bufkey, key, CF_BUFSIZE); DeleteDB(db, bufkey); strcpy(bufkey, "qo"); strlcat(bufkey, key, CF_BUFSIZE); DeleteDB(db, bufkey); clean: CloseDB(db); return res; } /*****************************************************************************/ bool ScanLastSeenQuality(LastSeenQualityCallback callback, void *ctx) { StringMap *lastseen_db = LoadDatabaseToStringMap(dbid_lastseen); if (!lastseen_db) { return false; } MapIterator it = MapIteratorInit(lastseen_db->impl); MapKeyValue *item; Seq *hostkeys = SeqNew(100, free); while ((item = MapIteratorNext(&it)) != NULL) { char *key = item->key; /* Only look for "keyhost" entries */ if (key[0] != 'k') { continue; } SeqAppend(hostkeys, xstrdup(key + 1)); } for (int i = 0; i < SeqLength(hostkeys); ++i) { const char *hostkey = SeqAt(hostkeys, i); char keyhost_key[CF_BUFSIZE]; snprintf(keyhost_key, CF_BUFSIZE, "k%s", hostkey); char *address = NULL; address = (char*)StringMapGet(lastseen_db, keyhost_key); if (!address) { Log(LOG_LEVEL_ERR, "Failed to read address for key '%s'.", hostkey); continue; } char incoming_key[CF_BUFSIZE]; snprintf(incoming_key, CF_BUFSIZE, "qi%s", hostkey); KeyHostSeen *incoming = NULL; incoming = (KeyHostSeen*)StringMapGet(lastseen_db, incoming_key); if (incoming) { if (!(*callback)(hostkey, address, true, incoming, ctx)) { break; } } char outgoing_key[CF_BUFSIZE]; snprintf(outgoing_key, CF_BUFSIZE, "qo%s", hostkey); KeyHostSeen *outgoing = NULL; outgoing = (KeyHostSeen*)StringMapGet(lastseen_db, outgoing_key); if (outgoing) { if (!(*callback)(hostkey, address, false, outgoing, ctx)) { break; } } } StringMapDestroy(lastseen_db); SeqDestroy(hostkeys); return true; } /*****************************************************************************/ int LastSeenHostKeyCount(void) { CF_DB *dbp; CF_DBC *dbcp; QPoint entry; char *key; void *value; int ksize, vsize; int count = 0; if (OpenDB(&dbp, dbid_lastseen)) { memset(&entry, 0, sizeof(entry)); if (NewDBCursor(dbp, &dbcp)) { while (NextDB(dbcp, &key, &ksize, &value, &vsize)) { /* Only look for valid "hostkey" entries */ if ((key[0] != 'k') || (value == NULL)) { continue; } count++; } DeleteDBCursor(dbcp); } CloseDB(dbp); } return count; } /** * @brief removes all traces of entry 'input' from lastseen DB * * @param[in] key digest (SHA/MD5 format) or free host name string * @param[in] must_be_coherent. false : delete if lastseen is incoherent, * true : don't if lastseen is incoherent * @param[out] equivalent. If input is a host, return its corresponding * digest. If input is a digest, return its * corresponding host. CAN BE NULL! If equivalent * is null, it stays as NULL * @retval 0 if entry was deleted, <>0 otherwise */ int RemoveKeysFromLastSeen(const char *input, bool must_be_coherent, char *equivalent) { bool is_coherent = false; if (must_be_coherent == true) { is_coherent = IsLastSeenCoherent(); if (is_coherent == false) { Log(LOG_LEVEL_ERR, "Lastseen database is incoherent. Will not proceed to remove entries from it."); return 254; } } bool is_digest; is_digest = IsDigestOrHost(input); if (is_digest == true) { Log(LOG_LEVEL_VERBOSE, "Removing digest '%s' from lastseen database\n", input); if (DeleteDigestFromLastSeen(input, equivalent) == false) { Log(LOG_LEVEL_ERR, "Unable to remove digest from lastseen database."); return 252; } } else { Log(LOG_LEVEL_VERBOSE, "Removing host '%s' from lastseen database\n", input); if (DeleteIpFromLastSeen(input, equivalent) == false) { Log(LOG_LEVEL_ERR, "Unable to remove host from lastseen database."); return 253; } } Log(LOG_LEVEL_INFO, "Removed corresponding entries from lastseen database."); return 0; } cfengine-3.6.2/libpromises/enterprise_extension.sed0000664000175100017510000000025712411001073022310 0ustar00a10038a1003800000000000000s,.*BEGIN_MARKER.*,/* #### THIS FILE WAS AUTOGENERATED FROM extension_template.* #### */,; s/xEXTENSIONx/ENTERPRISE/g; s/XextensionX/enterprise/g; s/xExtensionX/Enterprise/g; cfengine-3.6.2/libpromises/mod_environ.h0000664000175100017510000000217312243421446020043 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_ENVIRON_H #define CFENGINE_MOD_ENVIRON_H #include extern const PromiseTypeSyntax CF_ENVIRONMENT_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/locks.h0000644000175100017510000000334412316547775016655 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LOCKS_H #define CFENGINE_LOCKS_H #include time_t FindLockTime(const char *name); CfLock AcquireLock(EvalContext *ctx, const char *operand, const char *host, time_t now, TransactionContext tc, const Promise *pp, bool ignoreProcesses); void YieldCurrentLock(CfLock lock); void GetLockName(char *lockname, const char *locktype, const char *base, const Rlist *params); void PurgeLocks(void); void BackupLockDatabase(void); void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type); int WriteLock(const char *lock); CF_DB *OpenLock(void); void CloseLock(CF_DB *dbp); void WaitForCriticalSection(const char *section_id); void ReleaseCriticalSection(const char *section_id); #endif cfengine-3.6.2/libpromises/mod_exec.h0000664000175100017510000000215612243421446017310 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_EXEC_H #define CFENGINE_MOD_EXEC_H #include extern const PromiseTypeSyntax CF_EXEC_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/exec_tools.h0000664000175100017510000000253112243421446017666 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_EXEC_TOOLS_H #define CFENGINE_EXEC_TOOLS_H #include #include int IsExecutable(const char *file); bool ShellCommandReturnsZero(const char *command, ShellType shell); bool GetExecOutput(const char *command, char *buffer, ShellType shell); void ActAsDaemon(); char **ArgSplitCommand(const char *comm); void ArgFree(char **args); #endif cfengine-3.6.2/libpromises/granules.c0000664000175100017510000000433512400110676017334 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include char *GenTimeKey(time_t now) { struct tm tm; static char buf[18]; /* GLOBAL_R, no initialization needed */ gmtime_r(&now, &tm); xsnprintf(buf, sizeof(buf), "%3.3s:Hr%02d:Min%02d_%02d", DAY_TEXT[tm.tm_wday ? (tm.tm_wday - 1) : 6], tm.tm_hour, tm.tm_min / 5 * 5, ((tm.tm_min + 5) / 5 * 5) % 60); return buf; } int GetTimeSlot(time_t here_and_now) { return ((here_and_now - (4 * 24 * 60 * 60)) % SECONDS_PER_WEEK) / (long)CF_MEASURE_INTERVAL; } int GetShiftSlot(time_t t) { return UnsignedModulus((t - CF_MONDAY_MORNING), SECONDS_PER_WEEK) / CF_SHIFT_INTERVAL; } time_t GetShiftSlotStart(time_t t) { return (t - (t % SECONDS_PER_SHIFT)); } time_t MeasurementSlotStart(time_t t) { return (t - t % (time_t)CF_MEASURE_INTERVAL); } time_t MeasurementSlotTime(size_t slot, size_t num_slots, time_t now) { assert(slot <= num_slots); size_t start_slot = GetTimeSlot(now); size_t distance = 0; if (slot <= start_slot) { distance = start_slot - slot; } else { distance = start_slot + (num_slots - slot - 1); } time_t start_time = MeasurementSlotStart(now); return start_time - (distance * CF_MEASURE_INTERVAL); } cfengine-3.6.2/libpromises/var_expressions.c0000664000175100017510000003112112400110676020737 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include static size_t VarRefHash(const VarRef *ref) { unsigned int h = 0; if (VarRefIsQualified(ref)) { if (ref->ns) { for (int i = 0; ref->ns[i] != '\0'; i++) { h += ref->ns[i]; h += (h << 10); h ^= (h >> 6); } } else { h = 1195645448; // hash of "default" } int len = strlen(ref->scope); for (int i = 0; i < len; i++) { h += ref->scope[i]; h += (h << 10); h ^= (h >> 6); } } for (int i = 0; ref->lval[i] != '\0'; i++) { h += ref->lval[i]; h += (h << 10); h ^= (h >> 6); } for (size_t k = 0; k < ref->num_indices; k++) { for (int i = 0; ref->indices[k][i] != '\0'; i++) { h += ref->indices[k][i]; h += (h << 10); h ^= (h >> 6); } } h += (h << 3); h ^= (h >> 11); h += (h << 15); return (h & (INT_MAX - 1)); } VarRef VarRefConst(const char *ns, const char *scope, const char *lval) { VarRef ref; ref.ns = (char *)ns; ref.scope = (char *)scope; ref.lval = (char *)lval; ref.num_indices = 0; ref.indices = NULL; ref.hash = VarRefHash(&ref); return ref; } VarRef *VarRefCopy(const VarRef *ref) { VarRef *copy = xmalloc(sizeof(VarRef)); copy->hash = ref->hash; copy->ns = ref->ns ? xstrdup(ref->ns) : NULL; copy->scope = ref->scope ? xstrdup(ref->scope) : NULL; copy->lval = ref->lval ? xstrdup(ref->lval) : NULL; copy->num_indices = ref->num_indices; if (ref->num_indices > 0) { copy->indices = xmalloc(ref->num_indices * sizeof(char*)); for (size_t i = 0; i < ref->num_indices; i++) { copy->indices[i] = xstrdup(ref->indices[i]); } } else { copy->indices = NULL; } return copy; } VarRef *VarRefCopyLocalized(const VarRef *ref) { VarRef *copy = xmalloc(sizeof(VarRef)); copy->ns = NULL; copy->scope = xstrdup("this"); copy->lval = ref->lval ? xstrdup(ref->lval) : NULL; copy->num_indices = ref->num_indices; if (ref->num_indices > 0) { copy->indices = xmalloc(ref->num_indices * sizeof(char*)); for (size_t i = 0; i < ref->num_indices; i++) { copy->indices[i] = xstrdup(ref->indices[i]); } } else { copy->indices = NULL; } copy->hash = VarRefHash(copy); return copy; } VarRef *VarRefCopyIndexless(const VarRef *ref) { VarRef *copy = xmalloc(sizeof(VarRef)); copy->ns = ref->ns ? xstrdup(ref->ns) : NULL; copy->scope = ref->scope ? xstrdup(ref->scope) : NULL; copy->lval = ref->lval ? xstrdup(ref->lval) : NULL; copy->num_indices = 0; copy->indices = NULL; copy->hash = VarRefHash(copy); return copy; } static bool IndexBracketsBalance(const char *var_string) { int count = 0; for (const char *c = var_string; *c != '\0'; c++) { if (*c == '[') { count++; } if (*c == ']') { count--; } } return count == 0; } static size_t IndexCount(const char *var_string) { size_t count = 0; size_t level = 0; for (const char *c = var_string; *c != '\0'; c++) { if (*c == '[') { if (level == 0) { count++; } level++; } if (*c == ']') { level--; } } return count; } VarRef *VarRefParseFromNamespaceAndScope(const char *qualified_name, const char *_ns, const char *_scope, char ns_separator, char scope_separator) { assert(qualified_name); char *ns = NULL; const char *indices_start = strchr(qualified_name, '['); const char *scope_start = strchr(qualified_name, ns_separator); if (scope_start && (!indices_start || scope_start < indices_start)) { ns = xstrndup(qualified_name, scope_start - qualified_name); scope_start++; } else { scope_start = qualified_name; } char *scope = NULL; const char *lval_start = strchr(scope_start, scope_separator); if (lval_start && (!indices_start || lval_start < indices_start)) { lval_start++; scope = xstrndup(scope_start, lval_start - scope_start - 1); } else { lval_start = scope_start; } char *lval = NULL; char **indices = NULL; size_t num_indices = 0; if (indices_start) { indices_start++; lval = xstrndup(lval_start, indices_start - lval_start - 1); if (!IndexBracketsBalance(indices_start - 1)) { Log(LOG_LEVEL_ERR, "Broken variable expression, index brackets do not balance, in '%s'", qualified_name); } else { num_indices = IndexCount(indices_start - 1); indices = xmalloc(num_indices * sizeof(char *)); Buffer *buf = BufferNew(); size_t cur_index = 0; size_t open_count = 1; for (const char *c = indices_start; *c != '\0'; c++) { if (*c == '[') { if (open_count++ == 0) { cur_index++; continue; } } else if (*c == ']') { if (open_count-- == 1) { indices[cur_index] = xstrdup(BufferData(buf)); BufferClear(buf); continue; } } BufferAppend(buf, c, sizeof(char)); } BufferDestroy(buf); } } else { lval = xstrdup(lval_start); } assert(lval); if (!scope && !_scope) { assert(ns == NULL && "A variable missing a scope should not have a namespace"); } if (scope) { if (SpecialScopeFromString(scope) != SPECIAL_SCOPE_NONE) { _ns = NULL; } } else { if (!_scope) { assert(ns == NULL && "A variable missing a scope should not have a namespace"); } } VarRef *ref = xmalloc(sizeof(VarRef)); ref->ns = ns ? ns : (_ns ? xstrdup(_ns) : NULL); ref->scope = scope ? scope : (_scope ? xstrdup(_scope) : NULL); ref->lval = lval; ref->indices = indices; ref->num_indices = num_indices; ref->hash = VarRefHash(ref); return ref; } VarRef *VarRefParse(const char *var_ref_string) { return VarRefParseFromNamespaceAndScope(var_ref_string, NULL, NULL, CF_NS, '.'); } VarRef *VarRefParseFromScope(const char *var_ref_string, const char *scope) { if (!scope) { return VarRefParseFromNamespaceAndScope(var_ref_string, NULL, NULL, CF_NS, '.'); } const char *scope_start = strchr(scope, CF_NS); if (scope_start) { char *ns = xstrndup(scope, scope_start - scope); VarRef *ref = VarRefParseFromNamespaceAndScope(var_ref_string, ns, scope_start + 1, CF_NS, '.'); free(ns); return ref; } else { return VarRefParseFromNamespaceAndScope(var_ref_string, NULL, scope, CF_NS, '.'); } } VarRef *VarRefParseFromBundle(const char *var_ref_string, const Bundle *bundle) { if (bundle) { return VarRefParseFromNamespaceAndScope(var_ref_string, bundle->ns, bundle->name, CF_NS, '.'); } else { return VarRefParse(var_ref_string); } } void VarRefDestroy(VarRef *ref) { if (ref) { free(ref->ns); free(ref->scope); free(ref->lval); if (ref->num_indices > 0) { for (int i = 0; i < ref->num_indices; ++i) { free(ref->indices[i]); } free(ref->indices); } free(ref); } } char *VarRefToString(const VarRef *ref, bool qualified) { assert(ref->lval); Buffer *buf = BufferNew(); if (qualified && VarRefIsQualified(ref)) { const char *ns = ref->ns ? ref->ns : "default"; BufferAppend(buf, ns, strlen(ns)); BufferAppend(buf, ":", sizeof(char)); BufferAppend(buf, ref->scope, strlen(ref->scope)); BufferAppend(buf, ".", sizeof(char)); } BufferAppend(buf, ref->lval, strlen(ref->lval)); for (size_t i = 0; i < ref->num_indices; i++) { BufferAppend(buf, "[", sizeof(char)); BufferAppend(buf, ref->indices[i], strlen(ref->indices[i])); BufferAppend(buf, "]", sizeof(char)); } char *var_string = xstrdup(BufferData(buf)); BufferDestroy(buf); return var_string; } char *VarRefMangle(const VarRef *ref) { char *suffix = VarRefToString(ref, false); if (!ref->scope) { return suffix; } else { if (ref->ns) { char *mangled = StringFormat("%s*%s#%s", ref->ns, ref->scope, suffix); free(suffix); return mangled; } else { char *mangled = StringFormat("%s#%s", ref->scope, suffix); free(suffix); return mangled; } } } VarRef *VarRefDeMangle(const char *mangled_var_ref) { return VarRefParseFromNamespaceAndScope(mangled_var_ref, NULL, NULL, '*', '#'); } static bool VarRefIsMeta(VarRef *ref) { return StringEndsWith(ref->scope, "_meta"); } void VarRefSetMeta(VarRef *ref, bool enabled) { if (enabled) { if (!VarRefIsMeta(ref)) { char *tmp = StringConcatenate(2, ref->scope, "_meta"); free(ref->scope); ref->scope = tmp; } } else { if (VarRefIsMeta(ref)) { char *tmp = ref->scope; size_t len = strlen(ref->scope); memcpy(ref->scope, StringSubstring(ref->scope, len, 0, len - strlen("_meta")), len - strlen("_meta")); free(tmp); } } ref->hash = VarRefHash(ref); } bool VarRefIsQualified(const VarRef *ref) { return ref->scope != NULL; } void VarRefQualify(VarRef *ref, const char *ns, const char *scope) { assert(scope); free(ref->ns); ref->ns = NULL; free(ref->scope); ref->scope = NULL; ref->ns = ns ? xstrdup(ns) : NULL; ref->scope = xstrdup(scope); ref->hash = VarRefHash(ref); } void VarRefAddIndex(VarRef *ref, const char *index) { if (ref->indices) { assert(ref->num_indices > 0); ref->indices = xrealloc(ref->indices, sizeof(char *) * (ref->num_indices + 1)); } else { assert(ref->num_indices == 0); ref->indices = xmalloc(sizeof(char *)); } ref->indices[ref->num_indices] = xstrdup(index); ref->num_indices++; ref->hash = VarRefHash(ref); } int VarRefCompare(const VarRef *a, const VarRef *b) { int ret = strcmp(a->lval, b->lval); if (ret != 0) { return ret; } ret = strcmp(NULLStringToEmpty(a->scope), NULLStringToEmpty(b->scope)); if (ret != 0) { return ret; } const char *a_ns = a->ns ? a->ns : "default"; const char *b_ns = b->ns ? b->ns : "default"; ret = strcmp(a_ns, b_ns); if (ret != 0) { return ret; } ret = a->num_indices - b->num_indices; if (ret != 0) { return ret; } for (size_t i = 0; i < a->num_indices; i++) { ret = strcmp(a->indices[i], b->indices[i]); if (ret != 0) { return ret; } } return 0; } cfengine-3.6.2/libpromises/loading.h0000644000175100017510000000221712316547775017155 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LOADING_H #define CFENGINE_LOADING_H #include #include Policy *LoadPolicy(EvalContext *ctx, GenericAgentConfig *config); #endif cfengine-3.6.2/libpromises/mod_users.h0000644000175100017510000000216212352022221017505 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_USERS_H #define CFENGINE_MOD_USERS_H #include extern const PromiseTypeSyntax CF_USERS_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/cf3.extern.h0000664000175100017510000000417612411001073017473 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF3_EXTERN_H #define CFENGINE_CF3_EXTERN_H /* See variables in cf3globals.c and syntax.c */ extern bool LEGACY_OUTPUT; extern pid_t ALARM_PID; extern RSA *PRIVKEY, *PUBKEY; extern char BINDINTERFACE[CF_MAXVARSIZE]; extern time_t CONNTIMEOUT; extern char CFWORKDIR[CF_BUFSIZE]; extern time_t CFSTARTTIME; extern struct utsname VSYSNAME; extern char VIPADDRESS[CF_MAX_IP_LEN]; extern char VPREFIX[]; extern char VDOMAIN[CF_MAXVARSIZE]; extern char VFQNAME[]; extern char VUQNAME[]; extern bool DONTDO; extern bool MINUSF; extern int EDITFILESIZE; extern int VIFELAPSED; extern int VEXPIREAFTER; extern const char *const OBS[CF_OBSERVABLES][2]; extern bool FIPS_MODE; extern char POLICY_SERVER[CF_MAX_IP_LEN]; extern HashMethod CF_DEFAULT_DIGEST; extern int CF_DEFAULT_DIGEST_LEN; extern int CF_PERSISTENCE; extern const char *const CF_AGENTTYPES[]; extern int CFA_MAXTHREADS; extern AgentType THIS_AGENT_TYPE; extern int SHOWREPORTS; extern int LASTSEENEXPIREAFTER; extern const char *DEFAULT_COPYTYPE; extern Item *PROCESSTABLE; extern const char *const DAY_TEXT[]; extern const char *const MONTH_TEXT[]; extern const char *const SHIFT_TEXT[]; #endif cfengine-3.6.2/libpromises/enterprise_stubs.c0000664000175100017510000001676012400110676021121 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include /* * This module contains numeruous functions which don't use all their parameters * * Temporarily, in order to avoid cluttering output with thousands of warnings, * this module is excempted from producing warnings about unused function * parameters. * * Please remove this #pragma ASAP and provide ARG_UNUSED declarations for * unused parameters. */ #if defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-parameter" #endif extern int PR_KEPT; extern int PR_REPAIRED; extern int PR_NOTKEPT; ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, Nova_Initialize, EvalContext *, ctx) { } /* all agents: generic_agent.c */ ENTERPRISE_FUNC_0ARG_DEFINE_STUB(const char *, GetConsolePrefix) { return "cf3"; } /* all agents: sysinfo.c */ ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, EnterpriseContext, ARG_UNUSED EvalContext *, ctx) { } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, LoadSlowlyVaryingObservations, ARG_UNUSED EvalContext *, ctx) { Log(LOG_LEVEL_VERBOSE, "Extended system discovery is only available in CFEngine Enterprise"); } /* all agents: cfstream.c, expand.c, generic_agent.c */ ENTERPRISE_FUNC_1ARG_DEFINE_STUB(const char *, PromiseID, ARG_UNUSED const Promise *, pp) { return ""; } /* all agents: logging.c */ ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(void, NotePromiseCompliance, ARG_UNUSED const Promise *, pp, ARG_UNUSED PromiseState, state, ARG_UNUSED const char *, reason) { } ENTERPRISE_VOID_FUNC_4ARG_DEFINE_STUB(void, TrackValue, char *, date, double, kept, double, repaired, double, notkept) { } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, LogTotalCompliance, const char *, version, int, background_tasks) { double total = (double) (PR_KEPT + PR_NOTKEPT + PR_REPAIRED) / 100.0; char string[CF_BUFSIZE] = { 0 }; snprintf(string, CF_BUFSIZE, "Outcome of version %s (" CF_AGENTC "-%d): Promises observed to be kept %.2f%%, Promises repaired %.2f%%, Promises not repaired %.2f%%", version, background_tasks, (double) PR_KEPT / total, (double) PR_REPAIRED / total, (double) PR_NOTKEPT / total); Log(LOG_LEVEL_VERBOSE, "Logging total compliance, total '%s'", string); char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "%s/%s", GetLogDir(), CF_PROMISE_LOG); MapName(filename); FILE *fout = fopen(filename, "a"); if (fout == NULL) { Log(LOG_LEVEL_ERR, "In total compliance logging, could not open file '%s'. (fopen: %s)", filename, GetErrorStr()); } else { fprintf(fout, "%jd,%jd: %s\n", (intmax_t)CFSTARTTIME, (intmax_t)time(NULL), string); fclose(fout); } } /* network communication: cf-serverd.c, client_protocol.c, client_code.c, crypto.c */ ENTERPRISE_FUNC_1ARG_DEFINE_STUB(int, CfSessionKeySize, char, type) { return CF_BLOWFISHSIZE; } ENTERPRISE_FUNC_0ARG_DEFINE_STUB(char, CfEnterpriseOptions) { return 'c'; } ENTERPRISE_FUNC_1ARG_DEFINE_STUB(const EVP_CIPHER *, CfengineCipher, char, type) { return EVP_bf_cbc(); } /* cf-agent: evalfunction.c */ ENTERPRISE_FUNC_6ARG_DEFINE_STUB(char *, GetRemoteScalar, EvalContext *, ctx, char *, proto, char *, handle, char *, server, int, encrypted, char *, rcv) { Log(LOG_LEVEL_VERBOSE, "Access to server literals is only available in CFEngine Enterprise"); return ""; } ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(void, CacheUnreliableValue, char *, caller, char *, handle, char *, buffer) { Log(LOG_LEVEL_VERBOSE, "Value fault-tolerance only available in CFEngine Enterprise"); } ENTERPRISE_FUNC_3ARG_DEFINE_STUB(int, RetrieveUnreliableValue, char *, caller, char *, handle, char *, buffer) { Log(LOG_LEVEL_VERBOSE, "Value fault-tolerance only available in CFEngine Enterprise"); return false; } #if defined(__MINGW32__) ENTERPRISE_FUNC_4ARG_DEFINE_STUB(int, GetRegistryValue, char *, key, char *, name, char *, buf, int, bufSz) { return 0; } #endif ENTERPRISE_FUNC_6ARG_DEFINE_STUB(void *, CfLDAPValue, char *, uri, char *, dn, char *, filter, char *, name, char *, scope, char *, sec) { Log(LOG_LEVEL_ERR, "LDAP support only available in CFEngine Enterprise"); return NULL; } ENTERPRISE_FUNC_6ARG_DEFINE_STUB(void *, CfLDAPList, char *, uri, char *, dn, char *, filter, char *, name, char *, scope, char *, sec) { Log(LOG_LEVEL_ERR, "LDAP support only available in CFEngine Enterprise"); return NULL; } ENTERPRISE_FUNC_8ARG_DEFINE_STUB(void *, CfLDAPArray, EvalContext *, ctx, const Bundle *, caller, char *, array, char *, uri, char *, dn, char *, filter, char *, scope, char *, sec) { Log(LOG_LEVEL_ERR, "LDAP support only available in CFEngine Enterprise"); return NULL; } ENTERPRISE_FUNC_8ARG_DEFINE_STUB(void *, CfRegLDAP, EvalContext *, ctx, char *, uri, char *, dn, char *, filter, char *, name, char *, scope, char *, regex, char *, sec) { Log(LOG_LEVEL_ERR, "LDAP support only available in CFEngine Enterprise"); return NULL; } ENTERPRISE_FUNC_4ARG_DEFINE_STUB(bool, ListHostsWithClass, EvalContext *, ctx, Rlist **, return_list, char *, class_name, char *, return_format) { Log(LOG_LEVEL_ERR, "Host class counting is only available in CFEngine Enterprise"); return false; } /* cf-serverd: server_transform.c, cf-serverd.c */ ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, TranslatePath, char *, new, const char *, old) { strlcpy(new, old, CF_BUFSIZE); } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, ShowPromises, ARG_UNUSED const Seq *, bundles, ARG_UNUSED const Seq *, bodies) { } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, ShowPromise, ARG_UNUSED const Promise *, pp) { } ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(void, EvalContextLogPromiseIterationOutcome, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED const Promise *, pp, ARG_UNUSED PromiseResult, result) { } ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(void, GetObservable, ARG_UNUSED int, i, ARG_UNUSED char *, name, ARG_UNUSED char *, desc) { strcpy(name, OBS[i][0]); } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, SetMeasurementPromises, ARG_UNUSED Item **, classlist) { } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, CheckAndSetHAState, ARG_UNUSED const char *, workdir, ARG_UNUSED EvalContext *, ctx) { } ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(void, ReloadHAConfig) { } cfengine-3.6.2/libpromises/variable.h0000664000175100017510000000272612411001073017300 0ustar00a10038a1003800000000000000#ifndef CFENGINE_VARIABLE_H #define CFENGINE_VARIABLE_H #include #include typedef struct { VarRef *ref; Rval rval; DataType type; StringSet *tags; const Promise *promise; // The promise that set the present value } Variable; typedef struct VariableTable_ VariableTable; typedef struct VariableTableIterator_ VariableTableIterator; VariableTable *VariableTableNew(void); void VariableTableDestroy(VariableTable *table); bool VariableTablePut(VariableTable *table, const VarRef *ref, const Rval *rval, DataType type, const char *tags, const Promise *promise); Variable *VariableTableGet(const VariableTable *table, const VarRef *ref); bool VariableTableRemove(VariableTable *table, const VarRef *ref); size_t VariableTableCount(const VariableTable *table, const char *ns, const char *scope, const char *lval); bool VariableTableClear(VariableTable *table, const char *ns, const char *scope, const char *lval); VariableTableIterator *VariableTableIteratorNew(const VariableTable *table, const char *ns, const char *scope, const char *lval); VariableTableIterator *VariableTableIteratorNewFromVarRef(const VariableTable *table, const VarRef *ref); Variable *VariableTableIteratorNext(VariableTableIterator *iter); void VariableTableIteratorDestroy(VariableTableIterator *iter); VariableTable *VariableTableCopyLocalized(const VariableTable *table, const char *ns, const char *scope); #endif cfengine-3.6.2/libpromises/shared_lib.c0000644000175100017510000000345112352022221017576 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef __MINGW32__ #include #include #include #include void *shlib_open(const char *lib_name) { struct stat statbuf; if (stat(lib_name, &statbuf) == -1) { Log(LOG_LEVEL_DEBUG, "Could not open shared library: %s\n", GetErrorStr()); return NULL; } void * ret = dlopen(lib_name, RTLD_NOW); if (!ret) { Log(LOG_LEVEL_ERR, "Could not open shared library: %s\n", dlerror()); } return ret; } void *shlib_load(void *handle, const char *symbol_name) { static pthread_mutex_t dlsym_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; ThreadLock(&dlsym_mutex); void *ret = dlsym(handle, symbol_name); ThreadUnlock(&dlsym_mutex); return ret; } void shlib_close(void *handle) { dlclose(handle); } #endif // !__MINGW32__ cfengine-3.6.2/libpromises/timeout.h0000644000175100017510000000215612316547775017230 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_TIMEOUT_H #define CFENGINE_TIMEOUT_H void SetTimeOut(int timeout); void TimeOut(void); time_t SetReferenceTime(void); #endif cfengine-3.6.2/libpromises/dbm_migration.c0000644000175100017510000000416212352022221020315 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include extern const DBMigrationFunction dbm_migration_plan_bundles[]; extern const DBMigrationFunction dbm_migration_plan_lastseen[]; static const DBMigrationFunction *const dbm_migration_plans[dbid_max] = { [dbid_bundles] = dbm_migration_plan_bundles, [dbid_lastseen] = dbm_migration_plan_lastseen }; #ifdef LMDB bool DBMigrate(ARG_UNUSED DBHandle *db, ARG_UNUSED dbid id) { return true; } #else static size_t DBVersion(DBHandle *db) { char version[64]; if (ReadDB(db, "version", version, sizeof(version)) == false) { return 0; } else { return StringToLong(version); } } bool DBMigrate(DBHandle *db, dbid id) { const DBMigrationFunction *plan = dbm_migration_plans[id]; if (plan) { size_t step_version = 0; for (const DBMigrationFunction *step = plan; *step; step++, step_version++) { if (step_version == DBVersion(db)) { if (!(*step)(db)) { return false; } } } } return true; } #endif cfengine-3.6.2/libpromises/mod_storage.c0000664000175100017510000000702712243421446020025 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax volume_constraints[] = { ConstraintSyntaxNewBool("check_foreign", "true/false verify storage that is mounted from a foreign system on this host. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("freespace", "[0-9]+[MBkKgGmb%]", "Absolute or percentage minimum disk space that should be available before warning", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("sensible_size", CF_VALRANGE, "Minimum size in bytes that should be used on a sensible-looking storage device", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("sensible_count", CF_VALRANGE, "Minimum number of files that should be defined on a sensible-looking storage device", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("scan_arrivals", "true/false generate pseudo-periodic disk change arrival distribution. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax volume_body = BodySyntaxNew("volume", volume_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax mount_constraints[] = { ConstraintSyntaxNewBool("edit_fstab", "true/false add or remove entries to the file system table (\"fstab\"). Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("mount_type", "nfs,nfs2,nfs3,nfs4", "Protocol type of remote file system", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("mount_source", CF_ABSPATHRANGE, "Path of remote file system to mount", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("mount_server", "", "Hostname or IP or remote file system server", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("mount_options", "", "List of option strings to add to the file system table (\"fstab\")", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("unmount", "true/false unmount a previously mounted filesystem. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax mount_body = BodySyntaxNew("mount", mount_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax storage_constraints[] = { ConstraintSyntaxNewBody("mount", &mount_body, "Criteria for mounting foreign file systems", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("volume", &volume_body, "Criteria for monitoring/probing mounted volumes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_STORAGE_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "storage", storage_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/files_lib.c0000664000175100017510000004153412411001073017436 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include static Item *ROTATED = NULL; /* GLOBAL_X */ /*********************************************************************/ void PurgeItemList(Item **list, char *name) { Item *ip, *copy = NULL; struct stat sb; CopyList(©, *list); for (ip = copy; ip != NULL; ip = ip->next) { if (stat(ip->name, &sb) == -1) { Log(LOG_LEVEL_VERBOSE, "Purging file '%s' from '%s' list as it no longer exists", ip->name, name); DeleteItemLiteral(list, ip->name); } } DeleteItemList(copy); } bool FileWriteOver(char *filename, char *contents) { FILE *fp = safe_fopen(filename, "w"); if(fp == NULL) { return false; } int bytes_to_write = strlen(contents); size_t bytes_written = fwrite(contents, 1, bytes_to_write, fp); bool res = true; if(bytes_written != bytes_to_write) { res = false; } if(fclose(fp) != 0) { res = false; } return res; } /*********************************************************************/ /** * Like MakeParentDirectory, but honours warn-only and dry-run mode. * We should eventually migrate to this function to avoid making changes * in these scenarios. **/ int MakeParentDirectory2(char *parentandchild, int force, bool enforce_promise) { if(enforce_promise) { return MakeParentDirectory(parentandchild, force); } char *parent_dir = GetParentDirectoryCopy(parentandchild); if (parent_dir) { bool parent_exists = IsDir(parent_dir); free(parent_dir); return parent_exists; } else { return false; } } /** * Please consider using MakeParentDirectory2() instead. **/ bool MakeParentDirectory(const char *parentandchild, bool force) { char *spc, *sp; char currentpath[CF_BUFSIZE]; char pathbuf[CF_BUFSIZE]; struct stat statbuf; mode_t mask; int rootlen; char Path_File_Separator; #ifdef __APPLE__ /* Keeps track of if dealing w. resource fork */ int rsrcfork; rsrcfork = 0; char *tmpstr; #endif Log(LOG_LEVEL_DEBUG, "Trying to create a parent directory for '%s%s'", parentandchild, force ? " (force applied)" : ""); if (!IsAbsoluteFileName(parentandchild)) { Log(LOG_LEVEL_ERR, "Will not create directories for a relative filename '%s'. Has no invariant meaning", parentandchild); return false; } strlcpy(pathbuf, parentandchild, CF_BUFSIZE); /* local copy */ #ifdef __APPLE__ if (strstr(pathbuf, _PATH_RSRCFORKSPEC) != NULL) { rsrcfork = 1; } #endif /* skip link name */ /* This cast is necessary, as you can't have (char* -> char*) and (const char* -> const char*) functions in C */ sp = (char *) LastFileSeparator(pathbuf); if (sp == NULL) { sp = pathbuf; } *sp = '\0'; DeleteSlash(pathbuf); if (lstat(pathbuf, &statbuf) != -1) { if (S_ISLNK(statbuf.st_mode)) { Log(LOG_LEVEL_VERBOSE, "INFO: %s is a symbolic link, not a true directory!", pathbuf); } if (force) /* force in-the-way directories aside */ { struct stat dir; stat(pathbuf, &dir); if (!S_ISDIR(dir.st_mode)) /* if the dir exists - no problem */ { struct stat sbuf; if (DONTDO) { return true; } strcpy(currentpath, pathbuf); DeleteSlash(currentpath); strcat(currentpath, ".cf-moved"); Log(LOG_LEVEL_INFO, "Moving obstructing file/link %s to %s to make directory", pathbuf, currentpath); /* If cfagent, remove an obstructing backup object */ if (lstat(currentpath, &sbuf) != -1) { if (S_ISDIR(sbuf.st_mode)) { DeleteDirectoryTree(currentpath); } else { if (unlink(currentpath) == -1) { Log(LOG_LEVEL_INFO, "Couldn't remove file/link '%s' while trying to remove a backup. (unlink: %s)", currentpath, GetErrorStr()); } } } /* And then move the current object out of the way... */ if (rename(pathbuf, currentpath) == -1) { Log(LOG_LEVEL_INFO, "Warning: The object '%s' is not a directory. (rename: %s)", pathbuf, GetErrorStr()); return false; } } } else { if (!S_ISLNK(statbuf.st_mode) && !S_ISDIR(statbuf.st_mode)) { Log(LOG_LEVEL_INFO, "The object %s is not a directory. Cannot make a new directory without deleting it.", pathbuf); return false; } } } /* Now we can make a new directory .. */ currentpath[0] = '\0'; rootlen = RootDirLength(parentandchild); strncpy(currentpath, parentandchild, rootlen); for (sp = (char*) parentandchild + rootlen, spc = currentpath + rootlen; *sp != '\0'; sp++) { if (!IsFileSep(*sp) && *sp != '\0') { *spc = *sp; spc++; } else { Path_File_Separator = *sp; *spc = '\0'; if (strlen(currentpath) == 0) { } else if (stat(currentpath, &statbuf) == -1) { if (!DONTDO) { mask = umask(0); if (mkdir(currentpath, DEFAULTMODE) == -1) { Log(LOG_LEVEL_ERR, "Unable to make directories to '%s'. (mkdir: %s)", parentandchild, GetErrorStr()); umask(mask); return false; } umask(mask); } } else { if (!S_ISDIR(statbuf.st_mode)) { #ifdef __APPLE__ /* Ck if rsrc fork */ if (rsrcfork) { tmpstr = xmalloc(CF_BUFSIZE); strlcpy(tmpstr, currentpath, CF_BUFSIZE); strncat(tmpstr, _PATH_FORKSPECIFIER, CF_BUFSIZE); /* CFEngine removed terminating slashes */ DeleteSlash(tmpstr); if (strncmp(tmpstr, pathbuf, CF_BUFSIZE) == 0) { free(tmpstr); return true; } free(tmpstr); } #endif Log(LOG_LEVEL_ERR, "Cannot make %s - %s is not a directory! (use forcedirs=true)", pathbuf, currentpath); return false; } } /* *spc = FILE_SEPARATOR; */ *spc = Path_File_Separator; spc++; } } Log(LOG_LEVEL_DEBUG, "Directory for '%s' exists. Okay", parentandchild); return true; } int LoadFileAsItemList(Item **liststart, const char *file, EditDefaults edits) { { struct stat statbuf; if (stat(file, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "The proposed file '%s' could not be loaded. (stat: %s)", file, GetErrorStr()); return false; } if (edits.maxfilesize != 0 && statbuf.st_size > edits.maxfilesize) { Log(LOG_LEVEL_INFO, "File '%s' is bigger than the limit edit.max_file_size = %jd > %d bytes", file, (intmax_t) statbuf.st_size, edits.maxfilesize); return (false); } if (!S_ISREG(statbuf.st_mode)) { Log(LOG_LEVEL_INFO, "%s is not a plain file", file); return false; } } FILE *fp = safe_fopen(file, "rt"); if (!fp) { Log(LOG_LEVEL_INFO, "Couldn't read file '%s' for editing. (fopen: %s)", file, GetErrorStr()); return false; } Buffer *concat = BufferNew(); size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); bool result = true; for (;;) { ssize_t num_read = CfReadLine(&line, &line_size, fp); if (num_read == -1) { if (!feof(fp)) { Log(LOG_LEVEL_ERR, "Unable to read contents of '%s'. (fread: %s)", file, GetErrorStr()); result = false; } break; } if (edits.joinlines && *(line + strlen(line) - 1) == '\\') { *(line + strlen(line) - 1) = '\0'; BufferAppend(concat, line, num_read); } else { BufferAppend(concat, line, num_read); if (!feof(fp) || (BufferSize(concat) > 0)) { AppendItem(liststart, BufferData(concat), NULL); } } BufferClear(concat); } free(line); BufferDestroy(concat); fclose(fp); return result; } bool TraverseDirectoryTreeInternal(const char *base_path, const char *current_path, int (*callback)(const char *, const struct stat *, void *), void *user_data) { Dir *dirh = DirOpen(base_path); if (!dirh) { if (errno == ENOENT) { return true; } Log(LOG_LEVEL_INFO, "Unable to open directory '%s' during traversal of directory tree '%s' (opendir: %s)", current_path, base_path, GetErrorStr()); return false; } bool failed = false; for (const struct dirent *dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, "..")) { continue; } char sub_path[CF_BUFSIZE]; snprintf(sub_path, CF_BUFSIZE, "%s" FILE_SEPARATOR_STR "%s", current_path, dirp->d_name); struct stat lsb; if (lstat(sub_path, &lsb) == -1) { if (errno == ENOENT) { /* File disappeared on its own */ continue; } Log(LOG_LEVEL_VERBOSE, "Unable to stat file '%s' during traversal of directory tree '%s' (lstat: %s)", current_path, base_path, GetErrorStr()); failed = true; } else { if (S_ISDIR(lsb.st_mode)) { if (!TraverseDirectoryTreeInternal(base_path, sub_path, callback, user_data)) { failed = true; } } else { if (callback(sub_path, &lsb, user_data) == -1) { failed = true; } } } } DirClose(dirh); return !failed; } bool TraverseDirectoryTree(const char *path, int (*callback)(const char *, const struct stat *, void *), void *user_data) { return TraverseDirectoryTreeInternal(path, path, callback, user_data); } typedef struct { unsigned char buffer[1024]; const char **extensions_filter; EVP_MD_CTX *crypto_context; unsigned char **digest; } HashDirectoryTreeState; int HashDirectoryTreeCallback(const char *filename, ARG_UNUSED const struct stat *sb, void *user_data) { HashDirectoryTreeState *state = user_data; bool ignore = true; for (size_t i = 0; state->extensions_filter[i]; i++) { if (StringEndsWith(filename, state->extensions_filter[i])) { ignore = false; break; } } if (ignore) { return 0; } FILE *file = fopen(filename, "rb"); if (!file) { Log(LOG_LEVEL_INFO, "Cannot open file for hashing '%s'. (fopen: %s)", filename, GetErrorStr()); return -1; } size_t len = 0; char buffer[1024]; while ((len = fread(buffer, 1, 1024, file))) { EVP_DigestUpdate(state->crypto_context, state->buffer, len); } fclose(file); return 0; } bool HashDirectoryTree(const char *path, const char **extensions_filter, EVP_MD_CTX *crypto_context) { HashDirectoryTreeState state; memset(state.buffer, 0, 1024); state.extensions_filter = extensions_filter; state.crypto_context = crypto_context; return TraverseDirectoryTree(path, HashDirectoryTreeCallback, &state); } void RotateFiles(char *name, int number) { int i, fd; struct stat statbuf; char from[CF_BUFSIZE], to[CF_BUFSIZE]; if (IsItemIn(ROTATED, name)) { return; } PrependItem(&ROTATED, name, NULL); if (stat(name, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "No access to file %s", name); return; } for (i = number - 1; i > 0; i--) { snprintf(from, CF_BUFSIZE, "%s.%d", name, i); snprintf(to, CF_BUFSIZE, "%s.%d", name, i + 1); if (rename(from, to) == -1) { Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from); } snprintf(from, CF_BUFSIZE, "%s.%d.gz", name, i); snprintf(to, CF_BUFSIZE, "%s.%d.gz", name, i + 1); if (rename(from, to) == -1) { Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from); } snprintf(from, CF_BUFSIZE, "%s.%d.Z", name, i); snprintf(to, CF_BUFSIZE, "%s.%d.Z", name, i + 1); if (rename(from, to) == -1) { Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from); } snprintf(from, CF_BUFSIZE, "%s.%d.bz", name, i); snprintf(to, CF_BUFSIZE, "%s.%d.bz", name, i + 1); if (rename(from, to) == -1) { Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from); } snprintf(from, CF_BUFSIZE, "%s.%d.bz2", name, i); snprintf(to, CF_BUFSIZE, "%s.%d.bz2", name, i + 1); if (rename(from, to) == -1) { Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from); } } snprintf(to, CF_BUFSIZE, "%s.1", name); if (CopyRegularFileDisk(name, to) == false) { Log(LOG_LEVEL_DEBUG, "Copy failed in RotateFiles '%s' -> '%s'", name, to); return; } safe_chmod(to, statbuf.st_mode); if (safe_chown(to, statbuf.st_uid, statbuf.st_gid)) { UnexpectedError("Failed to chown %s", to); } safe_chmod(name, 0600); /* File must be writable to empty .. */ if ((fd = safe_creat(name, statbuf.st_mode)) == -1) { Log(LOG_LEVEL_ERR, "Failed to create new '%s' in disable(rotate). (creat: %s)", name, GetErrorStr()); } else { if (safe_chown(name, statbuf.st_uid, statbuf.st_gid)) /* NT doesn't have fchown */ { UnexpectedError("Failed to chown '%s'", name); } fchmod(fd, statbuf.st_mode); close(fd); } } #ifndef __MINGW32__ void CreateEmptyFile(char *name) { int tempfd; if (unlink(name) == -1) { if (errno != ENOENT) { Log(LOG_LEVEL_DEBUG, "Unable to remove existing file '%s'. (unlink: %s)", name, GetErrorStr()); } } if ((tempfd = safe_open(name, O_CREAT | O_EXCL | O_WRONLY, 0600)) < 0) { Log(LOG_LEVEL_ERR, "Couldn't open a file '%s'. (open: %s)", name, GetErrorStr()); } close(tempfd); } #endif cfengine-3.6.2/libpromises/mod_process.c0000664000175100017510000001203712243421446020034 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax process_count_constraints[] = { ConstraintSyntaxNewStringList("in_range_define", "", "List of classes to define if the matches are in range", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("match_range", CF_VALRANGE, "Integer range for acceptable number of matches for this process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("out_of_range_define", "", "List of classes to define if the matches are out of range", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax process_count_body = BodySyntaxNew("process_count", process_count_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax process_select_constraints[] = { ConstraintSyntaxNewString("command", "", "Regular expression matching the command/cmd field of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("pid", CF_VALRANGE, "Range of integers matching the process id of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("pgid", CF_VALRANGE, "Range of integers matching the parent group id of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("ppid", CF_VALRANGE, "Range of integers matching the parent process id of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("priority", "-20,+20", "Range of integers matching the priority field (PRI/NI) of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("process_owner", "", "List of regexes matching the user of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("process_result", "[(process_owner|pid|ppid||pgid|rsize|vsize|status|command|ttime|stime|tty|priority|threads)[|&!.]*]*", "Boolean class expression returning the logical combination of classes set by a process selection test", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("rsize", CF_VALRANGE, "Range of integers matching the resident memory size of a process, in kilobytes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("status", "", "Regular expression matching the status field of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("stime_range", CF_TIMERANGE, "Range of integers matching the start time of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("ttime_range", CF_TIMERANGE, "Range of integers matching the total elapsed time of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("tty", "", "Regular expression matching the tty field of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("threads", CF_VALRANGE, "Range of integers matching the threads (NLWP) field of a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("vsize", CF_VALRANGE, "Range of integers matching the virtual memory size of a process, in kilobytes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax process_select_body = BodySyntaxNew("process_select", process_select_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax processes_constraints[] = { ConstraintSyntaxNewBody("process_count", &process_count_body, "Criteria for constraining the number of processes matching other criteria", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("process_select", &process_select_body, "Criteria for matching processes in the system process table", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("process_stop", CF_ABSPATHRANGE, "A command used to stop a running process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("restart_class", CF_IDRANGE, "A class to be defined globally if the process is not running, so that a command: rule can be referred to restart the process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOptionList("signals", CF_SIGNALRANGE, "A list of menu options representing signals to be sent to a process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_PROCESS_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "processes", processes_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/syntax.h0000644000175100017510000001412612403352546017053 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SYNTAX_H #define CFENGINE_SYNTAX_H #include #include #include #include /* * WARNING: This file is in need of serious cleanup. */ typedef enum { SYNTAX_TYPE_MATCH_OK, SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED, SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED, SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS, SYNTAX_TYPE_MATCH_ERROR_GOT_SCALAR, SYNTAX_TYPE_MATCH_ERROR_GOT_LIST, SYNTAX_TYPE_MATCH_ERROR_GOT_NULL, SYNTAX_TYPE_MATCH_ERROR_SCALAR_OUT_OF_RANGE, SYNTAX_TYPE_MATCH_ERROR_EMPTY_SCALAR_OUT_OF_RANGE, SYNTAX_TYPE_MATCH_ERROR_STRING_UNIX_PERMISSION, SYNTAX_TYPE_MATCH_ERROR_INT_PARSE, SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE, SYNTAX_TYPE_MATCH_ERROR_REAL_INF, SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE, SYNTAX_TYPE_MATCH_ERROR_OPTS_OUT_OF_RANGE, SYNTAX_TYPE_MATCH_ERROR_FNCALL_RETURN_TYPE, SYNTAX_TYPE_MATCH_ERROR_FNCALL_UNKNOWN, SYNTAX_TYPE_MATCH_ERROR_CONTEXT_OUT_OF_RANGE, SYNTAX_TYPE_MATCH_MAX } SyntaxTypeMatch; const char *SyntaxTypeMatchToString(SyntaxTypeMatch result); int CheckParseVariableName(const char *name); SyntaxTypeMatch CheckConstraintTypeMatch(const char *lval, Rval rval, DataType dt, const char *range, int level); SyntaxTypeMatch CheckParseContext(const char *context, const char *range); DataType StringDataType(EvalContext *ctx, const char *string); DataType ExpectedDataType(const char *lvalname); const PromiseTypeSyntax *PromiseTypeSyntaxGet(const char *bundle_type, const char *promise_type); const ConstraintSyntax *PromiseTypeSyntaxGetConstraintSyntax(const PromiseTypeSyntax *promise_type_syntax, const char *lval); const BodySyntax *BodySyntaxGet(const char *body_type); const ConstraintSyntax *BodySyntaxGetConstraintSyntax(const ConstraintSyntax *body_syntax, const char *lval); const char *SyntaxStatusToString(SyntaxStatus status); JsonElement *SyntaxToJson(void); #define ConstraintSyntaxNewNull() { NULL, CF_DATA_TYPE_NONE, .range.validation_string = NULL, .status = SYNTAX_STATUS_NORMAL } #define ConstraintSyntaxNewBool(lval, description, status) { lval, CF_DATA_TYPE_OPTION, .range.validation_string = CF_BOOL, description, status } #define ConstraintSyntaxNewOption(lval, options, description, status) { lval, CF_DATA_TYPE_OPTION, .range.validation_string = options, description, status } #define ConstraintSyntaxNewOptionList(lval, item_range, description, status) { lval, CF_DATA_TYPE_OPTION_LIST, .range.validation_string = item_range, description, status } #define ConstraintSyntaxNewString(lval, regex, description, status) { lval, CF_DATA_TYPE_STRING, .range.validation_string = regex, description, status } #define ConstraintSyntaxNewStringList(lval, item_range, description, status) { lval, CF_DATA_TYPE_STRING_LIST, .range.validation_string = item_range, description, status } #define ConstraintSyntaxNewInt(lval, int_range, description, status) { lval, CF_DATA_TYPE_INT, .range.validation_string = int_range, description, status } #define ConstraintSyntaxNewIntRange(lval, int_range, description, status ) { lval , CF_DATA_TYPE_INT_RANGE, .range.validation_string = int_range, description, status } #define ConstraintSyntaxNewIntList(lval, description, status) { lval, CF_DATA_TYPE_INT_LIST, .range.validation_string = CF_INTRANGE, description, status } #define ConstraintSyntaxNewReal(lval, real_range, description, status) { lval, CF_DATA_TYPE_REAL, .range.validation_string = real_range, description, status } #define ConstraintSyntaxNewRealList(lval, description, status) { lval, CF_DATA_TYPE_REAL_LIST, .range.validation_string = CF_REALRANGE, description, status } #define ConstraintSyntaxNewContext(lval, description, status) { lval, CF_DATA_TYPE_CONTEXT, .range.validation_string = CF_CLASSRANGE, description, status } #define ConstraintSyntaxNewContextList(lval, description, status) { lval, CF_DATA_TYPE_CONTEXT_LIST, .range.validation_string = CF_CLASSRANGE, description, status } #define ConstraintSyntaxNewContainer(lval, description, status) { lval, CF_DATA_TYPE_CONTAINER, .range.validation_string = "", description, status } #define ConstraintSyntaxNewBody(lval, body_syntax, description, status) { lval, CF_DATA_TYPE_BODY, .range.body_type_syntax = body_syntax, description, status } #define ConstraintSyntaxNewBundle(lval, description, status) { lval, CF_DATA_TYPE_BUNDLE, .range.validation_string = CF_BUNDLE, description, status } #define BodySyntaxNew(body_type, constraints, check_fn, status) { body_type, constraints, check_fn, status } #define BodySyntaxNewNull() { NULL, NULL, NULL, SYNTAX_STATUS_NORMAL } #define PromiseTypeSyntaxNew(agent_type, promise_type, constraints, check_fn, status) { agent_type, promise_type, constraints, check_fn, status } #define PromiseTypeSyntaxNewNull() PromiseTypeSyntaxNew(NULL, NULL, NULL, NULL, SYNTAX_STATUS_NORMAL) #define FnCallTypeNew(name, return_type, arguments, implementation, description, opts, category, status) { name, return_type, arguments, implementation, description, .options = opts, category, status } #define FnCallTypeNewNull() FnCallTypeNew(NULL, CF_DATA_TYPE_NONE, NULL, NULL, NULL, false, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL) #endif cfengine-3.6.2/libpromises/acl_tools_posix.c0000664000175100017510000000542612400110676020717 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #ifdef HAVE_ACL_H # include #endif #ifdef HAVE_SYS_ACL_H # include #endif #ifdef HAVE_ACL_LIBACL_H # include #endif #ifdef HAVE_LIBACL int CopyACLs(const char *src, const char *dst) { acl_t acls; struct stat statbuf; int ret; acls = acl_get_file(src, ACL_TYPE_ACCESS); if (!acls) { if (errno == ENOTSUP) { return true; } else { Log(LOG_LEVEL_INFO, "Can't copy ACLs from '%s'. (acl_get_file: %s)", src, GetErrorStr()); return false; } } ret = acl_set_file(dst, ACL_TYPE_ACCESS, acls); acl_free(acls); if (ret != 0) { if (errno == ENOTSUP) { return true; } else { Log(LOG_LEVEL_INFO, "Can't copy ACLs to '%s'. (acl_set_file: %s)", dst, GetErrorStr()); return false; } } if (stat(src, &statbuf) != 0) { Log(LOG_LEVEL_INFO, "Can't copy ACLs from '%s'. (stat: %s)", src, GetErrorStr()); return false; } if (!S_ISDIR(statbuf.st_mode)) { return true; } // For directory, copy default ACL too. acls = acl_get_file(src, ACL_TYPE_DEFAULT); if (!acls) { Log(LOG_LEVEL_INFO, "Can't copy ACLs from '%s'. (acl_get_file: %s)", src, GetErrorStr()); return false; } ret = acl_set_file(dst, ACL_TYPE_DEFAULT, acls); acl_free(acls); if (ret != 0) { Log(LOG_LEVEL_INFO, "Can't copy ACLs to '%s'. (acl_set_file: %s)", dst, GetErrorStr()); return false; } return true; } #elif !defined(__MINGW32__) /* !HAVE_LIBACL */ int CopyACLs(ARG_UNUSED const char *src, ARG_UNUSED const char *dst) { return true; } #endif cfengine-3.6.2/libpromises/systype.h0000664000175100017510000000455412411001073017234 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SYSTYPE_H #define CFENGINE_SYSTYPE_H /*******************************************************************/ typedef enum { PLATFORM_CONTEXT_UNKNOWN, PLATFORM_CONTEXT_OPENVZ, /* VZ Host with vzps installed */ PLATFORM_CONTEXT_HP, PLATFORM_CONTEXT_AIX, PLATFORM_CONTEXT_LINUX, PLATFORM_CONTEXT_SOLARIS, /* > 5.10, BSD-compatible system tools */ PLATFORM_CONTEXT_SUN_SOLARIS, /* < 5.11, BSD tools in /usr/ucb */ PLATFORM_CONTEXT_FREEBSD, PLATFORM_CONTEXT_NETBSD, PLATFORM_CONTEXT_CRAYOS, PLATFORM_CONTEXT_WINDOWS_NT, /* MS-Win CygWin */ PLATFORM_CONTEXT_SYSTEMV, PLATFORM_CONTEXT_OPENBSD, PLATFORM_CONTEXT_CFSCO, PLATFORM_CONTEXT_DARWIN, /* MacOS X */ PLATFORM_CONTEXT_QNX, PLATFORM_CONTEXT_DRAGONFLY, PLATFORM_CONTEXT_MINGW, /* MS-Win native */ PLATFORM_CONTEXT_VMWARE, PLATFORM_CONTEXT_ANDROID, PLATFORM_CONTEXT_MAX /* Not an actual platform: must be last */ } PlatformContext; /*******************************************************************/ extern PlatformContext VSYSTEMHARDCLASS; extern const char *const CLASSTEXT[PLATFORM_CONTEXT_MAX]; extern const char *const VPSCOMM[PLATFORM_CONTEXT_MAX]; extern const char *const VPSOPTS[PLATFORM_CONTEXT_MAX]; extern const char *const VFSTAB[PLATFORM_CONTEXT_MAX]; /*******************************************************************/ #endif /* CFENGINE_SYSTYPE_H */ cfengine-3.6.2/libpromises/fncall.h0000644000175100017510000000477112316547775017006 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FNCALL_H #define CFENGINE_FNCALL_H #include struct FnCall_ { char *name; Rlist *args; const Promise *caller; }; typedef enum FnCallStatus { FNCALL_SUCCESS, FNCALL_FAILURE } FnCallStatus; typedef struct { FnCallStatus status; Rval rval; } FnCallResult; typedef struct { const char *pattern; DataType dtype; const char *description; } FnCallArg; typedef enum { FNCALL_OPTION_NONE = 0, FNCALL_OPTION_VARARG = 1 << 0, FNCALL_OPTION_CACHED = 1 << 1 } FnCallOption; typedef struct { const char *name; DataType dtype; const FnCallArg *args; FnCallResult (*impl)(EvalContext *, const Policy *, const FnCall *, const Rlist *); const char *description; FnCallOption options; FnCallCategory category; SyntaxStatus status; } FnCallType; extern const FnCallType CF_FNCALL_TYPES[]; bool FnCallIsBuiltIn(Rval rval); FnCall *FnCallNew(const char *name, Rlist *args); FnCall *FnCallCopy(const FnCall *f); void FnCallDestroy(FnCall *fp); unsigned FnCallHash(const FnCall *fp, unsigned seed, unsigned max); void FnCallWrite(Writer *writer, const FnCall *call); FnCallResult FnCallEvaluate(EvalContext *ctx, const Policy *policy, FnCall *fp, const Promise *caller); const FnCallType *FnCallTypeGet(const char *name); FnCall *ExpandFnCall(EvalContext *ctx, const char *ns, const char *scope, const FnCall *f); // TODO: should probably demolish this eventually void FnCallShow(FILE *fout, const char *prefix, const FnCall *fp, const Rlist *args); #endif cfengine-3.6.2/libpromises/mod_report.h0000664000175100017510000000224612243421446017677 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_REPORT_H #define CFENGINE_MOD_REPORT_H #include extern const PromiseTypeSyntax CF_REPORT_PROMISE_TYPES[]; extern const ConstraintSyntax CF_REPORT_BODIES[]; #endif cfengine-3.6.2/libpromises/verify_vars.h0000644000175100017510000000226012316547775020075 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_VARS_H #define CFENGINE_VERIFY_VARS_H #include #include PromiseResult VerifyVarPromise(EvalContext *ctx, const Promise *pp, bool allow_duplicates); #endif cfengine-3.6.2/libpromises/keyring.c0000644000175100017510000000611312352557236017173 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include /***************************************************************/ bool HostKeyAddressUnknown(const char *value) { if (strcmp(value, "location unknown") == 0) { return true; } // Is there some other non-ip string left over? if (!((strchr(value, '.')) || (strchr(value, ':')))) { return false; } return false; } /***************************************************************/ int RemovePublicKey(const char *id) { Dir *dirh = NULL; int removed = 0; char keysdir[CF_BUFSIZE]; const struct dirent *dirp; char suffix[CF_BUFSIZE]; snprintf(keysdir, CF_BUFSIZE, "%s/ppkeys", CFWORKDIR); MapName(keysdir); if ((dirh = DirOpen(keysdir)) == NULL) { if (errno == ENOENT) { return 0; } else { Log(LOG_LEVEL_ERR, "Unable to open keys directory at '%s'. (opendir: %s)", keysdir, GetErrorStr()); return -1; } } snprintf(suffix, CF_BUFSIZE, "-%s.pub", id); while ((dirp = DirRead(dirh)) != NULL) { char *c = strstr(dirp->d_name, suffix); if (c && c[strlen(suffix)] == '\0') /* dirp->d_name ends with suffix */ { char keyfilename[CF_BUFSIZE]; snprintf(keyfilename, CF_BUFSIZE, "%s/%s", keysdir, dirp->d_name); MapName(keyfilename); if (unlink(keyfilename) < 0) { if (errno != ENOENT) { Log(LOG_LEVEL_ERR, "Unable to remove key file '%s'. (unlink: %s)", dirp->d_name, GetErrorStr()); DirClose(dirh); return -1; } } else { removed++; } } } if (errno) { Log(LOG_LEVEL_ERR, "Unable to enumerate files in keys directory. (ReadDir: %s)", GetErrorStr()); DirClose(dirh); return -1; } DirClose(dirh); return removed; } /***************************************************************/ cfengine-3.6.2/libpromises/logic_expressions.c0000664000175100017510000001545612243421446021266 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include /* */ static ParseResult ParsePrimary(const char *expr, int start, int end) { if (start < end && expr[start] == '(') { ParseResult res = ParseExpression(expr, start + 1, end); if (res.result) { /* Check if there is a matching ')' at the end */ if (res.position < end && expr[res.position] == ')') { return (ParseResult) {res.result, res.position + 1}; } else { /* Haven't found a matching bracket. Give up */ FreeExpression(res.result); return (ParseResult) {NULL, res.position}; } } else { return res; } } else { StringParseResult strres = ParseStringExpression(expr, start, end); if (strres.result) { Expression *res = xcalloc(1, sizeof(Expression)); res->op = LOGICAL_OP_EVAL; res->val.eval.name = strres.result; return (ParseResult) {res, strres.position}; } else { return (ParseResult) {NULL, strres.position}; } } } /* */ static ParseResult ParseNotExpression(const char *expr, int start, int end) { if (start < end && expr[start] == '!') { ParseResult primres = ParsePrimary(expr, start + 1, end); if (primres.result) { Expression *res = xcalloc(1, sizeof(Expression)); res->op = LOGICAL_OP_NOT; res->val.not.arg = primres.result; return (ParseResult) {res, primres.position}; } else { return primres; } } else { return ParsePrimary(expr, start, end); } } /* */ static ParseResult ParseAndExpression(const char *expr, int start, int end) { ParseResult lhs, rhs; Expression *res; lhs = ParseNotExpression(expr, start, end); if (!lhs.result) { return lhs; } if (lhs.position == end || (expr[lhs.position] != '.' && expr[lhs.position] != '&')) { return lhs; } rhs = ParseAndExpression(expr, lhs.position + 1, end); if (!rhs.result) { FreeExpression(lhs.result); return rhs; } res = xcalloc(1, sizeof(Expression)); res->op = LOGICAL_OP_AND; res->val.andor.lhs = lhs.result; res->val.andor.rhs = rhs.result; return (ParseResult) {res, rhs.position}; } /* */ ParseResult ParseExpression(const char *expr, int start, int end) { ParseResult lhs, rhs; Expression *res; int position; lhs = ParseAndExpression(expr, start, end); if (!lhs.result) { return lhs; } /* End of left-hand side expression */ position = lhs.position; if (position == end || expr[position] != '|') { return lhs; } /* Skip second '|' in 'lhs||rhs' */ if (position + 1 < end && expr[position + 1] == '|') { position++; } rhs = ParseExpression(expr, position + 1, end); if (!rhs.result) { FreeExpression(lhs.result); return rhs; } res = xcalloc(1, sizeof(Expression)); res->op = LOGICAL_OP_OR; res->val.andor.lhs = lhs.result; res->val.andor.rhs = rhs.result; return (ParseResult) {res, rhs.position}; } /* Evaluation */ ExpressionValue EvalExpression(const Expression *expr, NameEvaluator nameevalfn, VarRefEvaluator varrefevalfn, void *param) { switch (expr->op) { case LOGICAL_OP_OR: case LOGICAL_OP_AND: { ExpressionValue lhs = EXPRESSION_VALUE_ERROR, rhs = EXPRESSION_VALUE_ERROR; lhs = EvalExpression(expr->val.andor.lhs, nameevalfn, varrefevalfn, param); if (lhs == EXPRESSION_VALUE_ERROR) { return EXPRESSION_VALUE_ERROR; } rhs = EvalExpression(expr->val.andor.rhs, nameevalfn, varrefevalfn, param); if (rhs == EXPRESSION_VALUE_ERROR) { return EXPRESSION_VALUE_ERROR; } if (expr->op == LOGICAL_OP_OR) { return lhs || rhs; } else { return lhs && rhs; } } case LOGICAL_OP_NOT: { ExpressionValue arg = EvalExpression(expr->val.not.arg, nameevalfn, varrefevalfn, param); if (arg == EXPRESSION_VALUE_ERROR) { return EXPRESSION_VALUE_ERROR; } else { return !arg; } } case LOGICAL_OP_EVAL: { ExpressionValue ret = EXPRESSION_VALUE_ERROR; char *name = EvalStringExpression(expr->val.eval.name, varrefevalfn, param); if (name == NULL) { return EXPRESSION_VALUE_ERROR; } ret = (*nameevalfn) (name, param); free(name); return ret; } default: ProgrammingError("Unexpected class expression type is found: %d", expr->op); } } /* Freeing results */ void FreeExpression(Expression *e) { if (!e) { return; } switch (e->op) { case LOGICAL_OP_OR: case LOGICAL_OP_AND: FreeExpression(e->val.andor.lhs); FreeExpression(e->val.andor.rhs); break; case LOGICAL_OP_NOT: FreeExpression(e->val.not.arg); break; case LOGICAL_OP_EVAL: FreeStringExpression(e->val.eval.name); break; default: ProgrammingError("Unknown logic expression type encountered in" "FreeExpression: %d", e->op); } free(e); } cfengine-3.6.2/libpromises/eval_context.h0000664000175100017510000002170112411001073020200 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_EVAL_CONTEXT_H #define CFENGINE_EVAL_CONTEXT_H #include #include #include #include #include #include #include #include #include #include #include typedef enum { STACK_FRAME_TYPE_BUNDLE, STACK_FRAME_TYPE_BODY, STACK_FRAME_TYPE_PROMISE_TYPE, STACK_FRAME_TYPE_PROMISE, STACK_FRAME_TYPE_PROMISE_ITERATION } StackFrameType; typedef struct { const Bundle *owner; ClassTable *classes; VariableTable *vars; } StackFrameBundle; typedef struct { const Body *owner; VariableTable *vars; } StackFrameBody; typedef struct { const Promise *owner; VariableTable *vars; } StackFramePromise; typedef struct { const PromiseType *owner; } StackFramePromiseType; typedef struct { Promise *owner; const PromiseIterator *iter_ctx; size_t index; RingBuffer *log_messages; } StackFramePromiseIteration; typedef struct { StackFrameType type; bool inherits_previous; // whether or not this frame inherits context from the previous frame union { StackFrameBundle bundle; StackFrameBody body; StackFramePromiseType promise_type; StackFramePromise promise; StackFramePromiseIteration promise_iteration; } data; char *path; } StackFrame; typedef enum { EVAL_OPTION_NONE = 0, EVAL_OPTION_EVAL_FUNCTIONS = 1 << 0, EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS = 1 << 1, EVAL_OPTION_FULL = 0xFFFFFFFF } EvalContextOption; EvalContext *EvalContextNew(void); void EvalContextDestroy(EvalContext *ctx); void EvalContextHeapAddAbort(EvalContext *ctx, const char *context, const char *activated_on_context); void EvalContextHeapAddAbortCurrentBundle(EvalContext *ctx, const char *context, const char *activated_on_context); void EvalContextHeapPersistentSave(EvalContext *ctx, const char *name, unsigned int ttl_minutes, PersistentClassPolicy policy, const char *tags); void EvalContextHeapPersistentRemove(const char *context); void EvalContextHeapPersistentLoadAll(EvalContext *ctx); bool EvalContextClassPutSoft(EvalContext *ctx, const char *name, ContextScope scope, const char *tags); bool EvalContextClassPutHard(EvalContext *ctx, const char *name, const char *tags); Class *EvalContextClassGet(const EvalContext *ctx, const char *ns, const char *name); Class *EvalContextClassMatch(const EvalContext *ctx, const char *regex); bool EvalContextClassRemove(EvalContext *ctx, const char *ns, const char *name); StringSet *EvalContextClassTags(const EvalContext *ctx, const char *ns, const char *name); ClassTableIterator *EvalContextClassTableIteratorNewGlobal(const EvalContext *ctx, const char *ns, bool is_hard, bool is_soft); ClassTableIterator *EvalContextClassTableIteratorNewLocal(const EvalContext *ctx); void EvalContextClear(EvalContext *ctx); void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous); void EvalContextStackPushBodyFrame(EvalContext *ctx, const Promise *caller, const Body *body, const Rlist *args); void EvalContextStackPushPromiseTypeFrame(EvalContext *ctx, const PromiseType *owner); void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner, bool copy_bundle_context); Promise *EvalContextStackPushPromiseIterationFrame(EvalContext *ctx, size_t iteration_index, const PromiseIterator *iter_ctx); void EvalContextStackPopFrame(EvalContext *ctx); char *EvalContextStackPath(const EvalContext *ctx); StringSet *EvalContextStackPromisees(const EvalContext *ctx); const Promise *EvalContextStackCurrentPromise(const EvalContext *ctx); const Bundle *EvalContextStackCurrentBundle(const EvalContext *ctx); const RingBuffer *EvalContextStackCurrentMessages(const EvalContext *ctx); bool EvalContextVariablePut(EvalContext *ctx, const VarRef *ref, const void *value, DataType type, const char *tags); bool EvalContextVariablePutSpecial(EvalContext *ctx, SpecialScope scope, const char *lval, const void *value, DataType type, const char *tags); const void *EvalContextVariableGet(const EvalContext *ctx, const VarRef *ref, DataType *type_out); const Promise *EvalContextVariablePromiseGet(const EvalContext *ctx, const VarRef *ref); bool EvalContextVariableRemoveSpecial(const EvalContext *ctx, SpecialScope scope, const char *lval); bool EvalContextVariableRemove(const EvalContext *ctx, const VarRef *ref); StringSet *EvalContextVariableTags(const EvalContext *ctx, const VarRef *ref); bool EvalContextVariableClearMatch(EvalContext *ctx); VariableTableIterator *EvalContextVariableTableIteratorNew(const EvalContext *ctx, const char *ns, const char *scope, const char *lval); bool EvalContextPromiseLockCacheContains(const EvalContext *ctx, const char *key); void EvalContextPromiseLockCachePut(EvalContext *ctx, const char *key); bool EvalContextFunctionCacheGet(const EvalContext *ctx, const FnCall *fp, const Rlist *args, Rval *rval_out); void EvalContextFunctionCachePut(EvalContext *ctx, const FnCall *fp, const Rlist *args, const Rval *rval); const void *EvalContextVariableControlCommonGet(const EvalContext *ctx, CommonControl lval); /** * @brief Find a bundle for a bundle call, given a callee reference (in the form of ns:bundle), and a type of bundle. * This is requires EvalContext because the callee reference may be unqualified. * Hopefully this should go away in the future if we make a more generalized API to simply call a bundle, * but we have a few special rules around edit_line and so on. */ const Bundle *EvalContextResolveBundleExpression(const EvalContext *ctx, const Policy *policy, const char *callee_reference, const char *callee_type); const Body *EvalContextResolveBodyExpression(const EvalContext *ctx, const Policy *policy, const char *callee_reference, const char *callee_type); /* - Parsing/evaluating expressions - */ void ValidateClassSyntax(const char *str); bool IsDefinedClass(const EvalContext *ctx, const char *context); bool EvalProcessResult(const char *process_result, StringSet *proc_attr); bool EvalFileResult(const char *file_result, StringSet *leaf_attr); /* Various global options */ void SetChecksumUpdatesDefault(EvalContext *ctx, bool enabled); bool GetChecksumUpdatesDefault(const EvalContext *ctx); /* IP addresses */ Item *EvalContextGetIpAddresses(const EvalContext *ctx); void EvalContextAddIpAddress(EvalContext *ctx, const char *address); void EvalContextDeleteIpAddresses(EvalContext *ctx); /* - Rest - */ bool EvalContextPromiseIsActive(const EvalContext *ctx, const Promise *pp); void EvalContextSetEvalOption(EvalContext *ctx, EvalContextOption option, bool value); bool EvalContextGetEvalOption(EvalContext *ctx, EvalContextOption option); bool EvalContextIsIgnoringLocks(const EvalContext *ctx); void EvalContextSetIgnoreLocks(EvalContext *ctx, bool ignore); void EvalContextSetLaunchDirectory(EvalContext *ctx, const char *path); bool Abort(EvalContext *ctx); bool VarClassExcluded(const EvalContext *ctx, const Promise *pp, char **classes); void NotifyDependantPromises(EvalContext *ctx, const Promise *pp, PromiseResult result); bool MissingDependencies(EvalContext *ctx, const Promise *pp); void cfPS(EvalContext *ctx, LogLevel level, PromiseResult status, const Promise *pp, Attributes attr, const char *fmt, ...) FUNC_ATTR_PRINTF(6, 7); /* This function is temporarily exported. It needs to be made an detail of * evaluator again, once variables promises are no longer specially handled */ void ClassAuditLog(EvalContext *ctx, const Promise *pp, Attributes attr, PromiseResult status); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, TrackTotalCompliance, ARG_UNUSED PromiseResult, status, ARG_UNUSED const Promise *, pp); ENTERPRISE_VOID_FUNC_3ARG_DECLARE(void, EvalContextLogPromiseIterationOutcome, EvalContext *, ctx, const Promise *, pp, PromiseResult, result); #endif cfengine-3.6.2/libpromises/enterprise_extension.h0000664000175100017510000047635012412324530022006 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* #### THIS FILE WAS AUTOGENERATED FROM extension_template.* #### */ /******************************************************************************* * Note: This shared library calling mechanism should only be used for private * shared libraries, such as the Enterprise plugins for CFEngine. ******************************************************************************/ /******************************************************************************* * How to use the Extension calling API: * * In the application: * * - Declare function prototypes using the ENTERPRISE_FUNC_xARG_DECLARE macros. * Replace x with the number of arguments to the function. * * - Define a stub function using the ENTERPRISE_FUNC_xARG_DEFINE_STUB macros. * * In the Enterprise plugin: * * - Include the same prototype as you used in the application. * * - Define the Enterprise function with the ENTERPRISE_FUNC_xARG_DEFINE * macros. * * IMPORTANT: * * - For functions returning void, you need to use the VOID_FUNC version of the * macros. * * - Due to macro limitations, for each function argument, you need to put the * type and the name as separate arguments, so instead of (int par), use * (int, par). * * - You can use the function normally in your code. If the Enterprise plugin * is available, it will call that function, if not, it will call the stub * function. * * - The lookup is more expensive than a normal function call. Don't use it in * a tight loop. * * - Be careful when changing the function signature. The plugin needs * to stay binary compatible, otherwise the it will not work, and may even * crash. Signature changes should only happen between major releases. * * Examples: * * - int EnterpriseOnlyInt(const char *str, int num) becomes * ENTERPRISE_FUNC_2ARG_DECLARE(int, EnterpriseOnlyInt, * const char *, str, int, num) * ENTERPRISE_FUNC_2ARG_DEFINE_STUB(int, EnterpriseOnlyInt, * const char *, str, int, num) * ENTERPRISE_FUNC_2ARG_DEFINE(int, EnterpriseOnlyInt, * const char *, str, int, num) * * - void EnterpriseFunc(int num) becomes * ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, EnterpriseFunc, int, num) * ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, EnterpriseFunc, int, num) * ENTERPRISE_VOID_FUNC_1ARG_DEFINE(void, EnterpriseFunc, int, num) ******************************************************************************/ /******************************************************************************* * It may be easier to understand the implementation below by looking at the * output it actually produces. gcc -E is your friend. ******************************************************************************/ #ifndef ENTERPRISE_EXTENSION_H #define ENTERPRISE_EXTENSION_H #include #include #ifndef BUILTIN_EXTENSIONS #define ENTERPRISE_CANARY_VALUE 0x10203040 #define ENTERPRISE_LIBRARY_NAME "cfengine-enterprise.so" void *enterprise_library_open(); void enterprise_library_close(void *handle); #ifndef BUILDING_ENTERPRISE_EXTENSION # define ENTERPRISE_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ __ret __func() # define ENTERPRISE_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func(__t1 __p1) # define ENTERPRISE_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func(__t1 __p1, __t2 __p2) # define ENTERPRISE_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3) # define ENTERPRISE_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define ENTERPRISE_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define ENTERPRISE_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define ENTERPRISE_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define ENTERPRISE_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define ENTERPRISE_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define ENTERPRISE_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define ENTERPRISE_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define ENTERPRISE_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define ENTERPRISE_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define ENTERPRISE_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define ENTERPRISE_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) # define ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) \ __ret __func##__stub() # define ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__stub(__t1 __p1) # define ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__stub(__t1 __p1, __t2 __p2) # define ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3) # define ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) #else // BUILDING_ENTERPRISE_EXTENSION # define ENTERPRISE_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, int32_t __end_canary) # define ENTERPRISE_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, int32_t __end_canary) # define ENTERPRISE_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, int32_t __end_canary) # define ENTERPRISE_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, int32_t __end_canary) # define ENTERPRISE_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, int32_t __end_canary) # define ENTERPRISE_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, int32_t __end_canary) # define ENTERPRISE_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, int32_t __end_canary) # define ENTERPRISE_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, int32_t __end_canary) # define ENTERPRISE_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, int32_t __end_canary) # define ENTERPRISE_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, int32_t __end_canary) # define ENTERPRISE_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, int32_t __end_canary) # define ENTERPRISE_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, int32_t __end_canary) # define ENTERPRISE_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, int32_t __end_canary) # define ENTERPRISE_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, int32_t __end_canary) # define ENTERPRISE_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, int32_t __end_canary) # define ENTERPRISE_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__wrapper(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15, int32_t __end_canary) # define ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) \ __ret __func##__real() # define ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__real(__t1 __p1) # define ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__real(__t1 __p1, __t2 __p2) # define ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3) # define ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__real(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) # define ENTERPRISE_FUNC_0ARG_INLINE_SIGNATURE(__ret, __func) \ inline static __ret __func() # define ENTERPRISE_FUNC_1ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1) \ inline static __ret __func(__t1 __p1) # define ENTERPRISE_FUNC_2ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ inline static __ret __func(__t1 __p1, __t2 __p2) # define ENTERPRISE_FUNC_3ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3) # define ENTERPRISE_FUNC_4ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define ENTERPRISE_FUNC_5ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define ENTERPRISE_FUNC_6ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define ENTERPRISE_FUNC_7ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define ENTERPRISE_FUNC_8ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define ENTERPRISE_FUNC_9ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define ENTERPRISE_FUNC_10ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define ENTERPRISE_FUNC_11ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define ENTERPRISE_FUNC_12ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define ENTERPRISE_FUNC_13ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define ENTERPRISE_FUNC_14ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define ENTERPRISE_FUNC_15ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ inline static __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) #endif // BUILDING_ENTERPRISE_EXTENSION #ifndef BUILDING_ENTERPRISE_EXTENSION # define ENTERPRISE_FUNC_0ARG_DECLARE_IMPL(__ret, __func) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, int32_t __end_canary); \ ENTERPRISE_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func); \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define ENTERPRISE_FUNC_1ARG_DECLARE_IMPL(__ret, __func, __t1, __p1) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, int32_t __end_canary); \ ENTERPRISE_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1); \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define ENTERPRISE_FUNC_2ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, int32_t __end_canary); \ ENTERPRISE_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2); \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define ENTERPRISE_FUNC_3ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, int32_t __end_canary); \ ENTERPRISE_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3); \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define ENTERPRISE_FUNC_4ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, int32_t __end_canary); \ ENTERPRISE_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4); \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define ENTERPRISE_FUNC_5ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, int32_t __end_canary); \ ENTERPRISE_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5); \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define ENTERPRISE_FUNC_6ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, int32_t __end_canary); \ ENTERPRISE_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6); \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define ENTERPRISE_FUNC_7ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, int32_t __end_canary); \ ENTERPRISE_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7); \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define ENTERPRISE_FUNC_8ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, int32_t __end_canary); \ ENTERPRISE_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8); \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define ENTERPRISE_FUNC_9ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, int32_t __end_canary); \ ENTERPRISE_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9); \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define ENTERPRISE_FUNC_10ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, int32_t __end_canary); \ ENTERPRISE_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10); \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define ENTERPRISE_FUNC_11ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, int32_t __end_canary); \ ENTERPRISE_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11); \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define ENTERPRISE_FUNC_12ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, int32_t __end_canary); \ ENTERPRISE_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12); \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define ENTERPRISE_FUNC_13ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, int32_t __end_canary); \ ENTERPRISE_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13); \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define ENTERPRISE_FUNC_14ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, int32_t __end_canary); \ ENTERPRISE_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14); \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define ENTERPRISE_FUNC_15ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ typedef __ret (*__func##__type)(int32_t __start_canary, int *__successful, __t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15, int32_t __end_canary); \ ENTERPRISE_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15); \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) # define ENTERPRISE_FUNC_0ARG_DECLARE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_DECLARE_IMPL(__ret, __func) # define ENTERPRISE_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_DECLARE_IMPL(__ret, __func, __t1, __p1) # define ENTERPRISE_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2) # define ENTERPRISE_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define ENTERPRISE_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define ENTERPRISE_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define ENTERPRISE_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define ENTERPRISE_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define ENTERPRISE_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define ENTERPRISE_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define ENTERPRISE_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define ENTERPRISE_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define ENTERPRISE_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define ENTERPRISE_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define ENTERPRISE_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define ENTERPRISE_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) # define ENTERPRISE_VOID_FUNC_0ARG_DECLARE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_DECLARE_IMPL(__ret, __func) # define ENTERPRISE_VOID_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_DECLARE_IMPL(__ret, __func, __t1, __p1) # define ENTERPRISE_VOID_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2) # define ENTERPRISE_VOID_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define ENTERPRISE_VOID_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define ENTERPRISE_VOID_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define ENTERPRISE_VOID_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define ENTERPRISE_VOID_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define ENTERPRISE_VOID_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define ENTERPRISE_VOID_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define ENTERPRISE_VOID_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define ENTERPRISE_VOID_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define ENTERPRISE_VOID_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define ENTERPRISE_VOID_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define ENTERPRISE_VOID_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define ENTERPRISE_VOID_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_DECLARE_IMPL(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #else // BUILDING_ENTERPRISE_EXTENSION # define ENTERPRISE_FUNC_0ARG_DECLARE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func); \ ENTERPRISE_FUNC_0ARG_INLINE_SIGNATURE(__ret, __func) \ { \ return __func##__real(); \ } \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define ENTERPRISE_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1); \ ENTERPRISE_FUNC_1ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1) \ { \ return __func##__real(__p1); \ } \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define ENTERPRISE_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2); \ ENTERPRISE_FUNC_2ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ { \ return __func##__real(__p1, __p2); \ } \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define ENTERPRISE_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3); \ ENTERPRISE_FUNC_3ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ { \ return __func##__real(__p1, __p2, __p3); \ } \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define ENTERPRISE_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4); \ ENTERPRISE_FUNC_4ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ { \ return __func##__real(__p1, __p2, __p3, __p4); \ } \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define ENTERPRISE_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5); \ ENTERPRISE_FUNC_5ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5); \ } \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define ENTERPRISE_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6); \ ENTERPRISE_FUNC_6ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6); \ } \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define ENTERPRISE_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7); \ ENTERPRISE_FUNC_7ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7); \ } \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define ENTERPRISE_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8); \ ENTERPRISE_FUNC_8ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8); \ } \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define ENTERPRISE_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9); \ ENTERPRISE_FUNC_9ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9); \ } \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define ENTERPRISE_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10); \ ENTERPRISE_FUNC_10ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10); \ } \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define ENTERPRISE_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11); \ ENTERPRISE_FUNC_11ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11); \ } \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define ENTERPRISE_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12); \ ENTERPRISE_FUNC_12ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12); \ } \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define ENTERPRISE_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13); \ ENTERPRISE_FUNC_13ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13); \ } \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define ENTERPRISE_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14); \ ENTERPRISE_FUNC_14ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14); \ } \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define ENTERPRISE_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15); \ ENTERPRISE_FUNC_15ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15); \ } \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) # define ENTERPRISE_VOID_FUNC_0ARG_DECLARE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func); \ ENTERPRISE_FUNC_0ARG_INLINE_SIGNATURE(__ret, __func) \ { \ return __func##__real(); \ } \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define ENTERPRISE_VOID_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1); \ ENTERPRISE_FUNC_1ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1) \ { \ return __func##__real(__p1); \ } \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define ENTERPRISE_VOID_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2); \ ENTERPRISE_FUNC_2ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ { \ return __func##__real(__p1, __p2); \ } \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define ENTERPRISE_VOID_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3); \ ENTERPRISE_FUNC_3ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ { \ return __func##__real(__p1, __p2, __p3); \ } \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define ENTERPRISE_VOID_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4); \ ENTERPRISE_FUNC_4ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ { \ return __func##__real(__p1, __p2, __p3, __p4); \ } \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define ENTERPRISE_VOID_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5); \ ENTERPRISE_FUNC_5ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5); \ } \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define ENTERPRISE_VOID_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6); \ ENTERPRISE_FUNC_6ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6); \ } \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define ENTERPRISE_VOID_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7); \ ENTERPRISE_FUNC_7ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7); \ } \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define ENTERPRISE_VOID_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8); \ ENTERPRISE_FUNC_8ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8); \ } \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define ENTERPRISE_VOID_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9); \ ENTERPRISE_FUNC_9ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9); \ } \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define ENTERPRISE_VOID_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10); \ ENTERPRISE_FUNC_10ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10); \ } \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define ENTERPRISE_VOID_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11); \ ENTERPRISE_FUNC_11ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11); \ } \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define ENTERPRISE_VOID_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12); \ ENTERPRISE_FUNC_12ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12); \ } \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define ENTERPRISE_VOID_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13); \ ENTERPRISE_FUNC_13ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13); \ } \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define ENTERPRISE_VOID_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14); \ ENTERPRISE_FUNC_14ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14); \ } \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define ENTERPRISE_VOID_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15); \ ENTERPRISE_FUNC_15ARG_INLINE_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ { \ return __func##__real(__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15); \ } \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #endif // BUILDING_ENTERPRISE_EXTENSION #ifndef BUILDING_ENTERPRISE_EXTENSION // The __ret__assign and __ret_ref parameters are to work around functions returning void. #define ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, __real__func__par, __stub__func__par) \ { \ void *__handle = enterprise_library_open(); \ if (__handle) \ { \ static __func##__type func_ptr = NULL; \ if (!func_ptr) \ { \ func_ptr = shlib_load(__handle, #__func "__wrapper"); \ } \ if (func_ptr) \ { \ int __successful = 0; \ __ret__assign func_ptr __real__func__par; \ if (__successful) \ { \ enterprise_library_close(__handle); \ return __ret__ref; \ } \ } \ enterprise_library_close(__handle); \ } \ return __func##__stub __stub__func__par; \ } # define ENTERPRISE_FUNC_0ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref) \ ENTERPRISE_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, ENTERPRISE_CANARY_VALUE), \ ()) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) # define ENTERPRISE_FUNC_1ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, ENTERPRISE_CANARY_VALUE), \ (__p1)) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) # define ENTERPRISE_FUNC_2ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2)) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) # define ENTERPRISE_FUNC_3ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3)) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) # define ENTERPRISE_FUNC_4ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4)) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) # define ENTERPRISE_FUNC_5ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5)) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) # define ENTERPRISE_FUNC_6ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6)) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) # define ENTERPRISE_FUNC_7ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7)) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) # define ENTERPRISE_FUNC_8ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8)) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) # define ENTERPRISE_FUNC_9ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9)) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) # define ENTERPRISE_FUNC_10ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10)) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) # define ENTERPRISE_FUNC_11ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11)) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) # define ENTERPRISE_FUNC_12ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12)) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) # define ENTERPRISE_FUNC_13ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13)) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) # define ENTERPRISE_FUNC_14ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14)) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) # define ENTERPRISE_FUNC_15ARG_DEFINE_STUB_IMPL(__ret, __func, __ret__assign, __ret__ref, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_IMPL_LOADER(__ret, __func, __ret__assign, __ret__ref, \ (ENTERPRISE_CANARY_VALUE, &__successful, __p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15, ENTERPRISE_CANARY_VALUE), \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15)) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ ENTERPRISE_FUNC_0ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value) #define ENTERPRISE_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1) #define ENTERPRISE_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2) #define ENTERPRISE_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_DEFINE_STUB_IMPL(__ret, __func, __ret __ret_value =, __ret_value, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ ENTERPRISE_FUNC_0ARG_DEFINE_STUB_IMPL(__ret, __func, , ) #define ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1) #define ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2) #define ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_VOID_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_VOID_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_VOID_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_VOID_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_VOID_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_VOID_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_VOID_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_VOID_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_VOID_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_VOID_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_VOID_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_VOID_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_DEFINE_STUB_IMPL(__ret, __func, , , __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_FUNC_DEFINE_REAL_INVALID In_core_code_you_need_to_use_DEFINE_STUB func() #define ENTERPRISE_FUNC_0ARG_DEFINE(__ret, __func) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_0ARG_DEFINE(__ret, __func) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #define ENTERPRISE_VOID_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_DEFINE_REAL_INVALID #else // BUILDING_ENTERPRISE_EXTENSION #define ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL_RET_VALUE(__ret, __func, __real__func__par, __ret__expr) \ { \ if (__start_canary != ENTERPRISE_CANARY_VALUE || __end_canary != ENTERPRISE_CANARY_VALUE) \ { \ Log(LOG_LEVEL_ERR, "Function '%s %s%s' failed stack consistency check. Most likely this means the plugin containing the " \ "function is incompatible with this version of CFEngine.", #__ret, #__func, #__real__func__par); \ __ret__expr; \ } \ *__successful = 1; \ return __func __real__func__par; \ } #define ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, __real__func__par) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL_RET_VALUE(__ret, __func, __real__func__par, \ __ret __ret_value = (__ret)0; \ (void)__ret_value; \ return __ret_value) #define ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, __real__func__par) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL_RET_VALUE(__ret, __func, __real__func__par, return) #define ENTERPRISE_FUNC_DEFINE_INLINE_IMPL(__ret, __func, __real__func__par) \ { \ return __func##__real __real__func__par; \ } #define ENTERPRISE_FUNC_0ARG_DEFINE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ ()) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define ENTERPRISE_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1)) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2)) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3)) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4)) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5)) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6)) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7)) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8)) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9)) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10)) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11)) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12)) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13)) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14)) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15)) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_VOID_FUNC_0ARG_DEFINE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_WRAPPER_SIGNATURE(__ret, __func) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ ()) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define ENTERPRISE_VOID_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1)) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_VOID_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2)) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_VOID_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3)) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_VOID_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4)) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_VOID_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5)) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_VOID_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6)) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_VOID_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7)) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_VOID_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8)) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_VOID_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9)) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_VOID_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10)) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_VOID_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11)) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_VOID_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12)) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_VOID_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13)) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_VOID_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14)) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_VOID_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_WRAPPER_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_VOID_FUNC_DEFINE_WRAPPER_IMPL(__ret, __func, \ (__p1, __p2, __p3, __p4, __p5, __p6, __p7, __p8, __p9, __p10, __p11, __p12, __p13, __p14, __p15)) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_FUNC_DEFINE_STUB_INVALID In_extension_code_you_cannot_define_a_STUB func() #define ENTERPRISE_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #define ENTERPRISE_VOID_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_DEFINE_STUB_INVALID #endif // BUILDING_ENTERPRISE_EXTENSION #else // BUILTIN_EXTENSIONS // In this case just map to real function calls. // BUILTIN_EXTENSIONS is for Windows binaries and debugging. # define ENTERPRISE_FUNC_0ARG_STUB_SIGNATURE(__ret, __func) \ __ret __func##__stub() # define ENTERPRISE_FUNC_1ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func##__stub(__t1 __p1) # define ENTERPRISE_FUNC_2ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func##__stub(__t1 __p1, __t2 __p2) # define ENTERPRISE_FUNC_3ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3) # define ENTERPRISE_FUNC_4ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define ENTERPRISE_FUNC_5ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define ENTERPRISE_FUNC_6ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define ENTERPRISE_FUNC_7ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define ENTERPRISE_FUNC_8ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define ENTERPRISE_FUNC_9ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define ENTERPRISE_FUNC_10ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define ENTERPRISE_FUNC_11ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define ENTERPRISE_FUNC_12ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define ENTERPRISE_FUNC_13ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define ENTERPRISE_FUNC_14ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define ENTERPRISE_FUNC_15ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func##__stub(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) # define ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) \ __ret __func() # define ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) \ __ret __func(__t1 __p1) # define ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) \ __ret __func(__t1 __p1, __t2 __p2) # define ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3) # define ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4) # define ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5) # define ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6) # define ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7) # define ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8) # define ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9) # define ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10) # define ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11) # define ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12) # define ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13) # define ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14) # define ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ __ret __func(__t1 __p1, __t2 __p2, __t3 __p3, __t4 __p4, __t5 __p5, __t6 __p6, __t7 __p7, __t8 __p8, __t9 __p9, __t10 __p10, __t11 __p11, __t12 __p12, __t13 __p13, __t14 __p14, __t15 __p15) #define ENTERPRISE_FUNC_0ARG_DECLARE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define ENTERPRISE_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_VOID_FUNC_0ARG_DECLARE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define ENTERPRISE_VOID_FUNC_1ARG_DECLARE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_VOID_FUNC_2ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_VOID_FUNC_3ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_VOID_FUNC_4ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_VOID_FUNC_5ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_VOID_FUNC_6ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_VOID_FUNC_7ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_VOID_FUNC_8ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_VOID_FUNC_9ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_VOID_FUNC_10ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_VOID_FUNC_11ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_VOID_FUNC_12ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_VOID_FUNC_13ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_VOID_FUNC_14ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_VOID_FUNC_15ARG_DECLARE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_FUNC_0ARG_DEFINE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define ENTERPRISE_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_VOID_FUNC_0ARG_DEFINE(__ret, __func) \ ENTERPRISE_FUNC_0ARG_REAL_SIGNATURE(__ret, __func) #define ENTERPRISE_VOID_FUNC_1ARG_DEFINE(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_VOID_FUNC_2ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_VOID_FUNC_3ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_VOID_FUNC_4ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_VOID_FUNC_5ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_VOID_FUNC_6ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_VOID_FUNC_7ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_VOID_FUNC_8ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_VOID_FUNC_9ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_VOID_FUNC_10ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_VOID_FUNC_11ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_VOID_FUNC_12ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_VOID_FUNC_13ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_VOID_FUNC_14ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_VOID_FUNC_15ARG_DEFINE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_REAL_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ ENTERPRISE_FUNC_0ARG_STUB_SIGNATURE(__ret, __func) #define ENTERPRISE_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #define ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(__ret, __func) \ ENTERPRISE_FUNC_0ARG_STUB_SIGNATURE(__ret, __func) #define ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(__ret, __func, __t1, __p1) \ ENTERPRISE_FUNC_1ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1) #define ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2) \ ENTERPRISE_FUNC_2ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2) #define ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) \ ENTERPRISE_FUNC_3ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3) #define ENTERPRISE_VOID_FUNC_4ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) \ ENTERPRISE_FUNC_4ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4) #define ENTERPRISE_VOID_FUNC_5ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) \ ENTERPRISE_FUNC_5ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5) #define ENTERPRISE_VOID_FUNC_6ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) \ ENTERPRISE_FUNC_6ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6) #define ENTERPRISE_VOID_FUNC_7ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) \ ENTERPRISE_FUNC_7ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7) #define ENTERPRISE_VOID_FUNC_8ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) \ ENTERPRISE_FUNC_8ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8) #define ENTERPRISE_VOID_FUNC_9ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) \ ENTERPRISE_FUNC_9ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9) #define ENTERPRISE_VOID_FUNC_10ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) \ ENTERPRISE_FUNC_10ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10) #define ENTERPRISE_VOID_FUNC_11ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) \ ENTERPRISE_FUNC_11ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11) #define ENTERPRISE_VOID_FUNC_12ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) \ ENTERPRISE_FUNC_12ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12) #define ENTERPRISE_VOID_FUNC_13ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) \ ENTERPRISE_FUNC_13ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13) #define ENTERPRISE_VOID_FUNC_14ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) \ ENTERPRISE_FUNC_14ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14) #define ENTERPRISE_VOID_FUNC_15ARG_DEFINE_STUB(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) \ ENTERPRISE_FUNC_15ARG_STUB_SIGNATURE(__ret, __func, __t1, __p1, __t2, __p2, __t3, __p3, __t4, __p4, __t5, __p5, __t6, __p6, __t7, __p7, __t8, __p8, __t9, __p9, __t10, __p10, __t11, __p11, __t12, __p12, __t13, __p13, __t14, __p14, __t15, __p15) #endif // BUILTIN_EXTENSIONS #endif // ENTERPRISE_EXTENSION_H cfengine-3.6.2/libpromises/keyring.h0000664000175100017510000000221012243421446017164 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_KEYRING_H #define CFENGINE_KEYRING_H #include bool HostKeyAddressUnknown(const char *value); int RemovePublicKey(const char *id); #endif cfengine-3.6.2/libpromises/evalfunction.h0000644000175100017510000000331712316547775020237 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_EVALFUNCTION_H #define CFENGINE_EVALFUNCTION_H #include #include #include #include FnCallResult FnCallHostInNetgroup(EvalContext *ctx, const Policy *policy, const FnCall *fp, const Rlist *finalargs); int FnNumArgs(const FnCallType *call_type); void ModuleProtocol(EvalContext *ctx, char *command, const char *line, int print, char* context, StringSet *tags); /* Implemented in Nova for Win32 */ FnCallResult FnCallGroupExists(EvalContext *ctx, const Policy *policy, const FnCall *fp, const Rlist *finalargs); FnCallResult FnCallUserExists(EvalContext *ctx, const Policy *policy, const FnCall *fp, const Rlist *finalargs); JsonElement *DefaultTemplateData(const EvalContext *ctx); #endif cfengine-3.6.2/libpromises/timeout.c0000644000175100017510000000361412316547775017223 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include void SetTimeOut(int timeout) { ALARM_PID = -1; signal(SIGALRM, (void *) TimeOut); alarm(timeout); } /*************************************************************************/ void TimeOut() { alarm(0); if (ALARM_PID != -1) { Log(LOG_LEVEL_VERBOSE, "Time out of process %jd", (intmax_t)ALARM_PID); GracefulTerminate(ALARM_PID, PROCESS_START_TIME_UNKNOWN); } else { Log(LOG_LEVEL_VERBOSE, "%s> Time out", VPREFIX); } } /*************************************************************************/ time_t SetReferenceTime(void) { time_t tloc; if ((tloc = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_ERR, "Couldn't read system clock. (time: %s)", GetErrorStr()); } CFSTARTTIME = tloc; Log(LOG_LEVEL_VERBOSE, "Reference time set to '%s'", ctime(&tloc)); return tloc; } cfengine-3.6.2/libpromises/instrumentation.h0000664000175100017510000000246612411001073020757 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_INSTRUMENTATION_H #define CFENGINE_INSTRUMENTATION_H #include #include #include struct timespec BeginMeasure(void); void EndMeasure(char *eventname, struct timespec start); int EndMeasureValueMs(struct timespec start); void EndMeasurePromise(struct timespec start, const Promise *pp); #endif cfengine-3.6.2/libpromises/matching.c0000664000175100017510000002153712400110676017311 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include /* CompileRegex,StringMatchFull */ /* Pure, non-thread-safe */ static char *FirstBackReference(pcre *rx, const char *teststring) { static char backreference[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */ int ovector[OVECCOUNT], i, rc; memset(backreference, 0, CF_BUFSIZE); if ((rc = pcre_exec(rx, NULL, teststring, strlen(teststring), 0, 0, ovector, OVECCOUNT)) >= 0) { for (i = 1; i < rc; i++) /* make backref vars $(1),$(2) etc */ { const char *backref_start = teststring + ovector[i * 2]; int backref_len = ovector[i * 2 + 1] - ovector[i * 2]; if (backref_len < CF_MAXVARSIZE) { strncpy(backreference, backref_start, backref_len); } break; } } free(rx); return backreference; } char *ExtractFirstReference(const char *regexp, const char *teststring) { char *backreference; pcre *rx; if ((regexp == NULL) || (teststring == NULL)) { return ""; } rx = CompileRegex(regexp); if (rx == NULL) { return ""; } backreference = FirstBackReference(rx, teststring); if (strlen(backreference) == 0) { strlcpy(backreference, "CF_NOMATCH", CF_MAXVARSIZE); } return backreference; } int IsRegex(const char *str) { const char *sp; int ret = false; enum { r_norm, r_norepeat, r_literal } special = r_norepeat; int bracket = 0; int paren = 0; /* Try to see when something is intended as a regular expression */ for (sp = str; *sp != '\0'; sp++) { if (special == r_literal) { special = r_norm; continue; } else if (*sp == '\\') { special = r_literal; continue; } else if (bracket && (*sp != ']')) { if (*sp == '[') { return false; } continue; } switch (*sp) { case '^': special = (sp == str) ? r_norepeat : r_norm; break; case '*': case '+': if (special == r_norepeat) { return false; } special = r_norepeat; ret = true; break; case '[': special = r_norm; bracket++; ret = true; break; case ']': if (bracket == 0) { return false; } bracket = 0; special = r_norm; break; case '(': special = r_norepeat; paren++; break; case ')': special = r_norm; paren--; if (paren < 0) { return false; } break; case '|': special = r_norepeat; if (paren > 0) { ret = true; } break; default: special = r_norm; } } if ((bracket != 0) || (paren != 0) || (special == r_literal)) { return false; } else { return ret; } } int IsPathRegex(const char *str) { int result = IsRegex(str); if (result) { int s = 0, r = 0; /* Count square and round brackets. */ for (const char *sp = str; *sp != '\0'; sp++) { switch (*sp) { case '[': s++; break; case ']': s--; if (s % 2 == 0) { result++; } break; case '(': r++; break; case ')': r--; if (r % 2 == 0) { result++; } break; default: if (*sp == FILE_SEPARATOR && (r || s)) { Log(LOG_LEVEL_ERR, "Path regular expression %s seems to use expressions containing the directory symbol %c", str, FILE_SEPARATOR); Log(LOG_LEVEL_ERR, "Use a work-around to avoid pathological behaviour"); return false; } break; } } } return result; } /* Checks whether item matches a list of wildcards */ int IsRegexItemIn(EvalContext *ctx, const Item *list, const char *regex) { for (const Item *ptr = list; ptr != NULL; ptr = ptr->next) { if ((ptr->classes) && (!IsDefinedClass(ctx, ptr->classes))) { continue; } /* Cheap pre-test: */ if (strcmp(regex, ptr->name) == 0) { return true; } /* Make it commutative */ if (StringMatchFull(regex, ptr->name) || StringMatchFull(ptr->name, regex)) { return true; } } return false; } /* Escapes non-alphanumeric chars, except sequence given in noEscSeq */ void EscapeSpecialChars(const char *str, char *strEsc, int strEscSz, char *noEscSeq, char *noEscList) { int strEscPos = 0; if (noEscSeq == NULL) { noEscSeq = ""; } if (noEscList == NULL) { noEscList = ""; } memset(strEsc, 0, strEscSz); for (const char *sp = str; (*sp != '\0') && (strEscPos < strEscSz - 2); sp++) { if (strncmp(sp, noEscSeq, strlen(noEscSeq)) == 0) { if (strEscSz <= strEscPos + strlen(noEscSeq)) { break; } strcat(strEsc, noEscSeq); strEscPos += strlen(noEscSeq); sp += strlen(noEscSeq); } if (strchr(noEscList,*sp)) { } else if ((*sp != '\0') && (!isalnum((int)*sp))) { strEsc[strEscPos++] = '\\'; } strEsc[strEscPos++] = *sp; } } void EscapeRegexChars(char *str, char *strEsc, int strEscSz) { char *sp; int strEscPos = 0; memset(strEsc, 0, strEscSz); for (sp = str; (*sp != '\0') && (strEscPos < strEscSz - 2); sp++) { switch (*sp) { case '.': case '*': strEsc[strEscPos++] = '\\'; break; default: break; } strEsc[strEscPos++] = *sp; } } /* Escapes characters esc in the string str of size strSz */ char *EscapeChar(char *str, int strSz, char esc) { char strDup[CF_BUFSIZE]; int strPos, strDupPos; if (sizeof(strDup) < strSz) { ProgrammingError("Too large string passed to EscapeCharInplace()"); } snprintf(strDup, sizeof(strDup), "%s", str); memset(str, 0, strSz); for (strPos = 0, strDupPos = 0; strPos < strSz - 2; strPos++, strDupPos++) { if (strDup[strDupPos] == esc) { str[strPos] = '\\'; strPos++; } str[strPos] = strDup[strDupPos]; } return str; } void AnchorRegex(const char *regex, char *out, int outSz) { if (NULL_OR_EMPTY(regex)) { memset(out, 0, outSz); } else { snprintf(out, outSz, "^(%s)$", regex); } } char *AnchorRegexNew(const char *regex) { if (NULL_OR_EMPTY(regex)) { return xstrdup("^$"); } char *ret = NULL; xasprintf(&ret, "^(%s)$", regex); return ret; } bool HasRegexMetaChars(const char *string) { if (!string) { return false; } if (string[strcspn(string, "\\^${}[]().*+?|<>-&")] == '\0') /* i.e. no metachars appear in string */ { return false; } return true; } cfengine-3.6.2/libpromises/generic_agent.h0000664000175100017510000001150312400110676020306 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_GENERIC_AGENT_H #define CFENGINE_GENERIC_AGENT_H #include #include #include #define GENERIC_AGENT_CHECKSUM_SIZE ((2*CF_SHA1_LEN) + 1) #define GENERIC_AGENT_CHECKSUM_METHOD HASH_METHOD_SHA1 typedef struct { AgentType agent_type; Rlist *bundlesequence; char *original_input_file; char *input_file; char *input_dir; char *tag_release_dir; bool check_not_writable_by_others; bool check_runnable; StringSet *heap_soft; StringSet *heap_negated; bool ignore_locks; bool tty_interactive; // agent is running interactively, via tty/terminal interface bool color; ProtocolVersion protocol_version; // agent state bool ignore_missing_bundles; bool ignore_missing_inputs; struct { struct { enum { GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE, GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_CF, GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_JSON } policy_output_format; unsigned int parser_warnings; unsigned int parser_warnings_error; bool eval_functions; bool show_classes; bool show_variables; } common; struct { char *bootstrap_policy_server; } agent; struct { /* Time of the last validated_at timestamp seen. */ time_t last_validated_at; } daemon; /* execd, serverd etc */ } agent_specific; } GenericAgentConfig; ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, GenericAgentSetDefaultDigest, HashMethod *, digest, int *, digest_len); const char *GenericAgentResolveInputPath(const GenericAgentConfig *config, const char *input_file); void MarkAsPolicyServer(EvalContext *ctx); void GenericAgentDiscoverContext(EvalContext *ctx, GenericAgentConfig *config); bool GenericAgentCheckPolicy(GenericAgentConfig *config, bool force_validation, bool write_validated_file); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, GenericAgentAddEditionClasses, EvalContext *, ctx); void GenericAgentInitialize(EvalContext *ctx, GenericAgentConfig *config); void GenericAgentFinalize(EvalContext *ctx, GenericAgentConfig *config); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, GenericAgentWriteVersion, Writer *, w); void GenericAgentWriteHelp(Writer *w, const char *comp, const struct option options[], const char *const hints[], bool accepts_file_argument); bool GenericAgentArePromisesValid(const GenericAgentConfig *config); time_t ReadTimestampFromPolicyValidatedFile(const GenericAgentConfig *config, const char *maybe_dirname); bool GenericAgentIsPolicyReloadNeeded(const GenericAgentConfig *config); void CloseLog(void); Seq *ControlBodyConstraints(const Policy *policy, AgentType agent); void SetFacility(const char *retval); void CheckBundleParameters(char *scope, Rlist *args); void WritePID(char *filename); bool GenericAgentConfigParseArguments(GenericAgentConfig *config, int argc, char **argv); bool GenericAgentConfigParseWarningOptions(GenericAgentConfig *config, const char *warning_options); bool GenericAgentConfigParseColor(GenericAgentConfig *config, const char *mode); GenericAgentConfig *GenericAgentConfigNewDefault(AgentType agent_type); void GenericAgentConfigDestroy(GenericAgentConfig *config); void GenericAgentConfigApply(EvalContext *ctx, const GenericAgentConfig *config); void GenericAgentConfigSetInputFile(GenericAgentConfig *config, const char *inputdir, const char *input_file); void GenericAgentConfigSetBundleSequence(GenericAgentConfig *config, const Rlist *bundlesequence); bool GenericAgentTagReleaseDirectory(const GenericAgentConfig *config, const char *dirname, bool write_validated, bool write_release); void GetReleaseIdFile(const char *base_path, char *filename, size_t max_size); #endif cfengine-3.6.2/libpromises/cf3parse.c0000664000175100017510000033053712412324530017227 0ustar00a10038a1003800000000000000/* A Bison parser, made by GNU Bison 3.0.2. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 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, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "3.0.2" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Copy the first part of user declarations. */ #line 2 "cf3parse.y" /* yacc.c:339 */ /* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include "cf3.defs.h" #include "parser.h" #include "parser_state.h" #include "fncall.h" #include "rlist.h" #include "item_lib.h" #include "policy.h" #include "mod_files.h" #include "string_lib.h" #include "logic_expressions.h" // FIX: remove #include "syntax.h" #include int yylex(void); extern char *yytext; static int RelevantBundle(const char *agent, const char *blocktype); static bool LvalWantsBody(char *stype, char *lval); static SyntaxTypeMatch CheckSelection(const char *type, const char *name, const char *lval, Rval rval); static SyntaxTypeMatch CheckConstraint(const char *type, const char *lval, Rval rval, const PromiseTypeSyntax *ss); static void fatal_yyerror(const char *s); static void ParseErrorColumnOffset(int column_offset, const char *s, ...) FUNC_ATTR_PRINTF(2, 3); static void ParseError(const char *s, ...) FUNC_ATTR_PRINTF(1, 2); static void ParseWarning(unsigned int warning, const char *s, ...) FUNC_ATTR_PRINTF(2, 3); static void ValidateClassLiteral(const char *class_literal); static bool INSTALL_SKIP = false; static size_t CURRENT_BLOCKID_LINE = 0; static size_t CURRENT_PROMISER_LINE = 0; #define YYMALLOC xmalloc #define ParserDebug if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) printf #line 134 "cf3parse.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULLPTR nullptr # else # define YY_NULLPTR 0 # endif # endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* In a future release of Bison, this section will be replaced by #include "y.tab.h". */ #ifndef YY_YY_CF_PARSE_H_INCLUDED # define YY_YY_CF_PARSE_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { IDSYNTAX = 258, BLOCKID = 259, QSTRING = 260, CLASS = 261, PROMISE_TYPE = 262, BUNDLE = 263, BODY = 264, ASSIGN = 265, ARROW = 266, NAKEDVAR = 267, OP = 268, CP = 269, OB = 270, CB = 271 }; #endif /* Tokens. */ #define IDSYNTAX 258 #define BLOCKID 259 #define QSTRING 260 #define CLASS 261 #define PROMISE_TYPE 262 #define BUNDLE 263 #define BODY 264 #define ASSIGN 265 #define ARROW 266 #define NAKEDVAR 267 #define OP 268 #define CP 269 #define OB 270 #define CB 271 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; int yyparse (void); #endif /* !YY_YY_CF_PARSE_H_INCLUDED */ /* Copy the second part of user declarations. */ #line 217 "cf3parse.c" /* yacc.c:358 */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #else typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ # define YY_(Msgid) Msgid # endif #endif #ifndef YY_ATTRIBUTE # if (defined __GNUC__ \ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C # define YY_ATTRIBUTE(Spec) __attribute__(Spec) # else # define YY_ATTRIBUTE(Spec) /* empty */ # endif #endif #ifndef YY_ATTRIBUTE_PURE # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif #ifndef YY_ATTRIBUTE_UNUSED # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif #if !defined _Noreturn \ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) # if defined _MSC_VER && 1200 <= _MSC_VER # define _Noreturn __declspec (noreturn) # else # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) #else # define YYUSE(E) /* empty */ #endif #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 18 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 133 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 19 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 63 /* YYNRULES -- Number of rules. */ #define YYNRULES 117 /* YYNSTATES -- Number of states. */ #define YYNSTATES 143 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 271 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 18, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 76, 76, 77, 81, 82, 86, 87, 88, 94, 96, 100, 116, 129, 136, 142, 143, 152, 166, 173, 179, 185, 186, 195, 205, 213, 214, 215, 216, 222, 227, 234, 235, 239, 244, 253, 252, 295, 299, 307, 308, 312, 313, 314, 325, 329, 372, 373, 377, 378, 382, 383, 388, 389, 414, 415, 425, 420, 451, 450, 477, 488, 510, 511, 512, 533, 552, 553, 558, 631, 651, 659, 658, 710, 711, 715, 716, 720, 721, 728, 808, 827, 848, 852, 860, 874, 894, 901, 908, 925, 934, 947, 955, 963, 967, 968, 969, 970, 990, 996, 1004, 1012, 1019, 1027, 1031, 1035, 1048, 1056, 1055, 1081, 1082, 1083, 1084, 1092, 1099, 1108, 1117, 1126 }; #endif #if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "IDSYNTAX", "BLOCKID", "QSTRING", "CLASS", "PROMISE_TYPE", "BUNDLE", "BODY", "ASSIGN", "ARROW", "NAKEDVAR", "OP", "CP", "OB", "CB", "','", "';'", "$accept", "specification", "blocks", "block", "bundle", "body", "bundletype", "bundletype_values", "bundleid", "bundleid_values", "bodytype", "bodytype_values", "bodyid", "bodyid_values", "typeid", "symbol", "arglist", "arglist_begin", "arglist_end", "aitems", "aitem", "bundlebody", "$@1", "body_begin", "bundle_decl", "bundle_statements", "bundle_statement", "promise_type", "classpromises_decl", "classpromises", "classpromise", "promise_decl", "promise_line", "promisee_statement", "$@2", "promiser_statement", "$@3", "promiser", "promiser_constraints_decl", "constraints_decl", "constraints", "constraint", "constraint_id", "bodybody", "$@4", "bodyattribs", "bodyattrib", "selection_line", "selection", "selection_id", "assign_type", "arrow_type", "class", "rval", "list", "litems", "litem", "functionid", "usefunction", "givearglist", "$@5", "gaitems", "gaitem", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 44, 59 }; # endif #define YYPACT_NINF -98 #define yypact_value_is_default(Yystate) \ (!!((Yystate) == (-98))) #define YYTABLE_NINF -111 #define yytable_value_is_error(Yytable_value) \ 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int8 yypact[] = { 94, -98, 67, 98, 9, 96, -98, -98, -98, -98, -98, 105, -98, -98, -98, 106, -98, -98, -98, -98, -98, -98, -3, -98, -98, -98, -3, -98, -98, -98, 45, 36, 45, -98, -98, -98, -98, 0, -98, -98, -98, 24, -98, -98, -98, 68, 109, -98, 55, -98, -98, 29, 14, -98, 58, -98, -98, -98, -98, -98, 12, -98, -98, 5, 47, -98, -98, -98, -98, -98, -98, 66, -98, -98, -2, -98, -98, 1, -98, -98, -98, -98, -98, -98, -98, 75, -98, -98, -98, -98, 2, 75, -98, 27, 64, -98, 72, 50, -98, -98, 85, -98, -98, -98, -98, 6, 71, -98, 47, -98, -98, 27, -98, -98, 72, 65, 10, -98, -98, -98, -98, 110, 75, 2, -98, -98, 50, 30, -98, -98, -98, -98, -98, 27, -98, 72, -98, 69, 35, -98, 88, -98, -98 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 8, 0, 0, 0, 0, 4, 6, 7, 13, 23, 0, 11, 12, 19, 0, 17, 18, 1, 5, 16, 24, 25, 14, 15, 22, 25, 20, 21, 29, 0, 0, 0, 38, 37, 9, 35, 28, 33, 30, 27, 0, 31, 71, 10, 0, 0, 26, 0, 43, 45, 0, 40, 41, 0, 34, 32, 81, 80, 85, 0, 73, 76, 0, 0, 75, 36, 42, 61, 60, 44, 0, 48, 51, 0, 54, 55, 0, 50, 72, 74, 78, 77, 83, 82, 0, 49, 52, 53, 84, 0, 0, 92, 86, 87, 88, 89, 0, 79, 90, 0, 91, 70, 69, 59, 0, 65, 66, 0, 56, 102, 98, 104, 99, 100, 0, 0, 101, 107, 106, 64, 0, 0, 0, 93, 97, 0, 0, 67, 68, 57, 96, 117, 113, 114, 115, 116, 0, 0, 108, 0, 112, 111 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -98, -98, -98, 17, -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, 111, 100, 90, -98, 76, -98, 73, -98, -98, 86, -98, -98, 70, -98, -98, -98, 49, -98, -98, -98, -98, -98, -98, -98, 3, -98, -98, 4, -98, -98, -98, -98, 61, -98, -98, -98, 15, -98, -46, -90, -98, 7, -98, -98, -97, -98, -98, -98, -16 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 4, 5, 6, 7, 8, 11, 12, 22, 23, 15, 16, 26, 27, 13, 24, 30, 31, 40, 41, 42, 35, 45, 36, 51, 52, 53, 54, 70, 71, 72, 73, 74, 75, 123, 76, 90, 77, 104, 105, 106, 107, 108, 44, 48, 60, 61, 62, 63, 64, 85, 91, 65, 98, 99, 115, 116, 100, 101, 119, 127, 137, 138 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { 117, 109, 88, 102, -58, 103, 81, 120, 78, 18, 29, 125, 89, 57, -34, 58, 87, -34, 59, -58, -62, 50, 19, 82, -63, 78, -95, 126, 79, 117, 136, 132, 129, 133, 112, 134, 141, 37, 39, 38, -103, 46, 135, 136, -109, 66, 33, -109, 83, -110, 39, 110, -110, 111, 112, 113, 57, 84, 58, 68, 34, 59, 114, 69, 59, -46, -94, 68, 9, 49, 10, 69, 59, -47, -46, 50, 92, -104, 93, 94, 95, 124, -47, 139, -39, -105, 140, 96, 121, 132, 97, 133, 112, 134, -2, 1, -3, 1, 118, 14, 135, 10, 2, 3, 2, 3, 20, 25, 21, 21, 55, 102, 38, 103, 17, 28, 32, 47, 43, 56, 86, 80, 67, 122, 142, 128, 130, 0, 0, 0, 0, 0, 0, 131 }; static const yytype_int16 yycheck[] = { 97, 91, 1, 1, 3, 3, 1, 1, 54, 0, 13, 1, 11, 1, 14, 3, 18, 17, 6, 18, 18, 7, 5, 18, 18, 71, 16, 17, 16, 126, 127, 1, 122, 3, 4, 5, 1, 1, 14, 3, 13, 17, 12, 140, 14, 16, 1, 17, 1, 14, 14, 1, 17, 3, 4, 5, 1, 10, 3, 1, 15, 6, 12, 5, 6, 7, 16, 1, 1, 1, 3, 5, 6, 7, 16, 7, 1, 13, 3, 4, 5, 16, 16, 14, 16, 13, 17, 12, 17, 1, 15, 3, 4, 5, 0, 1, 0, 1, 13, 1, 12, 3, 8, 9, 8, 9, 1, 1, 3, 3, 1, 1, 3, 3, 3, 15, 26, 41, 32, 46, 71, 60, 52, 108, 140, 121, 123, -1, -1, -1, -1, -1, -1, 126 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 1, 8, 9, 20, 21, 22, 23, 24, 1, 3, 25, 26, 33, 1, 29, 30, 33, 0, 22, 1, 3, 27, 28, 34, 1, 31, 32, 34, 13, 35, 36, 35, 1, 15, 40, 42, 1, 3, 14, 37, 38, 39, 42, 62, 41, 17, 37, 63, 1, 7, 43, 44, 45, 46, 1, 39, 1, 3, 6, 64, 65, 66, 67, 68, 71, 16, 45, 1, 5, 47, 48, 49, 50, 51, 52, 54, 56, 71, 16, 65, 1, 18, 1, 10, 69, 49, 18, 1, 11, 55, 70, 1, 3, 4, 5, 12, 15, 72, 73, 76, 77, 1, 3, 57, 58, 59, 60, 61, 72, 1, 3, 4, 5, 12, 74, 75, 77, 13, 78, 1, 17, 69, 53, 16, 1, 17, 79, 60, 72, 57, 74, 1, 3, 5, 12, 77, 80, 81, 14, 17, 1, 81 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 19, 20, 20, 21, 21, 22, 22, 22, 23, 24, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 35, 35, 36, 37, 38, 38, 39, 39, 41, 40, 42, 42, 43, 43, 44, 44, 44, 45, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51, 51, 53, 52, 55, 54, 56, 56, 57, 57, 57, 58, 59, 59, 60, 61, 61, 63, 62, 64, 64, 65, 65, 66, 66, 67, 68, 68, 69, 69, 70, 71, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74, 74, 74, 75, 75, 75, 75, 75, 76, 76, 76, 77, 79, 78, 80, 80, 80, 80, 81, 81, 81, 81, 81 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 1, 1, 2, 1, 1, 1, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 3, 2, 2, 1, 1, 1, 3, 1, 1, 0, 4, 1, 1, 0, 1, 1, 2, 1, 2, 1, 0, 1, 1, 2, 1, 1, 2, 2, 1, 1, 0, 5, 0, 3, 1, 1, 0, 1, 2, 1, 1, 3, 3, 1, 1, 0, 4, 1, 2, 1, 1, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 4, 0, 1, 3, 2, 1, 1, 1, 1, 1 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (yylen); \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) /* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*----------------------------------------. | Print this symbol's value on YYOUTPUT. | `----------------------------------------*/ static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) { FILE *yyo = yyoutput; YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) { YYFPRINTF (yyoutput, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) { unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyssp, yyvsp, Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T yystrlen (const char *yystr) { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * yystpcpy (char *yydest, const char *yysrc) { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per "expected"). */ int yycount = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; break; } yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } } } } switch (yycount) { # define YYCASE_(N, S) \ case N: \ yyformat = S; \ break YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); # undef YYCASE_ } { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return 1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyformat += 2; } else { yyp++; yyformat++; } } return 0; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); YY_IGNORE_MAYBE_UNINITIALIZED_END } /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ int yyparse (void) { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: 'yyss': related to states. 'yyvs': related to semantic values. Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yyssp = yyss = yyssa; yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = yylex (); } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 8: #line 89 "cf3parse.y" /* yacc.c:1646 */ { ParseError("Expected 'bundle' or 'body' keyword, wrong input '%s'", yytext); YYABORT; } #line 1415 "cf3parse.c" /* yacc.c:1646 */ break; case 11: #line 101 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:bundle:%s\n", P.blocktype); P.block = "bundle"; RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); RlistDestroy(P.currentRlist); P.currentRlist = NULL; if (P.currentstring) { free(P.currentstring); } P.currentstring = NULL; strcpy(P.blockid,""); } #line 1434 "cf3parse.c" /* yacc.c:1646 */ break; case 12: #line 117 "cf3parse.y" /* yacc.c:1646 */ { /* FIXME: We keep it here, because we skip unknown * promise bundles. Ought to be moved to * after-parsing step once we know how to deal with * it */ if (!BundleTypeCheck(P.blocktype)) { ParseError("Unknown bundle type '%s'", P.blocktype); INSTALL_SKIP = true; } } #line 1451 "cf3parse.c" /* yacc.c:1646 */ break; case 13: #line 130 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Expected bundle type, wrong input '%s'", yytext); INSTALL_SKIP = true; } #line 1461 "cf3parse.c" /* yacc.c:1646 */ break; case 14: #line 137 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:bundle:%s:%s\n", P.blocktype, P.blockid); CURRENT_BLOCKID_LINE = P.line_no; } #line 1470 "cf3parse.c" /* yacc.c:1646 */ break; case 16: #line 144 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Expected bundle identifier, wrong input '%s'", yytext); INSTALL_SKIP = true; } #line 1480 "cf3parse.c" /* yacc.c:1646 */ break; case 17: #line 153 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:body:%s\n", P.blocktype); P.block = "body"; strcpy(P.blockid,""); RlistDestroy(P.currentRlist); P.currentRlist = NULL; if (P.currentstring) { free(P.currentstring); } P.currentstring = NULL; } #line 1497 "cf3parse.c" /* yacc.c:1646 */ break; case 18: #line 167 "cf3parse.y" /* yacc.c:1646 */ { if (!BodySyntaxGet(P.blocktype)) { ParseError("Unknown body type '%s'", P.blocktype); } } #line 1508 "cf3parse.c" /* yacc.c:1646 */ break; case 19: #line 174 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Expected body type, wrong input '%s'", yytext); } #line 1517 "cf3parse.c" /* yacc.c:1646 */ break; case 20: #line 180 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:body:%s:%s\n", P.blocktype, P.blockid); CURRENT_BLOCKID_LINE = P.line_no; } #line 1526 "cf3parse.c" /* yacc.c:1646 */ break; case 22: #line 187 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Expected body identifier, wrong input '%s'", yytext); INSTALL_SKIP = true; } #line 1536 "cf3parse.c" /* yacc.c:1646 */ break; case 23: #line 196 "cf3parse.y" /* yacc.c:1646 */ { strncpy(P.blocktype,P.currentid,CF_MAXVARSIZE); RlistDestroy(P.useargs); P.useargs = NULL; } #line 1547 "cf3parse.c" /* yacc.c:1646 */ break; case 24: #line 206 "cf3parse.y" /* yacc.c:1646 */ { strncpy(P.blockid,P.currentid,CF_MAXVARSIZE); P.offsets.last_block_id = P.offsets.last_id; } #line 1556 "cf3parse.c" /* yacc.c:1646 */ break; case 28: #line 217 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Error in bundle parameter list, expected ')', wrong input '%s'", yytext); } #line 1565 "cf3parse.c" /* yacc.c:1646 */ break; case 29: #line 223 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:%s:%s:%s arglist begin:%s\n", P.block,P.blocktype,P.blockid, yytext); } #line 1573 "cf3parse.c" /* yacc.c:1646 */ break; case 30: #line 228 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:%s:%s:%s arglist end:%s\n", P.block,P.blocktype,P.blockid, yytext); } #line 1581 "cf3parse.c" /* yacc.c:1646 */ break; case 33: #line 240 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:%s:%s:%s arg id: %s\n", P.block,P.blocktype,P.blockid, P.currentid); RlistAppendScalar(&(P.useargs),P.currentid); } #line 1590 "cf3parse.c" /* yacc.c:1646 */ break; case 34: #line 245 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Expected identifier, wrong input '%s'", yytext); } #line 1599 "cf3parse.c" /* yacc.c:1646 */ break; case 35: #line 253 "cf3parse.y" /* yacc.c:1646 */ { if (RelevantBundle(CF_AGENTTYPES[P.agent_type], P.blocktype)) { INSTALL_SKIP = false; } else if (strcmp(CF_AGENTTYPES[P.agent_type], P.blocktype) != 0) { INSTALL_SKIP = true; } if (!INSTALL_SKIP) { P.currentbundle = PolicyAppendBundle(P.policy, P.current_namespace, P.blockid, P.blocktype, P.useargs, P.filename); P.currentbundle->offset.line = CURRENT_BLOCKID_LINE; P.currentbundle->offset.start = P.offsets.last_block_id; } else { P.currentbundle = NULL; } RlistDestroy(P.useargs); P.useargs = NULL; } #line 1628 "cf3parse.c" /* yacc.c:1646 */ break; case 36: #line 281 "cf3parse.y" /* yacc.c:1646 */ { INSTALL_SKIP = false; P.offsets.last_id = -1; P.offsets.last_string = -1; P.offsets.last_class_id = -1; if (P.currentbundle) { P.currentbundle->offset.end = P.offsets.current; } } #line 1644 "cf3parse.c" /* yacc.c:1646 */ break; case 37: #line 296 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:%s:%s:%s begin body open\n", P.block,P.blocktype,P.blockid); } #line 1652 "cf3parse.c" /* yacc.c:1646 */ break; case 38: #line 300 "cf3parse.y" /* yacc.c:1646 */ { ParseError("Expected body open '{', wrong input '%s'", yytext); } #line 1660 "cf3parse.c" /* yacc.c:1646 */ break; case 43: #line 315 "cf3parse.y" /* yacc.c:1646 */ { INSTALL_SKIP = true; ParseError("Expected promise type, got '%s'", yytext); ParserDebug("P:promise_type:error yychar = %d, %c, yyempty = %d\n", yychar, yychar, YYEMPTY); yyclearin; } #line 1671 "cf3parse.c" /* yacc.c:1646 */ break; case 45: #line 330 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s promise_type = %s\n", P.block, P.blocktype, P.blockid, P.currenttype); const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(P.blocktype, P.currenttype); if (promise_type_syntax) { switch (promise_type_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated promise type '%s' in bundle type '%s'", promise_type_syntax->promise_type, promise_type_syntax->bundle_type); // Intentional fall case SYNTAX_STATUS_NORMAL: if (strcmp(P.block, "bundle") == 0) { if (!INSTALL_SKIP) { P.currentstype = BundleAppendPromiseType(P.currentbundle,P.currenttype); P.currentstype->offset.line = P.line_no; P.currentstype->offset.start = P.offsets.last_promise_type_id; } else { P.currentstype = NULL; } } break; case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed promise type '%s' in bundle type '%s'", promise_type_syntax->promise_type, promise_type_syntax->bundle_type); INSTALL_SKIP = true; break; } } else { ParseError("Unknown promise type '%s'", P.currenttype); INSTALL_SKIP = true; } } #line 1715 "cf3parse.c" /* yacc.c:1646 */ break; case 53: #line 390 "cf3parse.y" /* yacc.c:1646 */ { /* * Based on yychar display right error message */ ParserDebug("P:promiser:error yychar = %d\n", yychar); if (yychar =='-' || yychar == '>') { ParseError("Expected '->', got '%s'", yytext); } else if (yychar == IDSYNTAX) { ParseError("Expected attribute, got '%s'", yytext); } else if (yychar == ',') { ParseError("Expected attribute, got '%s' (comma after promiser is not allowed since 3.5.0)", yytext); } else { ParseError("Expected ';', got '%s'", yytext); } yyclearin; } #line 1743 "cf3parse.c" /* yacc.c:1646 */ break; case 56: #line 425 "cf3parse.y" /* yacc.c:1646 */ { if (!INSTALL_SKIP) { if (!P.currentstype) { ParseError("Missing promise type declaration"); } P.currentpromise = PromiseTypeAppendPromise(P.currentstype, P.promiser, RvalCopy(P.rval), P.currentclasses ? P.currentclasses : "any"); P.currentpromise->offset.line = CURRENT_PROMISER_LINE; P.currentpromise->offset.start = P.offsets.last_string; P.currentpromise->offset.context = P.offsets.last_class_id; } else { P.currentpromise = NULL; } } #line 1768 "cf3parse.c" /* yacc.c:1646 */ break; case 58: #line 451 "cf3parse.y" /* yacc.c:1646 */ { if (!INSTALL_SKIP) { if (!P.currentstype) { ParseError("Missing promise type declaration"); } P.currentpromise = PromiseTypeAppendPromise(P.currentstype, P.promiser, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, P.currentclasses ? P.currentclasses : "any"); P.currentpromise->offset.line = CURRENT_PROMISER_LINE; P.currentpromise->offset.start = P.offsets.last_string; P.currentpromise->offset.context = P.offsets.last_class_id; } else { P.currentpromise = NULL; } } #line 1794 "cf3parse.c" /* yacc.c:1646 */ break; case 60: #line 478 "cf3parse.y" /* yacc.c:1646 */ { if (P.promiser) { free(P.promiser); } P.promiser = P.currentstring; P.currentstring = NULL; CURRENT_PROMISER_LINE = P.line_no; ParserDebug("\tP:%s:%s:%s:%s:%s promiser = %s\n", P.block, P.blocktype, P.blockid, P.currenttype, P.currentclasses ? P.currentclasses : "any", P.promiser); } #line 1809 "cf3parse.c" /* yacc.c:1646 */ break; case 61: #line 489 "cf3parse.y" /* yacc.c:1646 */ { INSTALL_SKIP = true; ParserDebug("P:promiser:qstring::error yychar = %d\n", yychar); if (yychar == BUNDLE || yychar == BODY || yychar == YYEOF) { ParseError("Expected '}', got '%s'", yytext); /* YYABORT; */ } else { ParseError("Expected promiser string, got '%s'", yytext); } yyclearin; } #line 1832 "cf3parse.c" /* yacc.c:1646 */ break; case 64: #line 513 "cf3parse.y" /* yacc.c:1646 */ { /* * Based on next token id display right error message */ ParserDebug("P:constraints_decl:error yychar = %d\n", yychar); if ( yychar == IDSYNTAX ) { ParseError("Check previous line, Expected ',', got '%s'", yytext); } else { ParseError("Check previous line, Expected ';', got '%s'", yytext); } yyclearin; } #line 1853 "cf3parse.c" /* yacc.c:1646 */ break; case 65: #line 534 "cf3parse.y" /* yacc.c:1646 */ { /* Don't free these */ strcpy(P.currentid,""); RlistDestroy(P.currentRlist); P.currentRlist = NULL; free(P.promiser); if (P.currentstring) { free(P.currentstring); } P.currentstring = NULL; P.promiser = NULL; P.promisee = NULL; /* reset argptrs etc*/ } #line 1873 "cf3parse.c" /* yacc.c:1646 */ break; case 68: #line 561 "cf3parse.y" /* yacc.c:1646 */ { if (!INSTALL_SKIP) { const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(P.blocktype, P.currenttype); assert(promise_type_syntax); const ConstraintSyntax *constraint_syntax = PromiseTypeSyntaxGetConstraintSyntax(promise_type_syntax, P.lval); if (constraint_syntax) { switch (constraint_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated constraint '%s' in promise type '%s'", constraint_syntax->lval, promise_type_syntax->promise_type); // Intentional fall case SYNTAX_STATUS_NORMAL: { { SyntaxTypeMatch err = CheckConstraint(P.currenttype, P.lval, P.rval, promise_type_syntax); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { yyerror(SyntaxTypeMatchToString(err)); } } if (P.rval.type == RVAL_TYPE_SCALAR && strcmp(P.lval, "ifvarclass") == 0) { ValidateClassLiteral(P.rval.item); } Constraint *cp = PromiseAppendConstraint(P.currentpromise, P.lval, RvalCopy(P.rval), P.references_body); cp->offset.line = P.line_no; cp->offset.start = P.offsets.last_id; cp->offset.end = P.offsets.current; cp->offset.context = P.offsets.last_class_id; P.currentstype->offset.end = P.offsets.current; // Cache whether there are subbundles for later $(this.promiser) logic if (strcmp(P.lval,"usebundle") == 0 || strcmp(P.lval,"edit_line") == 0 || strcmp(P.lval,"edit_xml") == 0 || strcmp(P.lval,"home_bundle") == 0) { P.currentpromise->has_subbundles = true; } } break; case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed constraint '%s' in promise type '%s'", constraint_syntax->lval, promise_type_syntax->promise_type); break; } } else { ParseError("Unknown constraint '%s' in promise type '%s'", P.lval, promise_type_syntax->promise_type); } RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); strcpy(P.lval,"no lval"); RlistDestroy(P.currentRlist); P.currentRlist = NULL; } else { RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } } #line 1945 "cf3parse.c" /* yacc.c:1646 */ break; case 69: #line 632 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s:%s:%s attribute = %s\n", P.block, P.blocktype, P.blockid, P.currenttype, P.currentclasses ? P.currentclasses : "any", P.promiser, P.currentid); const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(P.blocktype, P.currenttype); if (!promise_type_syntax) { ParseError("Invalid promise type '%s' in bundle '%s' of type '%s'", P.currenttype, P.blockid, P.blocktype); INSTALL_SKIP = true; } else if (!PromiseTypeSyntaxGetConstraintSyntax(promise_type_syntax, P.currentid)) { ParseError("Unknown attribute '%s' for promise type '%s' in bundle with type '%s'", P.currentid, P.currenttype, P.blocktype); INSTALL_SKIP = true; } strncpy(P.lval,P.currentid,CF_MAXVARSIZE); RlistDestroy(P.currentRlist); P.currentRlist = NULL; } #line 1969 "cf3parse.c" /* yacc.c:1646 */ break; case 70: #line 652 "cf3parse.y" /* yacc.c:1646 */ { ParseError("Expected attribute, got '%s'\n", yytext); } #line 1977 "cf3parse.c" /* yacc.c:1646 */ break; case 71: #line 659 "cf3parse.y" /* yacc.c:1646 */ { const BodySyntax *body_syntax = BodySyntaxGet(P.blocktype); if (body_syntax) { INSTALL_SKIP = false; switch (body_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated body '%s' of type '%s'", P.blockid, body_syntax->body_type); // intentional fall case SYNTAX_STATUS_NORMAL: P.currentbody = PolicyAppendBody(P.policy, P.current_namespace, P.blockid, P.blocktype, P.useargs, P.filename); P.currentbody->offset.line = CURRENT_BLOCKID_LINE; P.currentbody->offset.start = P.offsets.last_block_id; break; case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed body '%s' of type '%s'", P.blockid, body_syntax->body_type); INSTALL_SKIP = true; break; } } else { ParseError("Invalid body type '%s'", P.blocktype); INSTALL_SKIP = true; } RlistDestroy(P.useargs); P.useargs = NULL; strcpy(P.currentid,""); } #line 2017 "cf3parse.c" /* yacc.c:1646 */ break; case 72: #line 698 "cf3parse.y" /* yacc.c:1646 */ { P.offsets.last_id = -1; P.offsets.last_string = -1; P.offsets.last_class_id = -1; if (P.currentbody) { P.currentbody->offset.end = P.offsets.current; } } #line 2031 "cf3parse.c" /* yacc.c:1646 */ break; case 78: #line 722 "cf3parse.y" /* yacc.c:1646 */ { ParseError("Expected ';' check previous statement, got '%s'", yytext); } #line 2039 "cf3parse.c" /* yacc.c:1646 */ break; case 79: #line 731 "cf3parse.y" /* yacc.c:1646 */ { if (!INSTALL_SKIP) { const BodySyntax *body_syntax = BodySyntaxGet(P.blocktype); assert(body_syntax); const ConstraintSyntax *constraint_syntax = BodySyntaxGetConstraintSyntax(body_syntax->constraints, P.lval); if (constraint_syntax) { switch (constraint_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated constraint '%s' in body type '%s'", constraint_syntax->lval, body_syntax->body_type); // Intentional fall case SYNTAX_STATUS_NORMAL: { SyntaxTypeMatch err = CheckSelection(P.blocktype, P.blockid, P.lval, P.rval); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { yyerror(SyntaxTypeMatchToString(err)); } if (P.rval.type == RVAL_TYPE_SCALAR && strcmp(P.lval, "ifvarclass") == 0) { ValidateClassLiteral(P.rval.item); } Constraint *cp = NULL; if (P.currentclasses == NULL) { cp = BodyAppendConstraint(P.currentbody, P.lval, RvalCopy(P.rval), "any", P.references_body); } else { cp = BodyAppendConstraint(P.currentbody, P.lval, RvalCopy(P.rval), P.currentclasses, P.references_body); } cp->offset.line = P.line_no; cp->offset.start = P.offsets.last_id; cp->offset.end = P.offsets.current; cp->offset.context = P.offsets.last_class_id; break; } case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed constraint '%s' in promise type '%s'", constraint_syntax->lval, body_syntax->body_type); break; } } } else { RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } if (strcmp(P.blockid,"control") == 0 && strcmp(P.blocktype,"file") == 0) { if (strcmp(P.lval,"namespace") == 0) { if (P.rval.type != RVAL_TYPE_SCALAR) { yyerror("namespace must be a constant scalar string"); } else { free(P.current_namespace); P.current_namespace = xstrdup(P.rval.item); } } } RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } #line 2118 "cf3parse.c" /* yacc.c:1646 */ break; case 80: #line 809 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s attribute = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); if (!INSTALL_SKIP) { const BodySyntax *body_syntax = BodySyntaxGet(P.currentbody->type); if (!body_syntax || !BodySyntaxGetConstraintSyntax(body_syntax->constraints, P.currentid)) { ParseError("Unknown selection '%s' for body type '%s'", P.currentid, P.currentbody->type); INSTALL_SKIP = true; } strncpy(P.lval,P.currentid,CF_MAXVARSIZE); } RlistDestroy(P.currentRlist); P.currentRlist = NULL; } #line 2141 "cf3parse.c" /* yacc.c:1646 */ break; case 81: #line 828 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:selection_id:idsyntax:error yychar = %d\n", yychar); if ( yychar == BUNDLE || yychar == BODY || yychar == YYEOF ) { ParseError("Expected '}', got '%s'", yytext); /* YYABORT; */ } else { ParseError("Expected attribute, got '%s'", yytext); } yyclearin; } #line 2163 "cf3parse.c" /* yacc.c:1646 */ break; case 82: #line 849 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:=>\n"); } #line 2171 "cf3parse.c" /* yacc.c:1646 */ break; case 83: #line 853 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Expected '=>', got '%s'", yytext); } #line 2180 "cf3parse.c" /* yacc.c:1646 */ break; case 84: #line 861 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:->\n"); } #line 2188 "cf3parse.c" /* yacc.c:1646 */ break; case 85: #line 875 "cf3parse.y" /* yacc.c:1646 */ { P.offsets.last_class_id = P.offsets.current - strlen(P.currentclasses) - 2; ParserDebug("\tP:%s:%s:%s:%s class = %s\n", P.block, P.blocktype, P.blockid, P.currenttype, yytext); /* class literal includes terminating :: */ /* Warning : AIX does not like yylen */ char *literal = xstrndup(yytext, strlen(yytext) - 2); ValidateClassLiteral(literal); free(literal); } #line 2205 "cf3parse.c" /* yacc.c:1646 */ break; case 86: #line 895 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s id rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentid); RvalDestroy(P.rval); P.rval = (Rval) { xstrdup(P.currentid), RVAL_TYPE_SCALAR }; P.references_body = true; } #line 2216 "cf3parse.c" /* yacc.c:1646 */ break; case 87: #line 902 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s blockid rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentid); RvalDestroy(P.rval); P.rval = (Rval) { xstrdup(P.currentid), RVAL_TYPE_SCALAR }; P.references_body = true; } #line 2227 "cf3parse.c" /* yacc.c:1646 */ break; case 88: #line 909 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s qstring rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentstring); RvalDestroy(P.rval); P.rval = (Rval) { P.currentstring, RVAL_TYPE_SCALAR }; P.currentstring = NULL; P.references_body = false; if (P.currentpromise) { if (LvalWantsBody(P.currentpromise->parent_promise_type->name, P.lval)) { yyerror("An rvalue is quoted, but we expect an unquoted body identifier"); } } } #line 2248 "cf3parse.c" /* yacc.c:1646 */ break; case 89: #line 926 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s nakedvar rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentstring); RvalDestroy(P.rval); P.rval = (Rval) { P.currentstring, RVAL_TYPE_SCALAR }; P.currentstring = NULL; P.references_body = false; } #line 2261 "cf3parse.c" /* yacc.c:1646 */ break; case 90: #line 935 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s install list = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval); if (RlistLen(P.currentRlist) == 0) { RlistAppendScalar(&P.currentRlist, CF_NULL_VALUE); } RvalDestroy(P.rval); P.rval = (Rval) { RlistCopy(P.currentRlist), RVAL_TYPE_LIST }; RlistDestroy(P.currentRlist); P.currentRlist = NULL; P.references_body = false; } #line 2278 "cf3parse.c" /* yacc.c:1646 */ break; case 91: #line 948 "cf3parse.y" /* yacc.c:1646 */ { RvalDestroy(P.rval); P.rval = (Rval) { P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL }; P.currentfncall[P.arg_nesting+1] = NULL; P.references_body = false; } #line 2289 "cf3parse.c" /* yacc.c:1646 */ break; case 92: #line 956 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Invalid r-value type '%s'", yytext); } #line 2298 "cf3parse.c" /* yacc.c:1646 */ break; case 97: #line 971 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:rval:list:error yychar = %d\n", yychar); if ( yychar ==';' ) { ParseError("Expected '}', wrong input '%s'", yytext); } else if ( yychar == ASSIGN ) { ParseError("Check list statement previous line, Expected '}', wrong input '%s'", yytext); } else { ParseError("Expected ',', wrong input '%s'", yytext); } yyclearin; } #line 2319 "cf3parse.c" /* yacc.c:1646 */ break; case 98: #line 991 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s list append; id = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); RlistAppendScalar((Rlist **)&P.currentRlist, P.currentid); } #line 2328 "cf3parse.c" /* yacc.c:1646 */ break; case 99: #line 997 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s list append: qstring = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentstring); RlistAppendScalar((Rlist **)&P.currentRlist,(void *)P.currentstring); free(P.currentstring); P.currentstring = NULL; } #line 2339 "cf3parse.c" /* yacc.c:1646 */ break; case 100: #line 1005 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s list append: nakedvar = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentstring); RlistAppendScalar((Rlist **)&P.currentRlist,(void *)P.currentstring); free(P.currentstring); P.currentstring = NULL; } #line 2350 "cf3parse.c" /* yacc.c:1646 */ break; case 101: #line 1013 "cf3parse.y" /* yacc.c:1646 */ { RlistAppend(&P.currentRlist, P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL); FnCallDestroy(P.currentfncall[P.arg_nesting+1]); P.currentfncall[P.arg_nesting+1] = NULL; } #line 2360 "cf3parse.c" /* yacc.c:1646 */ break; case 102: #line 1020 "cf3parse.y" /* yacc.c:1646 */ { yyclearin; ParseError("Invalid input for a list item, got '%s'", yytext); } #line 2369 "cf3parse.c" /* yacc.c:1646 */ break; case 103: #line 1028 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s function id = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); } #line 2377 "cf3parse.c" /* yacc.c:1646 */ break; case 104: #line 1032 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s function blockid = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); } #line 2385 "cf3parse.c" /* yacc.c:1646 */ break; case 105: #line 1036 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s function nakedvar = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentstring); strncpy(P.currentid,P.currentstring,CF_MAXVARSIZE); // Make a var look like an ID free(P.currentstring); P.currentstring = NULL; } #line 2396 "cf3parse.c" /* yacc.c:1646 */ break; case 106: #line 1049 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s Finished with function, now at level %d\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.arg_nesting); } #line 2404 "cf3parse.c" /* yacc.c:1646 */ break; case 107: #line 1056 "cf3parse.y" /* yacc.c:1646 */ { if (++P.arg_nesting >= CF_MAX_NESTING) { fatal_yyerror("Nesting of functions is deeper than recommended"); } P.currentfnid[P.arg_nesting] = xstrdup(P.currentid); ParserDebug("\tP:%s:%s:%s begin givearglist for function %s, level %d\n", P.block,P.blocktype,P.blockid, P.currentfnid[P.arg_nesting], P.arg_nesting ); } #line 2417 "cf3parse.c" /* yacc.c:1646 */ break; case 108: #line 1068 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s end givearglist for function %s, level %d\n", P.block,P.blocktype,P.blockid, P.currentfnid[P.arg_nesting], P.arg_nesting ); P.currentfncall[P.arg_nesting] = FnCallNew(P.currentfnid[P.arg_nesting], P.giveargs[P.arg_nesting]); P.giveargs[P.arg_nesting] = NULL; strcpy(P.currentid,""); free(P.currentfnid[P.arg_nesting]); P.currentfnid[P.arg_nesting] = NULL; P.arg_nesting--; } #line 2431 "cf3parse.c" /* yacc.c:1646 */ break; case 112: #line 1085 "cf3parse.y" /* yacc.c:1646 */ { ParseError("Expected ',', wrong input '%s'", yytext); yyclearin; } #line 2440 "cf3parse.c" /* yacc.c:1646 */ break; case 113: #line 1093 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("\tP:%s:%s:%s:%s function %s, id arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentid); /* currently inside a use function */ RlistAppendScalar(&P.giveargs[P.arg_nesting],P.currentid); } #line 2450 "cf3parse.c" /* yacc.c:1646 */ break; case 114: #line 1100 "cf3parse.y" /* yacc.c:1646 */ { /* currently inside a use function */ ParserDebug("\tP:%s:%s:%s:%s function %s, qstring arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentstring); RlistAppendScalar(&P.giveargs[P.arg_nesting],P.currentstring); free(P.currentstring); P.currentstring = NULL; } #line 2462 "cf3parse.c" /* yacc.c:1646 */ break; case 115: #line 1109 "cf3parse.y" /* yacc.c:1646 */ { /* currently inside a use function */ ParserDebug("\tP:%s:%s:%s:%s function %s, nakedvar arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentstring); RlistAppendScalar(&P.giveargs[P.arg_nesting],P.currentstring); free(P.currentstring); P.currentstring = NULL; } #line 2474 "cf3parse.c" /* yacc.c:1646 */ break; case 116: #line 1118 "cf3parse.y" /* yacc.c:1646 */ { /* Careful about recursion */ ParserDebug("\tP:%s:%s:%s:%s function %s, nakedvar arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentstring); RlistAppend(&P.giveargs[P.arg_nesting], P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL); RvalDestroy((Rval) { P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL }); P.currentfncall[P.arg_nesting+1] = NULL; } #line 2486 "cf3parse.c" /* yacc.c:1646 */ break; case 117: #line 1127 "cf3parse.y" /* yacc.c:1646 */ { ParserDebug("P:rval:function:gaitem:error yychar = %d\n", yychar); if (yychar == ';') { ParseError("Expected ')', wrong input '%s'", yytext); } else if (yychar == ASSIGN ) { ParseError("Check function statement previous line, Expected ')', wrong input '%s'", yytext); } else { ParseError("Invalid function argument, wrong input '%s'", yytext); } yyclearin; } #line 2507 "cf3parse.c" /* yacc.c:1646 */ break; #line 2511 "cf3parse.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) { char const *yymsgp = YY_("syntax error"); int yysyntax_error_status; yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; yysyntax_error_status = 2; } else { yysyntax_error_status = YYSYNTAX_ERROR; yymsgp = yymsg; } } yyerror (yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } # undef YYSYNTAX_ERROR #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif return yyresult; } #line 1144 "cf3parse.y" /* yacc.c:1906 */ /*****************************************************************/ static void ParseErrorVColumnOffset(int column_offset, const char *s, va_list ap) { char *errmsg = StringVFormat(s, ap); fprintf(stderr, "%s:%d:%d: error: %s\n", P.filename, P.line_no, P.line_pos + column_offset, errmsg); free(errmsg); /* FIXME: why this might be NULL? */ if (P.current_line) { fprintf(stderr, "%s\n", P.current_line); fprintf(stderr, "%*s\n", P.line_pos + column_offset, "^"); P.error_count++; if (P.error_count > 12) { fprintf(stderr, "Too many errors\n"); exit(EXIT_FAILURE); } } } static void ParseErrorColumnOffset(int column_offset, const char *s, ...) { va_list ap; va_start(ap, s); ParseErrorVColumnOffset(column_offset, s, ap); va_end(ap); } static void ParseErrorV(const char *s, va_list ap) { ParseErrorVColumnOffset(0, s, ap); } static void ParseError(const char *s, ...) { va_list ap; va_start(ap, s); ParseErrorV(s, ap); va_end(ap); } static void ParseWarningV(unsigned int warning, const char *s, va_list ap) { if (((P.warnings | P.warnings_error) & warning) == 0) { return; } char *errmsg = StringVFormat(s, ap); const char *warning_str = ParserWarningToString(warning); fprintf(stderr, "%s:%d:%d: warning: %s [-W%s]\n", P.filename, P.line_no, P.line_pos, errmsg, warning_str); fprintf(stderr, "%s\n", P.current_line); fprintf(stderr, "%*s\n", P.line_pos, "^"); free(errmsg); P.warning_count++; if ((P.warnings_error & warning) != 0) { P.error_count++; } if (P.error_count > 12) { fprintf(stderr, "Too many errors\n"); exit(EXIT_FAILURE); } } static void ParseWarning(unsigned int warning, const char *s, ...) { va_list ap; va_start(ap, s); ParseWarningV(warning, s, ap); va_end(ap); } void yyerror(const char *str) { ParseError("%s", str); } static void fatal_yyerror(const char *s) { char *sp = yytext; /* Skip quotation mark */ if (sp && *sp == '\"' && sp[1]) { sp++; } fprintf(stderr, "%s: %d,%d: Fatal error during parsing: %s, near token \'%.20s\'\n", P.filename, P.line_no, P.line_pos, s, sp ? sp : "NULL"); exit(EXIT_FAILURE); } static int RelevantBundle(const char *agent, const char *blocktype) { if ((strcmp(agent, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0) || (strcmp(CF_COMMONC, blocktype) == 0)) { return true; } /* Here are some additional bundle types handled by cfAgent */ Item *ip = SplitString("edit_line,edit_xml", ','); if (strcmp(agent, CF_AGENTTYPES[AGENT_TYPE_AGENT]) == 0) { if (IsItemIn(ip, blocktype)) { DeleteItemList(ip); return true; } } DeleteItemList(ip); return false; } static bool LvalWantsBody(char *stype, char *lval) { for (int i = 0; i < CF3_MODULES; i++) { const PromiseTypeSyntax *promise_type_syntax = CF_ALL_PROMISE_TYPES[i]; if (!promise_type_syntax) { continue; } for (int j = 0; promise_type_syntax[j].promise_type != NULL; j++) { const ConstraintSyntax *bs = promise_type_syntax[j].constraints; if (!bs) { continue; } if (strcmp(promise_type_syntax[j].promise_type, stype) != 0) { continue; } for (int l = 0; bs[l].lval != NULL; l++) { if (strcmp(bs[l].lval, lval) == 0) { if (bs[l].dtype == CF_DATA_TYPE_BODY) { return true; } else { return false; } } } } } return false; } static SyntaxTypeMatch CheckSelection(const char *type, const char *name, const char *lval, Rval rval) { // Check internal control bodies etc if (strcmp("control", name) == 0) { for (int i = 0; CONTROL_BODIES[i].body_type != NULL; i++) { if (strcmp(type, CONTROL_BODIES[i].body_type) == 0) { const ConstraintSyntax *bs = CONTROL_BODIES[i].constraints; for (int l = 0; bs[l].lval != NULL; l++) { if (strcmp(lval, bs[l].lval) == 0) { if (bs[l].dtype == CF_DATA_TYPE_BODY) { return SYNTAX_TYPE_MATCH_OK; } else if (bs[l].dtype == CF_DATA_TYPE_BUNDLE) { return SYNTAX_TYPE_MATCH_OK; } else { return CheckConstraintTypeMatch(lval, rval, bs[l].dtype, bs[l].range.validation_string, 0); } } } } } } // Now check the functional modules - extra level of indirection for (int i = 0; i < CF3_MODULES; i++) { const PromiseTypeSyntax *promise_type_syntax = CF_ALL_PROMISE_TYPES[i]; if (!promise_type_syntax) { continue; } for (int j = 0; promise_type_syntax[j].promise_type != NULL; j++) { const ConstraintSyntax *bs = bs = promise_type_syntax[j].constraints; if (!bs) { continue; } for (int l = 0; bs[l].lval != NULL; l++) { if (bs[l].dtype == CF_DATA_TYPE_BODY) { const ConstraintSyntax *bs2 = bs[l].range.body_type_syntax->constraints; if (bs2 == NULL || bs2 == (void *) CF_BUNDLE) { continue; } for (int k = 0; bs2[k].dtype != CF_DATA_TYPE_NONE; k++) { /* Either module defined or common */ if (strcmp(promise_type_syntax[j].promise_type, type) == 0 && strcmp(promise_type_syntax[j].promise_type, "*") != 0) { char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "lval %s belongs to promise type '%s': but this is '%s'\n", lval, promise_type_syntax[j].promise_type, type); yyerror(output); return SYNTAX_TYPE_MATCH_OK; } if (strcmp(lval, bs2[k].lval) == 0) { return CheckConstraintTypeMatch(lval, rval, bs2[k].dtype, bs2[k].range.validation_string, 0); } } } } } } char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "Constraint lvalue \"%s\" is not allowed in \'%s\' constraint body", lval, type); yyerror(output); return SYNTAX_TYPE_MATCH_OK; // TODO: OK? } static SyntaxTypeMatch CheckConstraint(const char *type, const char *lval, Rval rval, const PromiseTypeSyntax *promise_type_syntax) { assert(promise_type_syntax); if (promise_type_syntax->promise_type != NULL) /* In a bundle */ { if (strcmp(promise_type_syntax->promise_type, type) == 0) { const ConstraintSyntax *bs = promise_type_syntax->constraints; for (int l = 0; bs[l].lval != NULL; l++) { if (strcmp(lval, bs[l].lval) == 0) { /* If we get here we have found the lval and it is valid for this promise_type */ /* For bodies and bundles definitions can be elsewhere, so they are checked in PolicyCheckRunnable(). */ if (bs[l].dtype != CF_DATA_TYPE_BODY && bs[l].dtype != CF_DATA_TYPE_BUNDLE) { return CheckConstraintTypeMatch(lval, rval, bs[l].dtype, bs[l].range.validation_string, 0); } } } } } return SYNTAX_TYPE_MATCH_OK; } static void ValidateClassLiteral(const char *class_literal) { ParseResult res = ParseExpression(class_literal, 0, strlen(class_literal)); if (!res.result) { ParseErrorColumnOffset(res.position - strlen(class_literal), "Syntax error in context string"); } FreeExpression(res.result); } cfengine-3.6.2/libpromises/extensions.c0000664000175100017510000001360612400110676017714 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include /* * A note regarding the loading of the extension plugins: * * The extension plugin was originally statically linked into each agent, * but was then refactored into plugins. * Therefore, since it hasn't been written according to plugin guidelines, * it is not safe to assume that we can unload it once we have * loaded it, since it may allocate resources that are not freed. It is also * not safe to assume that we can load it after initialization is complete * (for example if the plugin is dropped into the directory after cf-serverd * has already been running for some time), because some data structures may * not have been initialized. * * Therefore, the load strategy is as follows: * * - If we find the plugin immediately, load it, and keep it loaded. * * - If we don't find the plugin, NEVER attempt to load it again afterwards. * * - Never unload the plugin. * * - Any installation/upgrade/removal of the plugin requires daemon restarts. * * - The exception is for testing (see getenv below). */ #ifndef BUILTIN_EXTENSIONS static bool enable_extension_libraries = true; /* GLOBAL_X */ static bool attempted_loading = false; /* GLOBAL_X */ void extension_libraries_disable() { if (attempted_loading) { ProgrammingError("extension_libraries_disable() MUST be called before any call to extension functions"); } enable_extension_libraries = false; } void *extension_library_open(const char *name) { if (!enable_extension_libraries) { return NULL; } if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") == NULL) { // Only do loading checks if we are not doing tests. attempted_loading = true; } const char *dirs_to_try[3] = { NULL }; const char *dir = getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DIR"); char lib[] = "/lib"; if (dir) { lib[0] = '\0'; dirs_to_try[0] = dir; } else { dirs_to_try[0] = GetWorkDir(); if (strcmp(WORKDIR, dirs_to_try[0]) != 0) { // try to load from the real WORKDIR in case GetWorkDir returned the local workdir to the user // We try this because enterprise "make install" is in WORKDIR, not per user dirs_to_try[1] = WORKDIR; } } void *handle = NULL; for (int i = 0; dirs_to_try[i]; i++) { char path[strlen(dirs_to_try[i]) + strlen(lib) + strlen(name) + 2]; xsnprintf(path, sizeof(path), "%s%s/%s", dirs_to_try[i], lib, name); Log(LOG_LEVEL_DEBUG, "Trying to shlib_open extension plugin '%s' from '%s'", name, path); handle = shlib_open(path); if (handle) { Log(LOG_LEVEL_VERBOSE, "Successfully opened extension plugin '%s' from '%s'", name, path); break; } else { const char *error; if (errno == ENOENT) { error = "(not installed)"; } else { error = GetErrorStr(); } Log(LOG_LEVEL_VERBOSE, "Could not open extension plugin '%s' from '%s': %s", name, path, error); } } if (!handle) { return handle; } // Version check, to avoid binary incompatible plugins. const char * (*GetExtensionLibraryVersion)() = shlib_load(handle, "GetExtensionLibraryVersion"); if (!GetExtensionLibraryVersion) { Log(LOG_LEVEL_ERR, "Could not retreive version from extension plugin (%s). Not loading the plugin.", name); goto close_and_fail; } const char *plugin_version = GetExtensionLibraryVersion(); unsigned int bin_major, bin_minor, bin_patch; unsigned int plug_major, plug_minor, plug_patch; if (sscanf(VERSION, "%u.%u.%u", &bin_major, &bin_minor, &bin_patch) != 3) { Log(LOG_LEVEL_ERR, "Not able to extract version number from binary (%s). Not loading extension plugin.", name); goto close_and_fail; } if (sscanf(plugin_version, "%u.%u.%u", &plug_major, &plug_minor, &plug_patch) != 3) { Log(LOG_LEVEL_ERR, "Not able to extract version number from plugin (%s). Not loading extension plugin.", name); goto close_and_fail; } if (bin_major != plug_major || bin_minor != plug_minor || bin_patch != plug_patch) { Log(LOG_LEVEL_ERR, "Extension plugin version does not match CFEngine Community version " "(CFEngine Community v%u.%u.%u, Extension (%s) v%u.%u.%u). Refusing to load it.", bin_major, bin_minor, bin_patch, name, plug_major, plug_minor, plug_patch); goto close_and_fail; } Log(LOG_LEVEL_VERBOSE, "Successfully loaded extension plugin '%s'", name); return handle; close_and_fail: shlib_close(handle); return NULL; } void extension_library_close(void *handle) { shlib_close(handle); } #endif // !BUILTIN_EXTENSIONS cfengine-3.6.2/libpromises/mod_packages.h0000664000175100017510000000217312243421446020141 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_PACKAGES_H #define CFENGINE_MOD_PACKAGES_H #include extern const PromiseTypeSyntax CF_PACKAGES_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/matching.h0000664000175100017510000000342012400110676017305 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MATCHING_H #define CFENGINE_MATCHING_H #include int IsRegex(const char *str); /* Pure */ int IsRegexItemIn(EvalContext *ctx, const Item *list, const char *regex); /* Uses context */ char *ExtractFirstReference(const char *regexp, const char *teststring); /* Pure, not thread-safe */ int IsPathRegex(const char *str); /* Pure */ bool HasRegexMetaChars(const char *string); void EscapeRegexChars(char *str, char *strEsc, int strEscSz); /* Pure */ void EscapeSpecialChars(const char *str, char *strEsc, int strEscSz, char *noEscseq, char *noEsclist); /* Pure */ char *EscapeChar(char *str, int strSz, char esc); /* Pure */ void AnchorRegex(const char *regex, char *out, int outSz); /* Pure */ /** result is malloced */ char *AnchorRegexNew(const char *regex); #endif // MATCHING_H cfengine-3.6.2/libpromises/addr_lib.h0000644000175100017510000000266212316547775017304 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ADDR_LIB_H #define CFENGINE_ADDR_LIB_H #include bool IsLoopbackAddress(const char *address); int FuzzySetMatch(const char *s1, const char *s2); bool FuzzyHostParse(const char *arg2); int FuzzyHostMatch(const char *arg0, const char *arg1, const char *basename); bool FuzzyMatchParse(const char *item); bool IsInterfaceAddress(const Item *ip_addresses, const char *adr); void ParseHostPort(char *s, char **hostname, char **port); #endif cfengine-3.6.2/libpromises/shared_lib.h0000664000175100017510000000224212243421446017615 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef SHARED_LIB_H #define SHARED_LIB_H void *shlib_open(const char *lib_name); void *shlib_load(void *handle, const char *symbol_name); void shlib_close(void *handle); #endif // SHARED_LIB_H cfengine-3.6.2/libpromises/conversion.c0000664000175100017510000006574312411001073017703 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include static int IsSpace(char *remainder); /***************************************************************/ const char *MapAddress(const char *unspec_address) { /* Is the address a mapped ipv4 over ipv6 address */ if (strncmp(unspec_address, "::ffff:", 7) == 0) { return unspec_address + 7; } else { return unspec_address; } } int FindTypeInArray(const char *const haystack[], const char *needle, int default_value, int null_value) { if (needle == NULL) { return null_value; } for (int i = 0; haystack[i] != NULL; ++i) { if (strcmp(needle, haystack[i]) == 0) { return i; } } return default_value; } MeasurePolicy MeasurePolicyFromString(const char *s) { static const char *const MEASURE_POLICY_TYPES[] = { "average", "sum", "first", "last", NULL }; return FindTypeInArray(MEASURE_POLICY_TYPES, s, MEASURE_POLICY_AVERAGE, MEASURE_POLICY_NONE); } EnvironmentState EnvironmentStateFromString(const char *s) { static const char *const ENV_STATE_TYPES[] = { "create", "delete", "running", "suspended", "down", NULL }; return FindTypeInArray(ENV_STATE_TYPES, s, ENVIRONMENT_STATE_NONE, ENVIRONMENT_STATE_CREATE); } InsertMatchType InsertMatchTypeFromString(const char *s) { static const char *const INSERT_MATCH_TYPES[] = { "ignore_leading", "ignore_trailing", "ignore_embedded", "exact_match", NULL }; return FindTypeInArray(INSERT_MATCH_TYPES, s, INSERT_MATCH_TYPE_EXACT, INSERT_MATCH_TYPE_EXACT); } int SyslogPriorityFromString(const char *s) { static const char *const SYSLOG_PRIORITY_TYPES[] = { "emergency", "alert", "critical", "error", "warning", "notice", "info", "debug", NULL }; return FindTypeInArray(SYSLOG_PRIORITY_TYPES, s, 3, 3); } ShellType ShellTypeFromString(const char *string) { // For historical reasons, supports all CF_BOOL values (true/false/yes/no...), // as well as "noshell,useshell,powershell". char *start, *end; char *options = "noshell,useshell,powershell," CF_BOOL; int i; int size; if (string == NULL) { return SHELL_TYPE_NONE; } start = options; size = strlen(string); for (i = 0;; i++) { end = strchr(start, ','); if (end == NULL) { break; } if (size == end - start && strncmp(string, start, end - start) == 0) { int cfBoolIndex; switch (i) { case 0: return SHELL_TYPE_NONE; case 1: return SHELL_TYPE_USE; case 2: return SHELL_TYPE_POWERSHELL; default: // Even cfBoolIndex is true, odd cfBoolIndex is false (from CF_BOOL). cfBoolIndex = i-3; return (cfBoolIndex & 1) ? SHELL_TYPE_NONE : SHELL_TYPE_USE; } } start = end + 1; } return SHELL_TYPE_NONE; } DatabaseType DatabaseTypeFromString(const char *s) { static const char *const DB_TYPES[] = { "mysql", "postgres", NULL }; return FindTypeInArray(DB_TYPES, s, DATABASE_TYPE_NONE, DATABASE_TYPE_NONE); } UserState UserStateFromString(const char *s) { static const char *const U_TYPES[] = { "present", "absent", "locked", NULL }; return FindTypeInArray(U_TYPES, s, USER_STATE_NONE, USER_STATE_NONE); } PasswordFormat PasswordFormatFromString(const char *s) { static const char *const U_TYPES[] = { "plaintext", "hash", NULL }; return FindTypeInArray(U_TYPES, s, PASSWORD_FORMAT_NONE, PASSWORD_FORMAT_NONE); } PackageAction PackageActionFromString(const char *s) { static const char *const PACKAGE_ACTION_TYPES[] = { "add", "delete", "reinstall", "update", "addupdate", "patch", "verify", NULL }; return FindTypeInArray(PACKAGE_ACTION_TYPES, s, PACKAGE_ACTION_NONE, PACKAGE_ACTION_NONE); } PackageVersionComparator PackageVersionComparatorFromString(const char *s) { static const char *const PACKAGE_SELECT_TYPES[] = { "==", "!=", ">", "<", ">=", "<=", NULL }; return FindTypeInArray(PACKAGE_SELECT_TYPES, s, PACKAGE_VERSION_COMPARATOR_NONE, PACKAGE_VERSION_COMPARATOR_NONE); } PackageActionPolicy PackageActionPolicyFromString(const char *s) { static const char *const ACTION_POLICY_TYPES[] = { "individual", "bulk", NULL }; return FindTypeInArray(ACTION_POLICY_TYPES, s, PACKAGE_ACTION_POLICY_NONE, PACKAGE_ACTION_POLICY_NONE); } /***************************************************************************/ char *Rlist2String(Rlist *list, char *sep) { char line[CF_BUFSIZE]; Rlist *rp; line[0] = '\0'; for (rp = list; rp != NULL; rp = rp->next) { strcat(line, RlistScalarValue(rp)); if (rp->next) { strcat(line, sep); } } return xstrdup(line); } /***************************************************************************/ int SignalFromString(const char *s) { int i = 0; Item *ip, *names = SplitString(CF_SIGNALRANGE, ','); for (ip = names; ip != NULL; ip = ip->next) { if (strcmp(s, ip->name) == 0) { break; } i++; } DeleteItemList(names); switch (i) { case cfa_hup: return SIGHUP; case cfa_int: return SIGINT; case cfa_trap: return SIGTRAP; case cfa_kill: return SIGKILL; case cfa_pipe: return SIGPIPE; case cfa_cont: return SIGCONT; case cfa_abrt: return SIGABRT; case cfa_stop: return SIGSTOP; case cfa_quit: return SIGQUIT; case cfa_term: return SIGTERM; case cfa_child: return SIGCHLD; case cfa_usr1: return SIGUSR1; case cfa_usr2: return SIGUSR2; case cfa_bus: return SIGBUS; case cfa_segv: return SIGSEGV; default: return -1; } } ContextScope ContextScopeFromString(const char *scope_str) { static const char *const CONTEXT_SCOPES[] = { "namespace", "bundle" }; return FindTypeInArray(CONTEXT_SCOPES, scope_str, CONTEXT_SCOPE_NAMESPACE, CONTEXT_SCOPE_NONE); } FileLinkType FileLinkTypeFromString(const char *s) { static const char *const LINK_TYPES[] = { "symlink", "hardlink", "relative", "absolute", NULL }; return FindTypeInArray(LINK_TYPES, s, FILE_LINK_TYPE_SYMLINK, FILE_LINK_TYPE_SYMLINK); } FileComparator FileComparatorFromString(const char *s) { static const char *const FILE_COMPARISON_TYPES[] = { "atime", "mtime", "ctime", "digest", "hash", "binary", "exists", NULL }; return FindTypeInArray(FILE_COMPARISON_TYPES, s, FILE_COMPARATOR_NONE, FILE_COMPARATOR_NONE); } static const char *const datatype_strings[] = { [CF_DATA_TYPE_STRING] = "string", [CF_DATA_TYPE_INT] = "int", [CF_DATA_TYPE_REAL] = "real", [CF_DATA_TYPE_STRING_LIST] = "slist", [CF_DATA_TYPE_INT_LIST] = "ilist", [CF_DATA_TYPE_REAL_LIST] = "rlist", [CF_DATA_TYPE_OPTION] = "option", [CF_DATA_TYPE_OPTION_LIST] = "olist", [CF_DATA_TYPE_BODY] = "body", [CF_DATA_TYPE_BUNDLE] = "bundle", [CF_DATA_TYPE_CONTEXT] = "context", [CF_DATA_TYPE_CONTEXT_LIST] = "clist", [CF_DATA_TYPE_INT_RANGE] = "irange", [CF_DATA_TYPE_REAL_RANGE] = "rrange", [CF_DATA_TYPE_COUNTER] = "counter", [CF_DATA_TYPE_CONTAINER] = "data", [CF_DATA_TYPE_NONE] = "none" }; DataType DataTypeFromString(const char *name) { for (int i = 0; i < CF_DATA_TYPE_NONE; i++) { if (strcmp(datatype_strings[i], name) == 0) { return i; } } return CF_DATA_TYPE_NONE; } const char *DataTypeToString(DataType type) { assert(type < CF_DATA_TYPE_NONE); return datatype_strings[type]; } DataType ConstraintSyntaxGetDataType(const ConstraintSyntax *body_syntax, const char *lval) { int i = 0; for (i = 0; body_syntax[i].lval != NULL; i++) { if (lval && (strcmp(body_syntax[i].lval, lval) == 0)) { return body_syntax[i].dtype; } } return CF_DATA_TYPE_NONE; } /****************************************************************************/ bool BooleanFromString(const char *s) { Item *list = SplitString(CF_BOOL, ','), *ip; int count = 0; for (ip = list; ip != NULL; ip = ip->next) { if (strcmp(s, ip->name) == 0) { break; } count++; } DeleteItemList(list); if (count % 2) { return false; } else { return true; } } /****************************************************************************/ long IntFromString(const char *s) { long long a = CF_NOINT; char c = 'X'; char remainder[CF_BUFSIZE]; if (s == NULL) { return CF_NOINT; } if (strcmp(s, "inf") == 0) { return (long) CF_INFINITY; } if (strcmp(s, "now") == 0) { return (long) CFSTARTTIME; } remainder[0] = '\0'; sscanf(s, "%lld%c%s", &a, &c, remainder); // Test whether remainder is space only if ((a == CF_NOINT) || (!IsSpace(remainder))) { Log(LOG_LEVEL_INFO, "Error reading assumed integer value '%s' => 'non-value', found remainder '%s'", s, remainder); if (strchr(s, '$')) { Log(LOG_LEVEL_INFO, "The variable might not yet be expandable - not necessarily an error"); } } else { switch (c) { case 'k': a = 1000 * a; break; case 'K': a = 1024 * a; break; case 'm': a = 1000 * 1000 * a; break; case 'M': a = 1024 * 1024 * a; break; case 'g': a = 1000 * 1000 * 1000 * a; break; case 'G': a = 1024 * 1024 * 1024 * a; break; case '%': if ((a < 0) || (a > 100)) { Log(LOG_LEVEL_ERR, "Percentage out of range (%lld)", a); return CF_NOINT; } else { /* Represent percentages internally as negative numbers */ a = -a; } break; case ' ': break; default: break; } } /* TODO Use strtol() instead of scanf(), it properly checks for overflow * but it is prone to coding errors, so even better bring OpenBSD's * strtonum() for proper conversions. */ if (a < LONG_MIN) { Log(LOG_LEVEL_VERBOSE, "Number '%s' underflows a long int, truncating to %ld", s, LONG_MIN); return LONG_MIN; } else if (a > LONG_MAX) { Log(LOG_LEVEL_VERBOSE, "Number '%s' overflows a long int, truncating to %ld", s, LONG_MAX); return LONG_MAX; } return (long) a; } Interval IntervalFromString(const char *string) { static const char *const INTERVAL_TYPES[] = { "hourly", "daily", NULL }; return FindTypeInArray(INTERVAL_TYPES, string, INTERVAL_NONE, INTERVAL_NONE); } bool DoubleFromString(const char *s, double *value_out) { static const double NO_DOUBLE = -123.45; double a = NO_DOUBLE; char remainder[CF_BUFSIZE]; char c = 'X'; if (s == NULL) { return false; } remainder[0] = '\0'; sscanf(s, "%lf%c%s", &a, &c, remainder); if ((a == NO_DOUBLE) || (!IsSpace(remainder))) { Log(LOG_LEVEL_ERR, "Reading assumed real value '%s', anomalous remainder '%s'", s, remainder); return false; } else { switch (c) { case 'k': a = 1000 * a; break; case 'K': a = 1024 * a; break; case 'm': a = 1000 * 1000 * a; break; case 'M': a = 1024 * 1024 * a; break; case 'g': a = 1000 * 1000 * 1000 * a; break; case 'G': a = 1024 * 1024 * 1024 * a; break; case '%': if ((a < 0) || (a > 100)) { Log(LOG_LEVEL_ERR, "Percentage out of range (%.2lf)", a); return false; } else { /* Represent percentages internally as negative numbers */ a = -a; } break; case ' ': break; default: break; } } *value_out = a; return true; } /****************************************************************************/ /** * @return true if successful */ bool IntegerRangeFromString(const char *intrange, long *min_out, long *max_out) { Item *split; long lmax = CF_LOWINIT, lmin = CF_HIGHINIT; /* Numeric types are registered by range separated by comma str "min,max" */ if (intrange == NULL) { *min_out = CF_NOINT; *max_out = CF_NOINT; return true; } split = SplitString(intrange, ','); sscanf(split->name, "%ld", &lmin); if (strcmp(split->next->name, "inf") == 0) { lmax = (long) CF_INFINITY; } else { sscanf(split->next->name, "%ld", &lmax); } DeleteItemList(split); if ((lmin == CF_HIGHINIT) || (lmax == CF_LOWINIT)) { return false; } *min_out = lmin; *max_out = lmax; return true; } AclMethod AclMethodFromString(const char *string) { static const char *const ACL_METHOD_TYPES[] = { "append", "overwrite", NULL }; return FindTypeInArray(ACL_METHOD_TYPES, string, ACL_METHOD_NONE, ACL_METHOD_NONE); } AclType AclTypeFromString(const char *string) { static const char *const ACL_TYPES[]= { "generic", "posix", "ntfs", NULL }; return FindTypeInArray(ACL_TYPES, string, ACL_TYPE_NONE, ACL_TYPE_NONE); } /* For the deprecated attribute acl_directory_inherit. */ AclDefault AclInheritanceFromString(const char *string) { static const char *const ACL_INHERIT_TYPES[5] = { "nochange", "specify", "parent", "clear", NULL }; return FindTypeInArray(ACL_INHERIT_TYPES, string, ACL_DEFAULT_NONE, ACL_DEFAULT_NONE); } AclDefault AclDefaultFromString(const char *string) { static const char *const ACL_DEFAULT_TYPES[5] = { "nochange", "specify", "access", "clear", NULL }; return FindTypeInArray(ACL_DEFAULT_TYPES, string, ACL_DEFAULT_NONE, ACL_DEFAULT_NONE); } AclInherit AclInheritFromString(const char *string) { char *start, *end; char *options = CF_BOOL ",nochange"; int i; int size; if (string == NULL) { return ACL_INHERIT_NOCHANGE; } start = options; size = strlen(string); for (i = 0;; i++) { end = strchr(start, ','); if (end == NULL) { break; } if (size == end - start && strncmp(string, start, end - start) == 0) { // Even i is true, odd i is false (from CF_BOOL). return (i & 1) ? ACL_INHERIT_FALSE : ACL_INHERIT_TRUE; } start = end + 1; } return ACL_INHERIT_NOCHANGE; } ServicePolicy ServicePolicyFromString(const char *string) { static const char *const SERVICE_POLICY_TYPES[] = { "start", "stop", "disable", "restart", "reload", NULL }; return FindTypeInArray(SERVICE_POLICY_TYPES, string, SERVICE_POLICY_START, SERVICE_POLICY_START); } const char *DataTypeShortToType(char *short_type) { assert(short_type); if(strcmp(short_type, "s") == 0) { return "string"; } if(strcmp(short_type, "i") == 0) { return "int"; } if(strcmp(short_type, "r") == 0) { return "real"; } if(strcmp(short_type, "m") == 0) { return "menu"; } if(strcmp(short_type, "sl") == 0) { return "string list"; } if(strcmp(short_type, "il") == 0) { return "int list"; } if(strcmp(short_type, "rl") == 0) { return "real list"; } if(strcmp(short_type, "ml") == 0) { return "menu list"; } return "unknown type"; } int CoarseLaterThan(const char *bigger, const char *smaller) { char month_small[CF_SMALLBUF]; char month_big[CF_SMALLBUF]; int m_small, day_small, year_small, m_big, year_big, day_big; sscanf(smaller, "%d %s %d", &day_small, month_small, &year_small); sscanf(bigger, "%d %s %d", &day_big, month_big, &year_big); if (year_big < year_small) { return false; } m_small = Month2Int(month_small); m_big = Month2Int(month_big); if (m_big < m_small) { return false; } if (day_big < day_small && m_big == m_small && year_big == year_small) { return false; } return true; } int Month2Int(const char *string) { int i; if (string == NULL) { return -1; } for (i = 0; i < 12; i++) { if (strncmp(MONTH_TEXT[i], string, strlen(string)) == 0) { return i + 1; break; } } return -1; } /*********************************************************************/ void TimeToDateStr(time_t t, char *outStr, int outStrSz) /** * Formats a time as "30 Sep 2010". */ { char month[CF_SMALLBUF], day[CF_SMALLBUF], year[CF_SMALLBUF]; char tmp[CF_SMALLBUF]; snprintf(tmp, sizeof(tmp), "%s", ctime(&t)); sscanf(tmp, "%*s %5s %3s %*s %5s", month, day, year); snprintf(outStr, outStrSz, "%s %s %s", day, month, year); } /*********************************************************************/ /** * Copy first argument of #src to #dst. Argument is delimited either by double * quotes if first character is double quotes, or by space. * * @note Thread-safe version of CommandArg0(). * * @return The length of #dst, or (size_t) -1 in case of overflow. */ size_t CommandArg0_bound(char *dst, const char *src, size_t dst_size) { const char *start; char end_delimiter; if(src[0] == '\"') { start = &src[1]; end_delimiter = '\"'; } else { start = src; end_delimiter = ' '; } char *end = strchr(start, end_delimiter); size_t len = end - start; if (len < dst_size) { memcpy(dst, start, len); dst[len] = '\0'; return len; } else { /* Check return value! If -1, the user should never use dst. */ strlcpy(dst, "BUG: COMMANDARG0_TOO_LONG", MIN(dst_size - 1, strlen("BUG: COMMANDARG0_TOO_LONG"))); return (size_t) -1; } } const char *CommandArg0(const char *execstr) /** * WARNING: Not thread-safe. **/ { static char arg[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */ const char *start; char end_delimiter; if(execstr[0] == '\"') { start = execstr + 1; end_delimiter = '\"'; } else { start = execstr; end_delimiter = ' '; } strlcpy(arg, start, sizeof(arg)); char *cut = strchr(arg, end_delimiter); if(cut) { *cut = '\0'; } return arg; } /*************************************************************/ void CommandPrefix(char *execstr, char *comm) { char *sp; for (sp = execstr; (*sp != ' ') && (*sp != '\0'); sp++) { } if (sp - 10 >= execstr) { sp -= 10; /* copy 15 most relevant characters of command */ } else { sp = execstr; } memset(comm, 0, 20); strncpy(comm, sp, 15); } static int IsSpace(char *remainder) { char *sp; for (sp = remainder; *sp != '\0'; sp++) { if (!isspace((int)*sp)) { return false; } } return true; } /*******************************************************************/ bool IsRealNumber(const char *s) { static const double NO_DOUBLE = -123.45; double a = NO_DOUBLE; sscanf(s, "%lf", &a); if (a == NO_DOUBLE) { return false; } return true; } #ifndef __MINGW32__ /*******************************************************************/ /* Unix-only functions */ /*******************************************************************/ /****************************************************************************/ /* Rlist to Uid/Gid lists */ /****************************************************************************/ void UidListDestroy(UidList *uids) { while (uids) { UidList *ulp = uids; uids = uids->next; free(ulp->uidname); free(ulp); } } static void AddSimpleUidItem(UidList ** uidlist, uid_t uid, char *uidname) { UidList *ulp = xcalloc(1, sizeof(UidList)); ulp->uid = uid; if (uid == CF_UNKNOWN_OWNER) /* unknown user */ { ulp->uidname = xstrdup(uidname); } if (*uidlist == NULL) { *uidlist = ulp; } else /* Hang new element off end of list: */ { UidList *u = *uidlist; while (u->next != NULL) { u = u->next; } u->next = ulp; } } UidList *Rlist2UidList(Rlist *uidnames, const Promise *pp) { UidList *uidlist = NULL; Rlist *rp; char username[CF_MAXVARSIZE]; uid_t uid; for (rp = uidnames; rp != NULL; rp = rp->next) { username[0] = '\0'; uid = Str2Uid(RlistScalarValue(rp), username, pp); AddSimpleUidItem(&uidlist, uid, username); } if (uidlist == NULL) { AddSimpleUidItem(&uidlist, CF_SAME_OWNER, NULL); } return uidlist; } /*********************************************************************/ void GidListDestroy(GidList *gids) { while (gids) { GidList *glp = gids; gids = gids->next; free(glp->gidname); free(glp); } } static void AddSimpleGidItem(GidList ** gidlist, gid_t gid, char *gidname) { GidList *glp = xcalloc(1, sizeof(GidList)); glp->gid = gid; if (gid == CF_UNKNOWN_GROUP) /* unknown group */ { glp->gidname = xstrdup(gidname); } if (*gidlist == NULL) { *gidlist = glp; } else /* Hang new element off end of list: */ { GidList *g = *gidlist; while (g->next != NULL) { g = g->next; } g->next = glp; } } GidList *Rlist2GidList(Rlist *gidnames, const Promise *pp) { GidList *gidlist = NULL; Rlist *rp; char groupname[CF_MAXVARSIZE]; gid_t gid; for (rp = gidnames; rp != NULL; rp = rp->next) { groupname[0] = '\0'; gid = Str2Gid(RlistScalarValue(rp), groupname, pp); AddSimpleGidItem(&gidlist, gid, groupname); } if (gidlist == NULL) { AddSimpleGidItem(&gidlist, CF_SAME_GROUP, NULL); } return gidlist; } /*********************************************************************/ uid_t Str2Uid(const char *uidbuff, char *usercopy, const Promise *pp) { Item *ip, *tmplist; struct passwd *pw; int offset, uid = -2, tmp = -2; char *machine, *user, *domain; if (uidbuff[0] == '+') /* NIS group - have to do this in a roundabout */ { /* way because calling getpwnam spoils getnetgrent */ offset = 1; if (uidbuff[1] == '@') { offset++; } setnetgrent(uidbuff + offset); tmplist = NULL; while (getnetgrent(&machine, &user, &domain)) { if (user != NULL) { AppendItem(&tmplist, user, NULL); } } endnetgrent(); for (ip = tmplist; ip != NULL; ip = ip->next) { if ((pw = getpwnam(ip->name)) == NULL) { Log(LOG_LEVEL_INFO, "Unknown user in promise '%s'", ip->name); if (pp != NULL) { PromiseRef(LOG_LEVEL_INFO, pp); } uid = CF_UNKNOWN_OWNER; /* signal user not found */ } else { uid = pw->pw_uid; if (usercopy != NULL) { strcpy(usercopy, ip->name); } } } DeleteItemList(tmplist); return uid; } if (StringIsNumeric(uidbuff)) { sscanf(uidbuff, "%d", &tmp); uid = (uid_t) tmp; } else { if (strcmp(uidbuff, "*") == 0) { uid = CF_SAME_OWNER; /* signals wildcard */ } else if ((pw = getpwnam(uidbuff)) == NULL) { Log(LOG_LEVEL_INFO, "Unknown user '%s' in promise", uidbuff); uid = CF_UNKNOWN_OWNER; /* signal user not found */ if (usercopy != NULL) { strcpy(usercopy, uidbuff); } } else { uid = pw->pw_uid; } } return uid; } /*********************************************************************/ gid_t Str2Gid(const char *gidbuff, char *groupcopy, const Promise *pp) { struct group *gr; int gid = -2, tmp = -2; if (StringIsNumeric(gidbuff)) { sscanf(gidbuff, "%d", &tmp); gid = (gid_t) tmp; } else { if (strcmp(gidbuff, "*") == 0) { gid = CF_SAME_GROUP; /* signals wildcard */ } else if ((gr = getgrnam(gidbuff)) == NULL) { Log(LOG_LEVEL_INFO, "Unknown group '%s' in promise", gidbuff); if (pp) { PromiseRef(LOG_LEVEL_INFO, pp); } gid = CF_UNKNOWN_GROUP; } else { gid = gr->gr_gid; strcpy(groupcopy, gidbuff); } } return gid; } #else /* !__MINGW32__ */ /* Release everything NovaWin_Rlist2SidList() allocates: */ void UidListDestroy(UidList *uids) { while (uids) { UidList *ulp = uids; uids = uids->next; free(ulp); } } void GidListDestroy(ARG_UNUSED GidList *gids) { assert(gids == NULL); } #endif cfengine-3.6.2/libpromises/conversion.h0000664000175100017510000000721412411001073017675 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CONVERSION_H #define CFENGINE_CONVERSION_H #include // Type-String conversion MeasurePolicy MeasurePolicyFromString(const char *s); EnvironmentState EnvironmentStateFromString(const char *s); InsertMatchType InsertMatchTypeFromString(const char *s); Interval IntervalFromString(const char *s); DatabaseType DatabaseTypeFromString(const char *s); UserState UserStateFromString(const char *s); PasswordFormat PasswordFormatFromString(const char *s); ContextScope ContextScopeFromString(const char *scope_str); FileComparator FileComparatorFromString(const char *s); FileLinkType FileLinkTypeFromString(const char *s); DataType DataTypeFromString(const char *name); const char *DataTypeToString(DataType dtype); PackageActionPolicy PackageActionPolicyFromString(const char *s); PackageVersionComparator PackageVersionComparatorFromString(const char *s); PackageAction PackageActionFromString(const char *s); AclMethod AclMethodFromString(const char *string); AclType AclTypeFromString(const char *string); AclDefault AclDefaultFromString(const char *string); AclInherit AclInheritFromString(const char *string); ServicePolicy ServicePolicyFromString(const char *string); int SignalFromString(const char *s); int SyslogPriorityFromString(const char *s); ShellType ShellTypeFromString(const char *s); // Date/Time conversion void TimeToDateStr(time_t t, char *outStr, int outStrSz); int Month2Int(const char *string); // Evalaution conversion bool BooleanFromString(const char *val); long IntFromString(const char *s); bool DoubleFromString(const char *s, double *value_out); bool IntegerRangeFromString(const char *intrange, long *min_out, long *max_out); bool IsRealNumber(const char *s); // Misc. char *Rlist2String(Rlist *list, char *sep); // TODO: Yet another Rlist serialization scheme.. Found 5 so far. DataType ConstraintSyntaxGetDataType(const ConstraintSyntax *body_syntax, const char *lval); const char *MapAddress(const char *addr); const char *CommandArg0(const char *execstr); size_t CommandArg0_bound(char *dst, const char *src, size_t dst_size); void CommandPrefix(char *execstr, char *comm); const char *DataTypeShortToType(char *short_type); int CoarseLaterThan(const char *key, const char *from); int FindTypeInArray(const char *const haystack[], const char *needle, int default_value, int null_value); void UidListDestroy(UidList *uids); void GidListDestroy(GidList *gids); UidList *Rlist2UidList(Rlist *uidnames, const Promise *pp); GidList *Rlist2GidList(Rlist *gidnames, const Promise *pp); #ifndef __MINGW32__ uid_t Str2Uid(const char *uidbuff, char *copy, const Promise *pp); gid_t Str2Gid(const char *gidbuff, char *copy, const Promise *pp); #endif /* !__MINGW32__ */ #endif cfengine-3.6.2/libpromises/scope.h0000664000175100017510000000433112243421446016633 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SCOPE_H #define CFENGINE_SCOPE_H #include #include typedef enum { SPECIAL_SCOPE_CONST, SPECIAL_SCOPE_EDIT, SPECIAL_SCOPE_MATCH, SPECIAL_SCOPE_MON, SPECIAL_SCOPE_SYS, SPECIAL_SCOPE_THIS, SPECIAL_SCOPE_BODY, SPECIAL_SCOPE_NONE } SpecialScope; const char *SpecialScopeToString(SpecialScope scope); SpecialScope SpecialScopeFromString(const char *scope); /** * @brief augments a scope, expecting corresponding lists of lvals and rvals (implying same length). * in addition to copying them in, also attempts to do one-pass resolution of variables, * and evaluates function calls, and attempts expansion on senior scope members. */ void ScopeAugment(EvalContext *ctx, const Bundle *bp, const Promise *pp, const Rlist *arguments); void ScopeMapBodyArgs(EvalContext *ctx, const Body *body, const Rlist *args); // TODO: namespacing utility functions. there are probably a lot of these floating around, but probably best // leave them until we get a proper symbol table void SplitScopeName(const char *scope_name, char namespace_out[CF_MAXVARSIZE], char bundle_out[CF_MAXVARSIZE]); void JoinScopeName(const char *ns, const char *bundle, char scope_out[CF_MAXVARSIZE]); #endif cfengine-3.6.2/libpromises/mod_access.h0000644000175100017510000000342012316547775017635 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_ACCESS_H #define CFENGINE_MOD_ACCESS_H #include typedef enum { REMOTE_ACCESS_ADMIT, REMOTE_ACCESS_DENY, REMOTE_ACCESS_ADMITIPS, REMOTE_ACCESS_DENYIPS, REMOTE_ACCESS_ADMITHOSTNAMES, REMOTE_ACCESS_DENYHOSTNAMES, REMOTE_ACCESS_ADMITKEYS, REMOTE_ACCESS_DENYKEYS, REMOTE_ACCESS_MAPROOT, REMOTE_ACCESS_IFENCRYPTED, REMOTE_ACCESS_RESOURCE_TYPE, REMOTE_ACCESS_REPORT_DATA_SELECT, REMOTE_ACCESS_SHORTCUT, REMOTE_ACCESS_NONE } RemoteAccess; typedef enum { REMOTE_ROLE_AUTHORIZE, REMOTE_ROLE_NONE } RemoteRole; extern const PromiseTypeSyntax CF_REMACCESS_PROMISE_TYPES[]; extern const ConstraintSyntax CF_REMACCESS_BODIES[REMOTE_ACCESS_NONE + 1]; extern const ConstraintSyntax CF_REMROLE_BODIES[REMOTE_ROLE_NONE + 1]; #endif cfengine-3.6.2/libpromises/files_copy.h0000664000175100017510000000243612243421446017662 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_COPY_H #define CFENGINE_FILES_COPY_H #include bool CopyRegularFileDisk(const char *source, const char *destination); bool CopyFilePermissionsDisk(const char *source, const char *destination); bool CopyFileExtendedAttributesDisk(const char *source, const char *destination); #endif cfengine-3.6.2/libpromises/pipes.h0000664000175100017510000000344412243421446016646 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PIPES_H #define CFENGINE_PIPES_H #include FILE *cf_popen(const char *command, const char *type, bool capture_stderr); FILE *cf_popensetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, int background); FILE *cf_popen_sh(const char *command, const char *type); FILE *cf_popen_shsetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, int background); int cf_pclose(FILE *pp); bool PipeToPid(pid_t *pid, FILE *pp); bool PipeTypeIsOk(const char *type); #ifdef __MINGW32__ FILE *cf_popen_powershell(const char *command, const char *type); FILE *cf_popen_powershell_setuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, int background); #endif #endif cfengine-3.6.2/libpromises/vars.c0000644000175100017510000002530112316547775016505 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include static int IsCf3Scalar(char *str); /*******************************************************************/ bool RlistIsUnresolved(const Rlist *list) { for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (rp->val.type != RVAL_TYPE_SCALAR) { return true; } if (IsCf3Scalar(RlistScalarValue(rp))) { if (strstr(RlistScalarValue(rp), "$(this)") || strstr(RlistScalarValue(rp), "${this}") || strstr(RlistScalarValue(rp), "$(this.k)") || strstr(RlistScalarValue(rp), "${this.k}") || strstr(RlistScalarValue(rp), "$(this.v)") || strstr(RlistScalarValue(rp), "${this.v}")) { // We should allow this in function args for substitution in maplist() etc // We should allow this.k and this.v in function args for substitution in maparray() etc } else { return true; } } } return false; } /******************************************************************/ bool StringContainsVar(const char *s, const char *v) { int vlen = strlen(v); if (s == NULL) { return false; } /* Look for ${v}, $(v), @{v}, $(v) */ for (;;) { /* Look for next $ or @ */ s = strpbrk(s, "$@"); if (s == NULL) { return false; } /* If next symbol */ if (*++s == '\0') { return false; } /* is { or ( */ if (*s != '(' && *s != '{') { continue; } /* Then match the variable starting from next symbol */ if (strncmp(s + 1, v, vlen) != 0) { continue; } /* And if it matched, match the closing bracket */ if ((s[0] == '(' && s[vlen + 1] == ')') || (s[0] == '{' && s[vlen + 1] == '}')) { return true; } } } /*********************************************************************/ bool IsCf3VarString(const char *str) { char left = 'x', right = 'x'; int dollar = false; int bracks = 0, vars = 0; if (str == NULL) { return false; } for (const char *sp = str; *sp != '\0'; sp++) /* check for varitems */ { switch (*sp) { case '$': case '@': if (*(sp + 1) == '{' || *(sp + 1) == '(') { dollar = true; } break; case '(': case '{': if (dollar) { left = *sp; bracks++; } break; case ')': case '}': if (dollar) { bracks--; right = *sp; } break; } /* Some chars cannot be in variable ids, e.g. $(/bin/cat file) is legal in bash */ if (bracks > 0) { switch (*sp) { case '/': return false; } } if (left == '(' && right == ')' && dollar && (bracks == 0)) { vars++; dollar = false; } if (left == '{' && right == '}' && dollar && (bracks == 0)) { vars++; dollar = false; } } if (dollar && (bracks != 0)) { char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "Broken variable syntax or bracket mismatch in string (%s)", str); yyerror(output); return false; } return vars; } /*********************************************************************/ static int IsCf3Scalar(char *str) { char *sp; char left = 'x', right = 'x'; int dollar = false; int bracks = 0, vars = 0; if (str == NULL) { return false; } for (sp = str; *sp != '\0'; sp++) /* check for varitems */ { switch (*sp) { case '$': if (*(sp + 1) == '{' || *(sp + 1) == '(') { dollar = true; } break; case '(': case '{': if (dollar) { left = *sp; bracks++; } break; case ')': case '}': if (dollar) { bracks--; right = *sp; } break; } /* Some chars cannot be in variable ids, e.g. $(/bin/cat file) is legal in bash */ if (bracks > 0) { switch (*sp) { case '/': return false; } } if (left == '(' && right == ')' && dollar && (bracks == 0)) { vars++; dollar = false; } if (left == '{' && right == '}' && dollar && (bracks == 0)) { vars++; dollar = false; } } if (dollar && (bracks != 0)) { char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "Broken scalar variable syntax or bracket mismatch in '%s'", str); yyerror(output); return false; } return vars; } size_t ExtractScalarPrefix(Buffer *out, const char *str, size_t len) { assert(str); if (len == 0) { return 0; } const char *dollar_point = NULL; for (size_t i = 0; i < (len - 1); i++) { if (str[i] == '$') { if (str[i + 1] == '(' || str[i + 1] == '{') { dollar_point = str + i; break; } } } if (!dollar_point) { BufferAppend(out, str, len); return len; } else if (dollar_point > str) { size_t prefix_len = dollar_point - str; if (prefix_len > 0) { BufferAppend(out, str, prefix_len); } return prefix_len; } return 0; } static const char *ReferenceEnd(const char *str, size_t len) { assert(len > 1); assert(str[0] == '$'); assert(str[1] == '{' || str[1] == '('); #define MAX_VARIABLE_REFERENCE_LEVELS 10 char stack[MAX_VARIABLE_REFERENCE_LEVELS] = { 0, str[1], 0 }; int level = 1; for (size_t i = 2; i < len; i++) { switch (str[i]) { case '{': case '(': if (level < MAX_VARIABLE_REFERENCE_LEVELS - 1) { level++; stack[level] = str[i]; } else { Log(LOG_LEVEL_ERR, "Stack overflow in variable reference parsing. More than %d levels", MAX_VARIABLE_REFERENCE_LEVELS); return NULL; } break; case '}': if (stack[level] != '{') { Writer *w = StringWriter(); WriterWriteLen(w, str, len); Log(LOG_LEVEL_ERR, "Variable reference bracket mismatch '%s'", StringWriterData(w)); WriterClose(w); return NULL; } level--; break; case ')': if (stack[level] != '(') { Writer *w = StringWriter(); WriterWriteLen(w, str, len); Log(LOG_LEVEL_ERR, "Variable reference bracket mismatch '%s'", StringWriterData(w)); WriterClose(w); return NULL; } level--; break; } if (level == 0) { return str + i; } } return NULL; } bool ExtractScalarReference(Buffer *out, const char *str, size_t len, bool extract_inner) { if (len <= 1) { return false; } const char *dollar_point = memchr(str, '$', len); if (!dollar_point || (dollar_point - str) == len) { return false; } else { const char *close_point = NULL; { size_t remaining = len - (dollar_point - str); if (*(dollar_point + 1) == '{' || *(dollar_point + 1) == '(') { close_point = ReferenceEnd(dollar_point, remaining); } else { return ExtractScalarReference(out, dollar_point + 1, remaining - 1, extract_inner); } } if (!close_point) { Writer *w = StringWriter(); WriterWriteLen(w, str, len); Log(LOG_LEVEL_ERR, "Variable reference close mismatch '%s'", StringWriterData(w)); WriterClose(w); return false; } size_t outer_len = close_point - dollar_point + 1; if (outer_len <= 3) { Writer *w = StringWriter(); WriterWriteLen(w, str, len); Log(LOG_LEVEL_ERR, "Empty variable reference close mismatch '%s'", StringWriterData(w)); WriterClose(w); return false; } if (extract_inner) { BufferAppend(out, dollar_point + 2, outer_len - 3); } else { BufferAppend(out, dollar_point, outer_len); } return true; } } /*********************************************************************/ bool IsQualifiedVariable(const char *var) { int isarraykey = false; for (const char *sp = var; *sp != '\0'; sp++) { if (*sp == '[') { isarraykey = true; } if (isarraykey) { return false; } else { if (*sp == '.') { return true; } } } return false; } cfengine-3.6.2/libpromises/mod_measurement.h0000664000175100017510000000220312243421446020702 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_MEASUREMENT_H #define CFENGINE_MOD_MEASUREMENT_H #include extern const PromiseTypeSyntax CF_MEASUREMENT_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/verify_classes.h0000644000175100017510000000225612316547775020564 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_CLASSES_H #define CFENGINE_VERIFY_CLASSES_H #include #include PromiseResult VerifyClassPromise(EvalContext *ctx, const Promise *pp, void *param); #endif cfengine-3.6.2/libpromises/pipes_unix.c0000664000175100017510000003401112400110676017671 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include static int CfSetuid(uid_t uid, gid_t gid); static int cf_pwait(pid_t pid); static pid_t *CHILDREN = NULL; /* GLOBAL_X */ static int MAX_FD = 128; /* GLOBAL_X */ /* Max number of simultaneous pipes */ static int InitChildrenFD() { if (!ThreadLock(cft_count)) { return false; } if (CHILDREN == NULL) /* first time */ { CHILDREN = xcalloc(MAX_FD, sizeof(pid_t)); } ThreadUnlock(cft_count); return true; } /*****************************************************************************/ static void CloseChildrenFD() { ThreadLock(cft_count); int i; for (i = 0; i < MAX_FD; i++) { if (CHILDREN[i] > 0) { close(i); } } free(CHILDREN); CHILDREN = NULL; ThreadUnlock(cft_count); } /*****************************************************************************/ static void SetChildFD(int fd, pid_t pid) { int new_max = 0; if (fd >= MAX_FD) { Log(LOG_LEVEL_WARNING, "File descriptor %d of child %jd higher than MAX_FD, check for defunct children", fd, (intmax_t) pid); new_max = fd + 32; } ThreadLock(cft_count); if (new_max) { CHILDREN = xrealloc(CHILDREN, new_max * sizeof(pid_t)); MAX_FD = new_max; } CHILDREN[fd] = pid; ThreadUnlock(cft_count); } /*****************************************************************************/ static pid_t CreatePipeAndFork(const char *type, int *pd) { pid_t pid = -1; if (!PipeTypeIsOk(type)) { errno = EINVAL; return -1; } if (!InitChildrenFD()) { return -1; } if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return -1; } if ((pid = fork()) == -1) { close(pd[0]); close(pd[1]); return -1; } signal(SIGCHLD, SIG_DFL); // Redmine #2971: reset SIGPIPE signal handler to have a sane behavior of piped commands within child if (pid == 0) { signal(SIGPIPE, SIG_DFL); } ALARM_PID = (pid != 0 ? pid : -1); return pid; } /*****************************************************************************/ FILE *cf_popen(const char *command, const char *type, bool capture_stderr) { int pd[2]; char **argv; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ if (capture_stderr) { dup2(pd[1], 2); /* Merge stdout/stderr */ } else { int nullfd = open(NULLFILE, O_WRONLY); dup2(nullfd, 2); close(nullfd); } close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); argv = ArgSplitCommand(command); if (execv(argv[0], argv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't run '%s'. (execv: %s)", argv[0], GetErrorStr()); } _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; /* Cannot reach here */ } /*****************************************************************************/ FILE *cf_popensetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, ARG_UNUSED int background) { int pd[2]; char **argv; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); argv = ArgSplitCommand(command); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chroot to '%s'. (chroot: %s)", chrootv, GetErrorStr()); ArgFree(argv); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (safe_chdir(chdirv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chdir to '%s'. (chdir: %s)", chdirv, GetErrorStr()); ArgFree(argv); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(EXIT_FAILURE); } if (execv(argv[0], argv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't run '%s'. (execv: %s)", argv[0], GetErrorStr()); } _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; /* cannot reach here */ } /*****************************************************************************/ /* Shell versions of commands - not recommended for security reasons */ /*****************************************************************************/ FILE *cf_popen_sh(const char *command, const char *type) { int pd[2]; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; } /******************************************************************************/ FILE *cf_popen_shsetuid(const char *command, const char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv, ARG_UNUSED int background) { int pd[2]; pid_t pid; FILE *pp = NULL; pid = CreatePipeAndFork(type, pd); if (pid == -1) { return NULL; } if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1], 1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1], 2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0], 0); close(pd[0]); } } CloseChildrenFD(); if (chrootv && (strlen(chrootv) != 0)) { if (chroot(chrootv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chroot to '%s'. (chroot: %s)", chrootv, GetErrorStr()); return NULL; } } if (chdirv && (strlen(chdirv) != 0)) { if (safe_chdir(chdirv) == -1) { Log(LOG_LEVEL_ERR, "Couldn't chdir to '%s'. (chdir: %s)", chdirv, GetErrorStr()); return NULL; } } if (!CfSetuid(uid, gid)) { _exit(EXIT_FAILURE); } execl(SHELL_PATH, "sh", "-c", command, NULL); _exit(EXIT_FAILURE); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0], type)) == NULL) { cf_pwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1], type)) == NULL) { cf_pwait(pid); return NULL; } } SetChildFD(fileno(pp), pid); return pp; } return NULL; } static int cf_pwait(pid_t pid) { int status; Log(LOG_LEVEL_DEBUG, "cf_pwait - Waiting for process %jd", (intmax_t)pid); while (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { return -1; } } if (!WIFEXITED(status)) { return -1; } return WEXITSTATUS(status); } /*******************************************************************/ int cf_pclose(FILE *pp) { int fd = fileno(pp); pid_t pid; if (!ThreadLock(cft_count)) { fclose(pp); return -1; } if (CHILDREN == NULL) /* popen hasn't been called */ { ThreadUnlock(cft_count); fclose(pp); return -1; } ALARM_PID = -1; if (fd >= MAX_FD) { ThreadUnlock(cft_count); Log(LOG_LEVEL_ERR, "File descriptor %d of child higher than MAX_FD in cf_pclose!", fd); pid = 0; } else { pid = CHILDREN[fd]; CHILDREN[fd] = 0; ThreadUnlock(cft_count); } if (fclose(pp) == EOF || pid == 0) { return -1; } return cf_pwait(pid); } bool PipeToPid(pid_t *pid, FILE *pp) { int fd = fileno(pp); if (!ThreadLock(cft_count)) { return false; } if (CHILDREN == NULL) /* popen hasn't been called */ { ThreadUnlock(cft_count); return false; } *pid = CHILDREN[fd]; ThreadUnlock(cft_count); return true; } /*******************************************************************/ static int CfSetuid(uid_t uid, gid_t gid) { struct passwd *pw; if (gid != (gid_t) - 1) { Log(LOG_LEVEL_VERBOSE, "Changing gid to %ju", (uintmax_t)gid); if (setgid(gid) == -1) { Log(LOG_LEVEL_ERR, "Couldn't set gid to '%ju'. (setgid: %s)", (uintmax_t)gid, GetErrorStr()); return false; } /* Now eliminate any residual privileged groups */ if ((pw = getpwuid(uid)) == NULL) { Log(LOG_LEVEL_ERR, "Unable to get login groups when dropping privilege to '%jd'. (getpwuid: %s)", (uintmax_t)uid, GetErrorStr()); return false; } if (initgroups(pw->pw_name, pw->pw_gid) == -1) { Log(LOG_LEVEL_ERR, "Unable to set login groups when dropping privilege to '%s=%ju'. (initgroups: %s)", pw->pw_name, (uintmax_t)uid, GetErrorStr()); return false; } } if (uid != (uid_t) - 1) { Log(LOG_LEVEL_VERBOSE, "Changing uid to '%ju'", (uintmax_t)uid); if (setuid(uid) == -1) { Log(LOG_LEVEL_ERR, "Couldn't set uid to '%ju'. (setuid: %s)", (uintmax_t)uid, GetErrorStr()); return false; } } return true; } cfengine-3.6.2/libpromises/solaris_ifaddrs.h0000644000175100017510000000516512316547775020715 0ustar00a10038a1003800000000000000/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * CDDL HEADER END */ /* *Portions Copyright 2013 CFEngine AS */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SOLARIS_IFADDRS_H #define _SOLARIS_IFADDRS_H #include #define LIFC_ENABLED 0x20 /* Include only IFF_UP interfaces */ /* * The `getifaddrs' function generates a linked list of these structures. * Each element of the list describes one network interface. */ struct ifaddrs { struct ifaddrs *ifa_next; /* Pointer to the next structure. */ char *ifa_name; /* Name of this network interface. */ uint64_t ifa_flags; /* Flags as from SIOCGLIFFLAGS ioctl. */ struct sockaddr *ifa_addr; /* Network address of this interface. */ struct sockaddr *ifa_netmask; /* Netmask of this interface. */ union { /* * At most one of the following two is valid. If the * IFF_BROADCAST bit is set in `ifa_flags', then * `ifa_broadaddr' is valid. If the IFF_POINTOPOINT bit is * set, then `ifa_dstaddr' is valid. It is never the case that * both these bits are set at once. */ struct sockaddr *ifu_broadaddr; struct sockaddr *ifu_dstaddr; } ifa_ifu; void *ifa_data; /* Address-specific data (may be unused). */ /* * This may have been defined in . */ #ifndef ifa_broadaddr #define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ #endif #ifndef ifa_dstaddr #define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of p-to-p link */ #endif }; /* * Create a linked list of `struct ifaddrs' structures, one for each * network interface on the host machine. If successful, store the * list in *ifap and return 0. On errors, return -1 and set `errno'. * * The storage returned in *ifap is allocated dynamically and can * only be properly freed by passing it to `freeifaddrs'. */ extern int solaris_getifaddrs(struct ifaddrs **); /* Reclaim the storage allocated by a previous `getifaddrs' call. */ extern void solaris_freeifaddrs(struct ifaddrs *); #endif /* _SOLARIS_IFADDRS_H */ cfengine-3.6.2/libpromises/ornaments.h0000664000175100017510000000275512411001073017523 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ORNAMENTS_H #define CFENGINE_ORNAMENTS_H /* * Various ornaments in output */ #include #include #include void PromiseBanner(const Promise *pp); void BannerSubBundle(const Bundle *bp, const Rlist *params); void BannerPromiseType(const char *bundlename, const char *type, int p); void BannerSubPromiseType(const EvalContext *ctx, const char *bundlename, const char *type); void Banner(const char *s); void BannerBundle(const Bundle *bp, const Rlist *params); #endif cfengine-3.6.2/libpromises/lastseen.h0000664000175100017510000000402612400110676017334 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LASTSEEN_H #define CFENGINE_LASTSEEN_H typedef struct { time_t lastseen; QPoint Q; } KeyHostSeen; typedef enum { LAST_SEEN_ROLE_CONNECT, LAST_SEEN_ROLE_ACCEPT } LastSeenRole; bool Address2Hostkey(char *dst, size_t dst_size, const char *address); void LastSaw1(const char *ipaddress, const char *hashstr, LastSeenRole role); void LastSaw(const char *ipaddress, const char *digest, LastSeenRole role); bool DeleteIpFromLastSeen(const char *ip, char *digest); bool DeleteDigestFromLastSeen(const char *key, char *ip); /* * Return false in order to stop iteration */ typedef bool (*LastSeenQualityCallback)(const char *hostkey, const char *address, bool incoming, const KeyHostSeen *quality, void *ctx); bool ScanLastSeenQuality(LastSeenQualityCallback callback, void *ctx); int LastSeenHostKeyCount(void); bool IsLastSeenCoherent(void); int RemoveKeysFromLastSeen(const char *input, bool must_be_coherent, char *equivalent); #endif cfengine-3.6.2/libpromises/processes_select.c0000664000175100017510000010207212411001073021046 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include /* Chop */ #include /* CompileRegex,StringMatchWithPrecompiledRegex,StringMatchFull */ #include #include #include #include #include #include #include # ifdef HAVE_GETZONEID #include #define MAX_ZONENAME_SIZE 64 # endif static int SelectProcRangeMatch(char *name1, char *name2, int min, int max, char **names, char **line); static bool SelectProcRegexMatch(const char *name1, const char *name2, const char *regex, char **colNames, char **line); static int SplitProcLine(const char *proc, char **names, int *start, int *end, char **line); static int SelectProcTimeCounterRangeMatch(char *name1, char *name2, time_t min, time_t max, char **names, char **line); static int SelectProcTimeAbsRangeMatch(char *name1, char *name2, time_t min, time_t max, char **names, char **line); static int GetProcColumnIndex(const char *name1, const char *name2, char **names); static void GetProcessColumnNames(char *proc, char **names, int *start, int *end); static int ExtractPid(char *psentry, char **names, int *end); /***************************************************************************/ static int SelectProcess(char *procentry, char **names, int *start, int *end, ProcessSelect a) { int result = true, i; char *column[CF_PROCCOLS]; Rlist *rp; StringSet *process_select_attributes = StringSetNew(); if (!SplitProcLine(procentry, names, start, end, column)) { return false; } for (i = 0; names[i] != NULL; i++) { Log(LOG_LEVEL_DEBUG, "In SelectProcess, COL[%s] = '%s'", names[i], column[i]); } for (rp = a.owner; rp != NULL; rp = rp->next) { if (SelectProcRegexMatch("USER", "UID", RlistScalarValue(rp), names, column)) { StringSetAdd(process_select_attributes, xstrdup("process_owner")); break; } } if (SelectProcRangeMatch("PID", "PID", a.min_pid, a.max_pid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("pid")); } if (SelectProcRangeMatch("PPID", "PPID", a.min_ppid, a.max_ppid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("ppid")); } if (SelectProcRangeMatch("PGID", "PGID", a.min_pgid, a.max_pgid, names, column)) { StringSetAdd(process_select_attributes, xstrdup("pgid")); } if (SelectProcRangeMatch("VSZ", "SZ", a.min_vsize, a.max_vsize, names, column)) { StringSetAdd(process_select_attributes, xstrdup("vsize")); } if (SelectProcRangeMatch("RSS", "RSS", a.min_rsize, a.max_rsize, names, column)) { StringSetAdd(process_select_attributes, xstrdup("rsize")); } if (SelectProcTimeCounterRangeMatch("TIME", "TIME", a.min_ttime, a.max_ttime, names, column)) { StringSetAdd(process_select_attributes, xstrdup("ttime")); } if (SelectProcTimeAbsRangeMatch ("STIME", "START", a.min_stime, a.max_stime, names, column)) { StringSetAdd(process_select_attributes, xstrdup("stime")); } if (SelectProcRangeMatch("NI", "PRI", a.min_pri, a.max_pri, names, column)) { StringSetAdd(process_select_attributes, xstrdup("priority")); } if (SelectProcRangeMatch("NLWP", "NLWP", a.min_thread, a.max_thread, names, column)) { StringSetAdd(process_select_attributes, xstrdup("threads")); } if (SelectProcRegexMatch("S", "STAT", a.status, names, column)) { StringSetAdd(process_select_attributes, xstrdup("status")); } if (SelectProcRegexMatch("CMD", "COMMAND", a.command, names, column)) { StringSetAdd(process_select_attributes, xstrdup("command")); } if (SelectProcRegexMatch("TTY", "TTY", a.tty, names, column)) { StringSetAdd(process_select_attributes, xstrdup("tty")); } if (!a.process_result) { if (StringSetSize(process_select_attributes) == 0) { result = EvalProcessResult("", process_select_attributes); } else { Writer *w = StringWriter(); StringSetIterator iter = StringSetIteratorInit(process_select_attributes); char *attr = StringSetIteratorNext(&iter); WriterWrite(w, attr); while ((attr = StringSetIteratorNext(&iter))) { WriterWriteChar(w, '.'); WriterWrite(w, attr); } result = EvalProcessResult(StringWriterData(w), process_select_attributes); WriterClose(w); } } else { result = EvalProcessResult(a.process_result, process_select_attributes); } StringSetDestroy(process_select_attributes); for (i = 0; column[i] != NULL; i++) { free(column[i]); } return result; } Item *SelectProcesses(const Item *processes, const char *process_name, ProcessSelect a, bool attrselect) { Item *result = NULL; if (processes == NULL) { return result; } char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; GetProcessColumnNames(processes->name, &names[0], start, end); pcre *rx = CompileRegex(process_name); if (rx) { for (Item *ip = processes->next; ip != NULL; ip = ip->next) { int s, e; if (StringMatchWithPrecompiledRegex(rx, ip->name, &s, &e)) { if (NULL_OR_EMPTY(ip->name)) { continue; } if (attrselect && !SelectProcess(ip->name, names, start, end, a)) { continue; } pid_t pid = ExtractPid(ip->name, names, end); if (pid == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to extract pid while looking for %s", process_name); continue; } PrependItem(&result, ip->name, ""); result->counter = (int)pid; } } pcre_free(rx); } for (int i = 0; i < CF_PROCCOLS; i++) { free(names[i]); } return result; } static int SelectProcRangeMatch(char *name1, char *name2, int min, int max, char **names, char **line) { int i; long value; if ((min == CF_NOINT) || (max == CF_NOINT)) { return false; } if ((i = GetProcColumnIndex(name1, name2, names)) != -1) { value = IntFromString(line[i]); if (value == CF_NOINT) { Log(LOG_LEVEL_INFO, "Failed to extract a valid integer from '%s' => '%s' in process list", names[i], line[i]); return false; } if ((min <= value) && (value <= max)) { return true; } else { return false; } } return false; } /***************************************************************************/ static long TimeCounter2Int(const char *s) { long days, hours, minutes, seconds; if (s == NULL) { return CF_NOINT; } /* If we match dd-hh:mm[:ss], believe it: */ int got = sscanf(s, "%ld-%ld:%ld:%ld", &days, &hours, &minutes, &seconds); if (got > 2) { /* All but perhaps seconds set */ } /* Failing that, try matching hh:mm[:ss] */ else if (1 < (got = sscanf(s, "%ld:%ld:%ld", &hours, &minutes, &seconds))) { /* All but days and perhaps seconds set */ days = 0; got++; } else { Log(LOG_LEVEL_ERR, "Unable to parse 'ps' time field as [dd-]hh:mm[:ss], got '%s'", s); return CF_NOINT; } assert(got > 2); /* i.e. all but maybe seconds have been set */ /* Clear seconds if unset: */ if (got < 4) { seconds = 0; } Log(LOG_LEVEL_DEBUG, "TimeCounter2Int: Parsed '%s' as elapsed time '%ld-%02ld:%02ld:%02ld'", s, days, hours, minutes, seconds); /* Convert to seconds: */ return ((days * 24 + hours) * 60 + minutes) * 60 + seconds; } static int SelectProcTimeCounterRangeMatch(char *name1, char *name2, time_t min, time_t max, char **names, char **line) { if ((min == CF_NOINT) || (max == CF_NOINT)) { return false; } int i = GetProcColumnIndex(name1, name2, names); if (i != -1) { time_t value = (time_t) TimeCounter2Int(line[i]); if (value == CF_NOINT) { Log(LOG_LEVEL_INFO, "Failed to extract a valid integer from %c => '%s' in process list", name1[i], line[i]); return false; } if ((min <= value) && (value <= max)) { Log(LOG_LEVEL_VERBOSE, "Selection filter matched counter range '%s/%s' = '%s' in [%jd,%jd] (= %jd secs)", name1, name2, line[i], (intmax_t)min, (intmax_t)max, (intmax_t)value); return true; } else { Log(LOG_LEVEL_DEBUG, "Selection filter REJECTED counter range '%s/%s' = '%s' in [%jd,%jd] (= %jd secs)", name1, name2, line[i], (intmax_t) min, (intmax_t) max, (intmax_t) value); return false; } } return false; } static time_t TimeAbs2Int(const char *s) { if (s == NULL) { return CF_NOINT; } struct tm tm; localtime_r(&CFSTARTTIME, &tm); tm.tm_sec = 0; tm.tm_isdst = -1; /* Try various ways to parse s: */ char word[4]; /* Abbreviated month name */ long ns[3]; /* Miscellaneous numbers, diverse readings */ int got = sscanf(s, "%2ld:%2ld:%2ld", ns, ns + 1, ns + 2); if (1 < got) /* Hr:Min[:Sec] */ { tm.tm_hour = ns[0]; tm.tm_min = ns[1]; if (got == 3) { tm.tm_sec = ns[2]; } } /* or MMM dd (the %ld shall ignore any leading space) */ else if (2 == sscanf(s, "%3[a-zA-Z]%ld", word, ns) && /* Only match if word is a valid month text: */ 0 < (ns[1] = Month2Int(word))) { int month = ns[1] - 1; if (tm.tm_mon < month) { /* Wrapped around */ tm.tm_year--; } tm.tm_mon = month; tm.tm_mday = ns[0]; tm.tm_hour = 0; tm.tm_min = 0; } /* or just year, or seconds since 1970 */ else if (1 == sscanf(s, "%ld", ns)) { if (ns[0] > 9999) { /* Seconds since 1970. * * This is the amended value SplitProcLine() replaces * start time with if it's imprecise and a better value * can be calculated from elapsed time. */ return (time_t)ns[0]; } /* else year, at most four digits; either 4-digit CE or * already relative to 1900. */ memset(&tm, 0, sizeof(tm)); tm.tm_year = ns[0] < 999 ? ns[0] : ns[0] - 1900; tm.tm_isdst = -1; } else { return CF_NOINT; } return mktime(&tm); } static int SelectProcTimeAbsRangeMatch(char *name1, char *name2, time_t min, time_t max, char **names, char **line) { int i; time_t value; if ((min == CF_NOINT) || (max == CF_NOINT)) { return false; } if ((i = GetProcColumnIndex(name1, name2, names)) != -1) { value = TimeAbs2Int(line[i]); if (value == CF_NOINT) { Log(LOG_LEVEL_INFO, "Failed to extract a valid integer from %c => '%s' in process list", name1[i], line[i]); return false; } if ((min <= value) && (value <= max)) { Log(LOG_LEVEL_VERBOSE, "Selection filter matched absolute '%s/%s' = '%s(%jd)' in [%jd,%jd]", name1, name2, line[i], (intmax_t)value, (intmax_t)min, (intmax_t)max); return true; } else { return false; } } return false; } /***************************************************************************/ static bool SelectProcRegexMatch(const char *name1, const char *name2, const char *regex, char **colNames, char **line) { int i; if (regex == NULL) { return false; } if ((i = GetProcColumnIndex(name1, name2, colNames)) != -1) { if (StringMatchFull(regex, line[i])) { return true; } else { return false; } } return false; } /*******************************************************************/ /* line must be char *line[CF_PROCCOLS] in fact. */ static int SplitProcLine(const char *proc, char **names, int *start, int *end, char **line) { if (proc == NULL || proc[0] == '\0') { return false; } memset(line, 0, sizeof(char *) * CF_PROCCOLS); const char *sp = proc; /* Scan in parallel for two heuristics: space-delimited fields * found using sp, and ones inferred from the column headers. */ for (int i = 0; i < CF_PROCCOLS && names[i] != NULL; i++) { /* Space-delimited heuristic, from sp to just before ep: */ while (isspace((unsigned char) sp[0])) { sp++; } const char *ep = sp; /* Header-driven heuristic, field from proc[s] to proc[e]. * Start with the column header's position and maybe grow * outwards. */ int s = start[i], e; if (i + 1 == CF_PROCCOLS || names[i + 1] == NULL) { e = strlen(proc) - 1; /* Extend space-delimited field to line end: */ while (ep[0] && ep[0] != '\n') { ep++; } /* But trim trailing hspace: */ while (isspace((unsigned char)ep[-1])) { ep--; } } else { e = end[i]; /* Extend space-delimited to next space: */ while (ep[0] && !isspace((unsigned char)ep[0])) { ep++; } } /* ep points at the space (or '\0') *following* the word or * final field. */ /* Some ps stimes may contain spaces, e.g. "Jan 25" */ if (strcmp(names[i], "STIME") == 0 && ep - sp == 3) { const char *np = ep; while (isspace((unsigned char) np[0])) { np++; } if (isdigit((unsigned char) np[0])) { do { np++; } while (isdigit((unsigned char) np[0])); ep = np; } } /* Numeric columns, including times, are apt to grow leftwards * and be right-aligned; identify candidates for this by * proc[e] being a digit. Text columns are typically * left-aligned and may grow rightwards; identify candidates * for this by proc[s] being alphabetic. Some columns shall * match both (e.g. STIME). Some numeric columns may grow * left even as far as under the heading of the next column * (seen with ps -fel's SZ spilling left into ADDR's space on * Linux). While widening, it's OK to include a stray space; * we'll trim that afterwards. Overspill from neighbouring * columns can muck up alignment, so "digit" means any * character that can appear in a numeric field (we may need * to tweak "alphabetic" likewise for text fields; the user * field can, for example, have a '+' appended). */ bool overspilt = false; /* Numeric fields may include [-.:] and perhaps other * punctuators: */ #define IsNumberish(c) (isdigit((unsigned char)(c)) || ispunct((unsigned char)(c))) /* Right-aligned numeric: move s left until we run outside the * field or find space. */ if (IsNumberish(proc[e])) { bool number = i > 0; /* Should we check for under-spill ? */ int outer = number ? end[i - 1] + 1 : 0; while (s >= outer && !isspace((unsigned char) proc[s])) { if (number && !IsNumberish(proc[s])) { number = false; } s--; } /* Numeric field might overspill under previous header: */ if (s < outer) { int spill = s; s = outer; /* By default, don't overlap previous column. */ if (number && IsNumberish(proc[spill])) { outer = start[i - 1]; /* Explore all the way to the start-column of the * previous field's header. If we get there, in * digits-and-punctuation, we've got two numeric * fields that abut; we can't do better than assume * the boundary is under the right end of the previous * column label (which is what our parsing of the * previous column assumed). So leave s where it is, * just after the previous field's header's * end-column. */ while (spill > outer) { spill--; if (!IsNumberish(proc[spill])) { s = spill + 1; /* Confirmed overlap. */ break; } } } } overspilt = IsNumberish(proc[e + 1]); } #undef IsNumberish /* Left-aligned text or numeric misaligned by overspill; * move e right (but never under next heading): */ if (overspilt || isalpha((unsigned char) proc[s])) { int outer; if (i + 1 < CF_PROCCOLS && names[i + 1]) { outer = start[i + 1]; } else { outer = strlen(proc); } /* Simplify loop condition; we want e to end *before* next * field, not on its first byte (or the terminator): */ outer--; while (e < outer && !isspace((unsigned char) proc[e])) { e++; } } /* Strip off any leading and trailing spaces: */ while (isspace((unsigned char) proc[s])) { s++; } /* ... but stop if the field is empty ! */ while (s <= e && isspace((unsigned char) proc[e])) { e--; } /* Grumble if the two heuristics don't agree: */ size_t wordlen = ep - sp; if (e < s ? ep > sp : (sp != proc + s || ep != proc + e + 1)) { char word[CF_SMALLBUF]; if (wordlen >= CF_SMALLBUF) { wordlen = CF_SMALLBUF - 1; } memcpy(word, sp, wordlen); word[wordlen] = '\0'; char column[CF_SMALLBUF]; if (s <= e) { /* Copy proc[s through e] inclusive: */ const size_t len = MIN(1 + e - s, CF_SMALLBUF - 1); memcpy(column, proc + s, len); column[len] = '\0'; } else { column[0] = '\0'; } Log(LOG_LEVEL_VERBOSE, "Unreliable fuzzy parsing of ps output (%s) %s: '%s' != '%s'", proc, names[i], word, column); } /* Fall back on word if column got an empty answer: */ line[i] = e < s ? xstrndup(sp, ep - sp) : xstrndup(proc + s, 1 + e - s); sp = ep; } /* Since start times can be very imprecise (e.g. just a past day's * date, or a past year), calculate a better value from elapsed * time, if available: */ int k = GetProcColumnIndex("ELAPSED", "ELAPSED", names); if (k != -1) { const long elapsed = TimeCounter2Int(line[k]); if (elapsed != CF_NOINT) /* Only use if parsed successfully ! */ { int j = GetProcColumnIndex("STIME", "START", names), ns[3]; /* Trust the reported value if it matches hh:mm[:ss], though: */ if (sscanf(line[j], "%d:%d:%d", ns, ns + 1, ns + 2) < 2) { /* TODO: use time of ps-run, not time(NULL), which may be later. */ time_t value = time(NULL) - (time_t) elapsed; Log(LOG_LEVEL_DEBUG, "SplitProcLine: Replacing parsed start time %s with %s", line[j], ctime(&value)); free(line[j]); xasprintf(line + j, "%ld", value); } } } return true; } /*******************************************************************/ static int GetProcColumnIndex(const char *name1, const char *name2, char **names) { for (int i = 0; names[i] != NULL; i++) { if (strcmp(names[i], name1) == 0 || strcmp(names[i], name2) == 0) { return i; } } Log(LOG_LEVEL_VERBOSE, "Process column %s/%s was not supported on this system", name1, name2); return -1; } /**********************************************************************************/ bool IsProcessNameRunning(char *procNameRegex) { char *colHeaders[CF_PROCCOLS]; int start[CF_PROCCOLS] = { 0 }; int end[CF_PROCCOLS] = { 0 }; bool matched = false; int i; if (PROCESSTABLE == NULL) { Log(LOG_LEVEL_ERR, "IsProcessNameRunning: PROCESSTABLE is empty"); return false; } GetProcessColumnNames(PROCESSTABLE->name, (char **) colHeaders, start, end); for (const Item *ip = PROCESSTABLE->next; !matched && ip != NULL; ip = ip->next) // iterate over ps lines { char *lineSplit[CF_PROCCOLS]; if (NULL_OR_EMPTY(ip->name)) { continue; } if (!SplitProcLine(ip->name, colHeaders, start, end, lineSplit)) { Log(LOG_LEVEL_ERR, "IsProcessNameRunning: Could not split process line '%s'", ip->name); continue; } if (SelectProcRegexMatch("CMD", "COMMAND", procNameRegex, colHeaders, lineSplit)) { matched = true; } for (i = 0; lineSplit[i] != NULL; i++) { free(lineSplit[i]); } } for (i = 0; colHeaders[i] != NULL; i++) { free(colHeaders[i]); } return matched; } static void GetProcessColumnNames(char *proc, char **names, int *start, int *end) { char *sp, title[16]; int col, offset = 0; for (col = 0; col < CF_PROCCOLS; col++) { start[col] = end[col] = -1; names[col] = NULL; } col = 0; for (sp = proc; *sp != '\0'; sp++) { offset = sp - proc; if (isspace((unsigned char) *sp)) { if (start[col] != -1) { Log(LOG_LEVEL_DEBUG, "End of '%s' is %d", title, offset - 1); end[col++] = offset - 1; if (col > CF_PROCCOLS - 1) { Log(LOG_LEVEL_ERR, "Column overflow in process table"); break; } } } else if (start[col] == -1) { start[col] = offset; sscanf(sp, "%15s", title); Log(LOG_LEVEL_DEBUG, "Start of '%s' is %d", title, offset); names[col] = xstrdup(title); Log(LOG_LEVEL_DEBUG, "Col[%d] = '%s'", col, names[col]); } } if (end[col] == -1) { Log(LOG_LEVEL_DEBUG, "End of '%s' is %d", title, offset); end[col] = offset; } } #ifndef __MINGW32__ static const char *GetProcessOptions(void) { # ifdef __linux__ if (strncmp(VSYSNAME.release, "2.4", 3) == 0) { // No threads on 2.4 kernels return "-eo user,pid,ppid,pgid,pcpu,pmem,vsz,pri,rss,stime,time,args"; } # endif return VPSOPTS[VSYSTEMHARDCLASS]; } #endif static int ExtractPid(char *psentry, char **names, int *end) { int offset = 0; for (int col = 0; col < CF_PROCCOLS; col++) { if (strcmp(names[col], "PID") == 0) { if (col > 0) { offset = end[col - 1]; } break; } } for (const char *sp = psentry + offset; *sp != '\0'; sp++) /* if first field contains alpha, skip */ { /* If start with alphanum then skip it till the first space */ if (isalnum((unsigned char) *sp)) { while (*sp != ' ' && *sp != '\0') { sp++; } } while (*sp == ' ' || *sp == '\t') { sp++; } int pid; if (sscanf(sp, "%d", &pid) == 1 && pid != -1) { return pid; } } return -1; } # ifndef __MINGW32__ # ifdef HAVE_GETZONEID /* ListLookup with the following return semantics * -1 if the first argument is smaller than the second * 0 if the arguments are equal * 1 if the first argument is bigger than the second */ int PidListCompare(const void *pid1, const void *pid2, ARG_UNUSED void *user_data) { int p1 = (intptr_t)(void *)pid1; int p2 = (intptr_t)(void *)pid2; if (p1 < p2) { return -1; } else if (p1 > p2) { return 1; } return 0; } /* Load processes using zone-aware ps * to obtain solaris list of global * process ids for root and non-root * users to lookup later */ int ZLoadProcesstable(Seq *pidlist, Seq *rootpidlist) { char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; int index = 0; const char *pscmd = "/usr/bin/ps -Aleo zone,user,pid"; FILE *psf = cf_popen(pscmd, "r", false); if (psf == NULL) { Log(LOG_LEVEL_ERR, "ZLoadProcesstable: Couldn't open the process list with command %s.", pscmd); return false; } size_t pbuff_size = CF_BUFSIZE; char *pbuff = xmalloc(pbuff_size); while (true) { ssize_t res = CfReadLine(&pbuff, &pbuff_size, psf); if (res == -1) { if (!feof(psf)) { Log(LOG_LEVEL_ERR, "IsGlobalProcess(char **, int): Unable to read process list with command '%s'. (fread: %s)", pscmd, GetErrorStr()); cf_pclose(psf); free(pbuff); return false; } else { break; } } Chop(pbuff, pbuff_size); if (strstr(pbuff, "PID")) /*this is the banner*/ { GetProcessColumnNames(pbuff, &names[0], start, end); } else { int pid = ExtractPid(pbuff, &names[0], end); size_t zone_offset = strspn(pbuff, " "); size_t zone_end_offset = strcspn(pbuff + zone_offset, " ") + zone_offset; size_t user_offset = strspn(pbuff + zone_end_offset, " ") + zone_end_offset; size_t user_end_offset = strcspn(pbuff + user_offset, " ") + user_offset; bool is_global = (zone_end_offset - zone_offset == 6 && strncmp(pbuff + zone_offset, "global", 6) == 0); bool is_root = (user_end_offset - user_offset == 4 && strncmp(pbuff + user_offset, "root", 4) == 0); if (is_global && is_root) { SeqAppend(rootpidlist, (void*)(intptr_t)pid); } else if (is_global && !is_root) { SeqAppend(pidlist, (void*)(intptr_t)pid); } } } cf_pclose(psf); free(pbuff); return true; } bool PidInSeq(Seq *list, int pid) { void *res = SeqLookup(list, (void *)(intptr_t)pid, PidListCompare); int result = (intptr_t)(void*)res; if (result == pid) { return true; } return false; } /* return true if the process with * pid is in the global zone */ int IsGlobalProcess(int pid, Seq *pidlist, Seq *rootpidlist) { if (PidInSeq(pidlist, pid) || PidInSeq(rootpidlist, pid)) { return true; } else { return false; } } void ZCopyProcessList(Item **dest, const Item *source, Seq *pidlist, char **names, int *end) { int gpid = ExtractPid(source->name, names, end); if (PidInSeq(pidlist, gpid)) { PrependItem(dest, source->name, ""); } } # endif /* HAVE_GETZONEID */ int LoadProcessTable(Item **procdata) { FILE *prp; char pscomm[CF_MAXLINKSIZE]; Item *rootprocs = NULL; Item *otherprocs = NULL; if (PROCESSTABLE) { Log(LOG_LEVEL_VERBOSE, "Reusing cached process table"); return true; } const char *psopts = GetProcessOptions(); snprintf(pscomm, CF_MAXLINKSIZE, "%s %s", VPSCOMM[VSYSTEMHARDCLASS], psopts); Log(LOG_LEVEL_VERBOSE, "Observe process table with %s", pscomm); if ((prp = cf_popen(pscomm, "r", false)) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open the process list with command '%s'. (popen: %s)", pscomm, GetErrorStr()); return false; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); # ifdef HAVE_GETZONEID char *names[CF_PROCCOLS]; int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; Seq *pidlist = SeqNew(1, NULL); Seq *rootpidlist = SeqNew(1, NULL); bool global_zone = IsGlobalZone(); if (global_zone) { int res = ZLoadProcesstable(pidlist, rootpidlist); if (res == false) { Log(LOG_LEVEL_ERR, "Unable to load solaris zone process table."); return false; } } # endif for (;;) { ssize_t res = CfReadLine(&vbuff, &vbuff_size, prp); if (res == -1) { if (!feof(prp)) { Log(LOG_LEVEL_ERR, "Unable to read process list with command '%s'. (fread: %s)", pscomm, GetErrorStr()); cf_pclose(prp); free(vbuff); return false; } else { break; } } Chop(vbuff, vbuff_size); # ifdef HAVE_GETZONEID if (global_zone) { if (strstr(vbuff, "PID") != NULL) { /* this is the banner so get the column header names for later use*/ GetProcessColumnNames(vbuff, &names[0], start, end); } else { int gpid = ExtractPid(vbuff, names, end); if (!IsGlobalProcess(gpid, pidlist, rootpidlist)) { continue; } } } # endif AppendItem(procdata, vbuff, ""); } cf_pclose(prp); /* Now save the data */ snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_procs", CFWORKDIR); RawSaveItemList(*procdata, vbuff, NewLineMode_Unix); # ifdef HAVE_GETZONEID if (global_zone) /* pidlist and rootpidlist are empty if we're not in the global zone */ { Item *ip = *procdata; while (ip != NULL) { ZCopyProcessList(&rootprocs, ip, rootpidlist, names, end); ip = ip->next; } ReverseItemList(rootprocs); ip = *procdata; while (ip != NULL) { ZCopyProcessList(&otherprocs, ip, pidlist, names, end); ip = ip->next; } ReverseItemList(otherprocs); } else # endif { CopyList(&rootprocs, *procdata); CopyList(&otherprocs, *procdata); while (DeleteItemNotContaining(&rootprocs, "root")) { } while (DeleteItemContaining(&otherprocs, "root")) { } } if (otherprocs) { PrependItem(&rootprocs, otherprocs->name, NULL); } snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_rootprocs", CFWORKDIR); RawSaveItemList(rootprocs, vbuff, NewLineMode_Unix); DeleteItemList(rootprocs); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_otherprocs", CFWORKDIR); RawSaveItemList(otherprocs, vbuff, NewLineMode_Unix); DeleteItemList(otherprocs); free(vbuff); return true; } # endif cfengine-3.6.2/libpromises/sort.h0000644000175100017510000000334312316547775016530 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SORT_H #define CFENGINE_SORT_H /* * Sorting is destructive, use the returned pointer to refer to sorted list. */ Item *SortItemListNames(Item *list); /* Alphabetical */ Item *SortItemListClasses(Item *list); /* Alphabetical */ Item *SortItemListCounters(Item *list); /* Reverse sort */ Item *SortItemListTimes(Item *list); /* Reverse sort */ Rlist *SortRlist(Rlist *list, int (*CompareItems) ()); Rlist *AlphaSortRListNames(Rlist *list); Rlist *IntSortRListNames(Rlist *list); Rlist *RealSortRListNames(Rlist *list); Rlist *IPSortRListNames(Rlist *list); Rlist *MACSortRListNames(Rlist *list); bool GenericItemLess(const char *mode, void *lhs, void *rhs); bool GenericStringItemLess(const char *sort_type, const char *lhs, const char *rhs); #endif cfengine-3.6.2/libpromises/bootstrap.h0000644000175100017510000000554412316547775017563 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_BOOTSTRAP_H #define CFENGINE_BOOTSTRAP_H #include /** * @brief Sets sys.policy_hub and the POLICY_SERVER global. * @param ctx EvalContext is used to set related variables * @param new_policy_server IP of new policy server */ void SetPolicyServer(EvalContext *ctx, const char *new_policy_server); /** * @brief Updates sys.last_policy_update variable from $(sys.masterdir)/cf_promises_validated * @param ctx EvalContext to put variable into */ void UpdateLastPolicyUpdateTime(EvalContext *ctx); /** * @return The contents of policy_server.dat, or NULL if file is not found. Return value must be freed. */ char *ReadPolicyServerFile(const char *workdir); /** * @brief Write new_policy_server to the policy_server.dat file. * @return True if successful */ bool WritePolicyServerFile(const char *workdir, const char *new_policy_server); /** * @brief Remove the policy_server.dat file * @return True if successful */ bool RemovePolicyServerFile(const char *workdir); /** * @return True if the file WORKDIR/state/am_policy_hub exists */ bool GetAmPolicyHub(const char *workdir); /** * @brief Set the am_policy_hub marker file. If am_policy_hub is true, create the file. If false, delete it. * @return True if successful */ bool WriteAmPolicyHubFile(const char *workdir, bool am_policy_hub); /** * @brief Write the builtin failsafe policy to the default location * @return True if succesful */ bool WriteBuiltinFailsafePolicy(const char *workdir); /** * @brief Exposed for testing. Use WriteBuiltinFailsafePolicy. */ bool WriteBuiltinFailsafePolicyToPath(const char *filename); /** * @brief Removes all files in $(sys.inputdir) * @param inputdir * @return True if succesful */ bool RemoveAllExistingPolicyInInputs(const char *inputdir); /** * @return True if the file $(sys.masterdir)/promises.cf exists */ bool MasterfileExists(const char *masterdir); #endif cfengine-3.6.2/libpromises/constants.c0000664000175100017510000001343612411001073017522 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include const char *const DAY_TEXT[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", NULL }; const char *const MONTH_TEXT[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL }; const char *const SHIFT_TEXT[] = { "Night", "Morning", "Afternoon", "Evening", NULL }; const char *const CF_AGENTTYPES[] = /* see enum cfagenttype */ { CF_COMMONC, CF_AGENTC, CF_SERVERC, CF_MONITORC, CF_EXECC, CF_RUNC, CF_KEYGEN, CF_HUBC, "", }; const char *const OBS[CF_OBSERVABLES][2] = { {"users", "Users with active processes - including system users"}, {"rootprocs", "Sum privileged system processes"}, {"otherprocs", "Sum non-privileged process"}, {"diskfree", "Free disk on / partition"}, {"loadavg", "Kernel load average utilization (sum over cores)"}, {"netbiosns_in", "netbios name lookups (in)"}, {"netbiosns_out", "netbios name lookups (out)"}, {"netbiosdgm_in", "netbios name datagrams (in)"}, {"netbiosdgm_out", "netbios name datagrams (out)"}, {"netbiosssn_in", "Samba/netbios name sessions (in)"}, {"netbiosssn_out", "Samba/netbios name sessions (out)"}, {"imap_in", "imap mail client sessions (in)"}, {"imap_out", "imap mail client sessions (out)"}, {"cfengine_in", "cfengine connections (in)"}, {"cfengine_out", "cfengine connections (out)"}, {"nfsd_in", "nfs connections (in)"}, {"nfsd_out", "nfs connections (out)"}, {"smtp_in", "smtp connections (in)"}, {"smtp_out", "smtp connections (out)"}, {"www_in", "www connections (in)"}, {"www_out", "www connections (out)"}, {"ftp_in", "ftp connections (in)"}, {"ftp_out", "ftp connections (out)"}, {"ssh_in", "ssh connections (in)"}, {"ssh_out", "ssh connections (out)"}, {"wwws_in", "wwws connections (in)"}, {"wwws_out", "wwws connections (out)"}, {"icmp_in", "ICMP packets (in)"}, {"icmp_out", "ICMP packets (out)"}, {"udp_in", "UDP dgrams (in)"}, {"udp_out", "UDP dgrams (out)"}, {"dns_in", "DNS requests (in)"}, {"dns_out", "DNS requests (out)"}, {"tcpsyn_in", "TCP sessions (in)"}, {"tcpsyn_out", "TCP sessions (out)"}, {"tcpack_in", "TCP acks (in)"}, {"tcpack_out", "TCP acks (out)"}, {"tcpfin_in", "TCP finish (in)"}, {"tcpfin_out", "TCP finish (out)"}, {"tcpmisc_in", "TCP misc (in)"}, {"tcpmisc_out", "TCP misc (out)"}, {"webaccess", "Webserver hits"}, {"weberrors", "Webserver errors"}, {"syslog", "New log entries (Syslog)"}, {"messages", "New log entries (messages)"}, {"temp0", "CPU Temperature 0"}, {"temp1", "CPU Temperature 1"}, {"temp2", "CPU Temperature 2"}, {"temp3", "CPU Temperature 3"}, {"cpu", "%CPU utilization (all)"}, {"cpu0", "%CPU utilization 0"}, {"cpu1", "%CPU utilization 1"}, {"cpu2", "%CPU utilization 2"}, {"cpu3", "%CPU utilization 3"}, {"microsoft_ds_in", "Samba/MS_ds name sessions (in)"}, {"microsoft_ds_out", "Samba/MS_ds name sessions (out)"}, {"www_alt_in", "Alternative web service connections (in)"}, {"www_alt_out", "Alternative web client connections (out)"}, {"imaps_in", "encrypted imap mail service sessions (in)"}, {"imaps_out", "encrypted imap mail client sessions (out)"}, {"ldap_in", "LDAP directory service service sessions (in)"}, {"ldap_out", "LDAP directory service client sessions (out)"}, {"ldaps_in", "LDAP directory service service sessions (in)"}, {"ldaps_out", "LDAP directory service client sessions (out)"}, {"mongo_in", "Mongo database service sessions (in)"}, {"mongo_out", "Mongo database client sessions (out)"}, {"mysql_in", "MySQL database service sessions (in)"}, {"mysql_out", "MySQL database client sessions (out)"}, {"postgres_in", "PostgreSQL database service sessions (in)"}, {"postgres_out", "PostgreSQL database client sessions (out)"}, {"ipp_in", "Internet Printer Protocol (in)"}, {"ipp_out", "Internet Printer Protocol (out)"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, {"spare", "unused"}, }; cfengine-3.6.2/libpromises/bootstrap.inc0000664000175100017510000002545312411001073020054 0ustar00a10038a1003800000000000000 "################################################################################\n" "## CFEngine Bootstrap / Failsafe Policy ########################################\n" "################################################################################\n" "# THIS FILE REPRESENTS A FALL-BACK SOLUTION FOR THE PRIMARY FAILSAFE FILE.\n" "# IF THE PRIMARY FAILSAFE/UPDATE LOSES FUNCTIONALITY DUE TO MODIFICATIONS MADE\n" "# BY THE USER, CFENGINE WILL RECOVER BY USING THIS FALL-BACK BOOTSTRAPPED FILE.\n" "# NEVER EDIT THIS FILE, YOU WILL HAVE TO LOG ON TO EVERY NODE MANAGED BY\n" "# CFENGINE TO RECTIFY POTENTIAL ERRORS IF SOMETHING GOES WRONG.\n" "################################################################################\n" "\n" "body common control\n" "{\n" " bundlesequence => { \"cfe_internal_update\", \"cfe_internal_call_update\" };\n" "}\n" "\n" "################################################################################\n" "\n" "body agent control\n" "{\n" " skipidentify => \"true\";\n" "}\n" "\n" "################################################################################\n" "\n" "bundle agent cfe_internal_update\n" "{\n" " classes:\n" "\n" " any::\n" "\n" " \"have_ppkeys\"\n" " expression => fileexists(\"$(sys.workdir)/ppkeys/localhost.pub\"),\n" " handle => \"cfe_internal_bootstrap_update_classes_have_ppkeys\";\n" "\n" " \"have_promises_cf\"\n" " expression => fileexists(\"$(sys.inputdir)/promises.cf\"),\n" " handle => \"cfe_internal_bootstrap_update_classes_have_promises_cf\";\n" "\n" " #\n" "\n" " commands:\n" "\n" " !have_ppkeys::\n" "\n" " \"$(sys.cf_key)\"\n" " handle => \"cfe_internal_bootstrap_update_commands_generate_keys\";\n" "\n" " #\n" "\n" " files:\n" "\n" " !windows.have_ppkeys::\n" "\n" " \"$(sys.inputdir)\"\n" " handle => \"cfe_internal_bootstrap_update_files_sys_workdir_inputs_not_windows\",\n" " copy_from => u_scp(\"$(sys.masterdir)\"),\n" " depth_search => u_recurse(\"inf\"),\n" " classes => repaired(\"got_policy\");\n" "\n" " windows.have_ppkeys::\n" "\n" " \"$(sys.inputdir)\"\n" " handle => \"cfe_internal_bootstrap_update_files_sys_workdir_inputs_windows\",\n" " copy_from => u_scp(\"/var/cfengine/masterfiles\"), # Not $(sys.masterdir) when referring to remote host.\n" " depth_search => u_recurse(\"inf\"),\n" " classes => repaired(\"got_policy\");\n" "\n" " \"$(sys.workdir)\\\\bin-twin\\\\.\"\n" " handle => \"cfe_internal_bootstrap_update_files_sys_workdir_bin_twin_windows\",\n" " comment => \"Make sure we maintain a clone of the binaries and libraries for updating\",\n" " copy_from => u_cp(\"$(sys.workdir)\\\\bin\\\\.\"),\n" " depth_search => u_recurse(\"1\");\n" "\n" " #\n" "\n" " processes:\n" "\n" " !windows.got_policy::\n" "\n" " \"cf-execd\" restart_class => \"start_exec\",\n" " handle => \"cfe_internal_bootstrap_update_processes_start_cf_execd\";\n" "\n" " am_policy_hub.got_policy::\n" "\n" " \"cf-serverd\" restart_class => \"start_server\",\n" " handle => \"cfe_internal_bootstrap_update_processes_start_cf_serverd\";\n" "\n" " #\n" "\n" " commands:\n" "\n" " start_exec.!windows::\n" "\n" " \"$(sys.cf_execd)\"\n" " handle => \"cfe_internal_bootstrap_update_commands_check_sys_cf_execd_start\",\n" " classes => repaired(\"executor_started\");\n" "\n" " start_server::\n" "\n" " \"$(sys.cf_serverd)\"\n" " handle => \"cfe_internal_bootstrap_update_commands_check_sys_cf_serverd_start\",\n" " action => ifwin_bg,\n" " classes => repaired(\"server_started\");\n" "\n" " #\n" "\n" " services:\n" "\n" " windows.got_policy::\n" "\n" " \"CfengineNovaExec\"\n" " handle => \"cfe_internal_bootstrap_update_services_windows_executor\",\n" " service_policy => \"start\",\n" " service_method => bootstart,\n" " classes => repaired(\"executor_started\");\n" "\n" " #\n" "\n" " reports:\n" "\n" " bootstrap_mode.am_policy_hub::\n" "\n" " \"This host assumes the role of policy server\"\n" " handle => \"cfe_internal_bootstrap_update_reports_assume_policy_hub\";\n" "\n" " bootstrap_mode.!am_policy_hub::\n" "\n" " \"This autonomous node assumes the role of voluntary client\"\n" " handle => \"cfe_internal_bootstrap_update_reports_assume_voluntary_client\";\n" "\n" " got_policy::\n" "\n" " \"Updated local policy from policy server\"\n" " handle => \"cfe_internal_bootstrap_update_reports_got_policy\";\n" "\n" " !got_policy.!have_promises_cf.have_ppkeys::\n" "\n" " \"Failed to copy policy from policy server at $(sys.policy_hub):$(sys.masterdir)\n" " Please check\n" " * cf-serverd is running on $(sys.policy_hub)\n" " * network connectivity to $(sys.policy_hub) on port 5308\n" " * masterfiles 'body server control' - in particular allowconnects, trustkeysfrom and skipverify\n" " * masterfiles 'bundle server' -> access: -> masterfiles -> admit/deny\n" " It is often useful to restart cf-serverd in verbose mode (cf-serverd -v) on $(sys.policy_hub) to diagnose connection issues.\n" " When updating masterfiles, wait (usually 5 minutes) for files to propagate to inputs on $(sys.policy_hub) before retrying.\"\n" " handle => \"cfe_internal_bootstrap_update_reports_did_not_get_policy\";\n" "\n" " server_started::\n" "\n" " \"Started the server\"\n" " handle => \"cfe_internal_bootstrap_update_reports_started_serverd\";\n" "\n" " am_policy_hub.!server_started.!have_promises_cf.have_ppkeys::\n" "\n" " \"Failed to start the server\"\n" " handle => \"cfe_internal_bootstrap_update_reports_failed_to_start_serverd\";\n" "\n" " executor_started::\n" "\n" " \"Started the scheduler\"\n" " handle => \"cfe_internal_bootstrap_update_reports_started_execd\";\n" "\n" " !executor_started.!have_promises_cf.have_ppkeys::\n" "\n" " \"Did not start the scheduler\"\n" " handle => \"cfe_internal_bootstrap_update_reports_failed_to_start_execd\";\n" "\n" " !executor_started.have_promises_cf::\n" "\n" " \"You are running a hard-coded failsafe. Please use the following command instead.\n" " $(sys.cf_agent) -f $(sys.inputdir)/update.cf\"\n" " handle => \"cfe_internal_bootstrap_update_reports_run_another_failsafe_instead\";\n" " \n" "}\n" "\n" "################################################################################\n" "bundle agent cfe_internal_call_update\n" "{\n" " commands:\n" "\n" " # On Windows we need cf-execd to call update.cf, otherwise the daemons will\n" " # not run under the SYSTEM account.\n" " !windows::\n" "\n" " \"$(sys.cf_agent) -f update.cf\"\n" " handle => \"cfe_internal_call_update_commands_call_update_cf\";\n" "\n" "}\n" "############################################\n" "body classes repaired(x)\n" "{\n" " promise_repaired => {\"$(x)\"};\n" "}\n" "############################################\n" "body perms u_p(p)\n" "{\n" " mode => \"$(p)\";\n" "}\n" "#############################################\n" "body copy_from u_scp(from)\n" "{\n" " source => \"$(from)\";\n" " compare => \"digest\";\n" " trustkey => \"true\";\n" " !am_policy_hub::\n" " servers => { \"$(sys.policy_hub)\" };\n" "}\n" "############################################\n" "body action u_background\n" "{\n" " background => \"true\";\n" "}\n" "############################################\n" "body depth_search u_recurse(d)\n" "{\n" " depth => \"$(d)\";\n" " exclude_dirs => { \"\\.svn\", \"\\.git\" };\n" "}\n" "############################################\n" "body service_method bootstart\n" "{\n" " service_autostart_policy => \"boot_time\";\n" "}\n" "############################################\n" "body action ifwin_bg\n" "{\n" " windows::\n" " background => \"true\";\n" "}\n" "############################################\n" "body copy_from u_cp(from)\n" "{\n" " source => \"$(from)\";\n" " compare => \"digest\";\n" " copy_backup => \"false\";\n" "}\n" cfengine-3.6.2/libpromises/generic_agent.c0000664000175100017510000013172312411001073020300 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static pthread_once_t pid_cleanup_once = PTHREAD_ONCE_INIT; /* GLOBAL_T */ static char PIDFILE[CF_BUFSIZE] = ""; /* GLOBAL_C */ static void CheckWorkingDirectories(EvalContext *ctx); static void GetAutotagDir(char *dirname, size_t max_size, const char *maybe_dirname); static void GetPromisesValidatedFile(char *filename, size_t max_size, const GenericAgentConfig *config, const char *maybe_dirname); static bool WriteReleaseIdFile(const char *filename, const char *dirname); static bool GeneratePolicyReleaseIDFromGit(char *release_id_out, size_t out_size, const char *policy_dir); static bool GeneratePolicyReleaseID(char *release_id_out, size_t out_size, const char *policy_dir); static char* ReadReleaseIdFromReleaseIdFileMasterfiles(const char *maybe_dirname); static bool MissingInputFile(const char *input_file); #if !defined(__MINGW32__) static void OpenLog(int facility); #endif /*****************************************************************************/ static void SanitizeEnvironment() { /* ps(1) and other utilities invoked by CFEngine may be affected */ unsetenv("COLUMNS"); /* Make sure subprocesses output is not localized */ unsetenv("LANG"); unsetenv("LANGUAGE"); unsetenv("LC_MESSAGES"); } /*****************************************************************************/ ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, GenericAgentSetDefaultDigest, HashMethod *, digest, int *, digest_len) { *digest = HASH_METHOD_MD5; *digest_len = CF_MD5_LEN; } void MarkAsPolicyServer(EvalContext *ctx) { EvalContextClassPutHard(ctx, "am_policy_hub", "source=bootstrap,deprecated,alias=policy_server"); Log(LOG_LEVEL_VERBOSE, "Additional class defined: am_policy_hub"); EvalContextClassPutHard(ctx, "policy_server", "inventory,attribute_name=CFEngine roles,source=bootstrap"); Log(LOG_LEVEL_VERBOSE, "Additional class defined: policy_server"); } void GenericAgentDiscoverContext(EvalContext *ctx, GenericAgentConfig *config) { GenericAgentSetDefaultDigest(&CF_DEFAULT_DIGEST, &CF_DEFAULT_DIGEST_LEN); GenericAgentInitialize(ctx, config); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); SanitizeEnvironment(); THIS_AGENT_TYPE = config->agent_type; EvalContextClassPutHard(ctx, CF_AGENTTYPES[config->agent_type], "cfe_internal,source=agent"); DetectEnvironment(ctx); EvalContextHeapPersistentLoadAll(ctx); LoadSystemConstants(ctx); if (config->agent_type == AGENT_TYPE_AGENT && config->agent_specific.agent.bootstrap_policy_server) { if (!RemoveAllExistingPolicyInInputs(GetInputDir())) { Log(LOG_LEVEL_ERR, "Error removing existing input files prior to bootstrap"); exit(EXIT_FAILURE); } if (!WriteBuiltinFailsafePolicy(GetInputDir())) { Log(LOG_LEVEL_ERR, "Error writing builtin failsafe to inputs prior to bootstrap"); exit(EXIT_FAILURE); } bool am_policy_server = false; { const char *canonified_bootstrap_policy_server = CanonifyName(config->agent_specific.agent.bootstrap_policy_server); am_policy_server = NULL != EvalContextClassGet(ctx, NULL, canonified_bootstrap_policy_server); { char policy_server_ipv4_class[CF_BUFSIZE]; snprintf(policy_server_ipv4_class, CF_MAXVARSIZE, "ipv4_%s", canonified_bootstrap_policy_server); am_policy_server |= NULL != EvalContextClassGet(ctx, NULL, policy_server_ipv4_class); } if (am_policy_server) { Log(LOG_LEVEL_INFO, "Assuming role as policy server, with policy distribution point at %s", GetMasterDir()); MarkAsPolicyServer(ctx); if (!MasterfileExists(GetMasterDir())) { Log(LOG_LEVEL_ERR, "In order to bootstrap as a policy server, the file '%s/promises.cf' must exist.", GetMasterDir()); exit(EXIT_FAILURE); } } else { Log(LOG_LEVEL_INFO, "Not assuming role as policy server"); } WriteAmPolicyHubFile(CFWORKDIR, am_policy_server); } WritePolicyServerFile(GetWorkDir(), config->agent_specific.agent.bootstrap_policy_server); SetPolicyServer(ctx, config->agent_specific.agent.bootstrap_policy_server); if (am_policy_server) //It makes sense to check HA status only on policy hub. { CheckAndSetHAState(GetWorkDir(), ctx); } /* FIXME: Why it is called here? Can't we move both invocations to before if? */ UpdateLastPolicyUpdateTime(ctx); Log(LOG_LEVEL_INFO, "Bootstrapping to '%s'", POLICY_SERVER); } else { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); if (existing_policy_server) { Log(LOG_LEVEL_VERBOSE, "This agent is bootstrapped to '%s'", existing_policy_server); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); UpdateLastPolicyUpdateTime(ctx); } else { Log(LOG_LEVEL_VERBOSE, "This agent is not bootstrapped"); return; } if (GetAmPolicyHub(GetWorkDir())) { MarkAsPolicyServer(ctx); /* Should this go in MarkAsPolicyServer() ? */ CheckAndSetHAState(GetWorkDir(), ctx); } } } static bool IsPolicyPrecheckNeeded(GenericAgentConfig *config, bool force_validation) { bool check_policy = false; if (IsFileOutsideDefaultRepository(config->input_file)) { check_policy = true; Log(LOG_LEVEL_VERBOSE, "Input file is outside default repository, validating it"); } if (GenericAgentIsPolicyReloadNeeded(config)) { check_policy = true; Log(LOG_LEVEL_VERBOSE, "Input file is changed since last validation, validating it"); } if (force_validation) { check_policy = true; Log(LOG_LEVEL_VERBOSE, "always_validate is set, forcing policy validation"); } return check_policy; } bool GenericAgentCheckPolicy(GenericAgentConfig *config, bool force_validation, bool write_validated_file) { if (!MissingInputFile(config->input_file)) { { if (config->agent_type == AGENT_TYPE_SERVER || config->agent_type == AGENT_TYPE_MONITOR || config->agent_type == AGENT_TYPE_EXECUTOR) { time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); config->agent_specific.daemon.last_validated_at = validated_at; } } if (IsPolicyPrecheckNeeded(config, force_validation)) { bool policy_check_ok = GenericAgentArePromisesValid(config); if (policy_check_ok && write_validated_file) { GenericAgentTagReleaseDirectory(config, NULL, // use GetAutotagDir write_validated_file, // true GetAmPolicyHub(GetWorkDir())); // write release ID? } if (config->agent_specific.agent.bootstrap_policy_server && !policy_check_ok) { Log(LOG_LEVEL_VERBOSE, "Policy is not valid, but proceeding with bootstrap"); return true; } return policy_check_ok; } else { Log(LOG_LEVEL_VERBOSE, "Policy is already validated"); return true; } } return false; } static JsonElement *ReadJsonFile(const char *filename) { struct stat sb; if (stat(filename, &sb) == -1) { Log(LOG_LEVEL_DEBUG, "Could not open JSON file %s", filename); return NULL; } JsonElement *doc = NULL; JsonParseError err = JsonParseFile(filename, 4096, &doc); if (err != JSON_PARSE_OK || NULL == doc) { Log(LOG_LEVEL_DEBUG, "Could not parse JSON file %s", filename); } return doc; } static JsonElement *ReadPolicyValidatedFile(const char *filename) { bool missing = true; struct stat sb; if (stat(filename, &sb) != -1) { missing = false; } JsonElement *validated_doc = ReadJsonFile(filename); if (NULL == validated_doc) { Log(missing ? LOG_LEVEL_DEBUG : LOG_LEVEL_VERBOSE, "Could not parse policy_validated JSON file '%s', using dummy data", filename); validated_doc = JsonObjectCreate(2); if (missing) { JsonObjectAppendInteger(validated_doc, "timestamp", 0); } else { JsonObjectAppendInteger(validated_doc, "timestamp", sb.st_mtime); } } return validated_doc; } static JsonElement *ReadPolicyValidatedFileFromMasterfiles(const GenericAgentConfig *config, const char *maybe_dirname) { char filename[CF_MAXVARSIZE]; GetPromisesValidatedFile(filename, sizeof(filename), config, maybe_dirname); return ReadPolicyValidatedFile(filename); } /** * @brief Writes a file with a contained timestamp to mark a policy file as validated * @param filename the filename * @return True if successful. */ static bool WritePolicyValidatedFile(ARG_UNUSED const GenericAgentConfig *config, const char *filename) { if (!MakeParentDirectory(filename, true)) { Log(LOG_LEVEL_ERR, "While writing policy validated marker file '%s', could not create directory (MakeParentDirectory: %s)", filename, GetErrorStr()); return false; } int fd = creat(filename, 0600); if (fd == -1) { Log(LOG_LEVEL_ERR, "While writing policy validated marker file '%s', could not create file (creat: %s)", filename, GetErrorStr()); return false; } JsonElement *info = JsonObjectCreate(3); JsonObjectAppendInteger(info, "timestamp", time(NULL)); Writer *w = FileWriter(fdopen(fd, "w")); JsonWrite(w, info, 0); WriterClose(w); JsonDestroy(info); Log(LOG_LEVEL_VERBOSE, "Saved policy validated marker file '%s'", filename); return true; } /** * @brief Writes the policy validation file and release ID to a directory * @return True if successful. */ bool GenericAgentTagReleaseDirectory(const GenericAgentConfig *config, const char *dirname, bool write_validated, bool write_release) { char local_dirname[PATH_MAX + 1]; if (NULL == dirname) { GetAutotagDir(local_dirname, PATH_MAX, NULL); dirname = local_dirname; } char filename[CF_MAXVARSIZE]; char git_checksum[GENERIC_AGENT_CHECKSUM_SIZE]; bool have_git_checksum = GeneratePolicyReleaseIDFromGit(git_checksum, sizeof(git_checksum), dirname); Log(LOG_LEVEL_DEBUG, "Tagging directory %s for release (write_validated: %s, write_release: %s)", dirname, write_validated ? "yes" : "no", write_release ? "yes" : "no"); if (write_release) { // first, tag the release ID GetReleaseIdFile(dirname, filename, sizeof(filename)); char *id = ReadReleaseIdFromReleaseIdFileMasterfiles(dirname); if (NULL == id || (have_git_checksum && 0 != strcmp(id, git_checksum))) { if (NULL == id) { Log(LOG_LEVEL_DEBUG, "The release_id of %s was missing", dirname); } else { Log(LOG_LEVEL_DEBUG, "The release_id of %s needs to be updated", dirname); } bool wrote_release = WriteReleaseIdFile(filename, dirname); if (!wrote_release) { Log(LOG_LEVEL_VERBOSE, "The release_id file %s was NOT updated", filename); free(id); return false; } else { Log(LOG_LEVEL_DEBUG, "The release_id file %s was updated", filename); } } free(id); } // now, tag the promises_validated if (write_validated) { Log(LOG_LEVEL_DEBUG, "Tagging directory %s for validation", dirname); GetPromisesValidatedFile(filename, sizeof(filename), config, dirname); bool wrote_validated = WritePolicyValidatedFile(config, filename); if (!wrote_validated) { Log(LOG_LEVEL_VERBOSE, "The promises_validated file %s was NOT updated", filename); return false; } Log(LOG_LEVEL_DEBUG, "The promises_validated file %s was updated", filename); return true; } return true; } /** * @brief Writes a file with a contained release ID based on git SHA, * or file checksum if git SHA is not available. * @param filename the release_id file * @param dirname the directory to checksum or get the Git hash * @return True if successful */ static bool WriteReleaseIdFile(const char *filename, const char *dirname) { char release_id[GENERIC_AGENT_CHECKSUM_SIZE]; bool have_release_id = GeneratePolicyReleaseID(release_id, sizeof(release_id), dirname); if (!have_release_id) { return false; } int fd = creat(filename, 0600); if (fd == -1) { Log(LOG_LEVEL_ERR, "While writing policy release ID file '%s', could not create file (creat: %s)", filename, GetErrorStr()); return false; } JsonElement *info = JsonObjectCreate(3); JsonObjectAppendString(info, "releaseId", release_id); Writer *w = FileWriter(fdopen(fd, "w")); JsonWrite(w, info, 0); WriterClose(w); JsonDestroy(info); Log(LOG_LEVEL_VERBOSE, "Saved policy release ID file '%s'", filename); return true; } bool GenericAgentArePromisesValid(const GenericAgentConfig *config) { char cmd[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "Verifying the syntax of the inputs..."); { char cfpromises[CF_MAXVARSIZE]; snprintf(cfpromises, sizeof(cfpromises), "%s%cbin%ccf-promises%s", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, EXEC_SUFFIX); struct stat sb; if (stat(cfpromises, &sb) == -1) { Log(LOG_LEVEL_ERR, "cf-promises%s needs to be installed in %s%cbin for pre-validation of full configuration", EXEC_SUFFIX, CFWORKDIR, FILE_SEPARATOR); return false; } if (config->bundlesequence) { snprintf(cmd, sizeof(cmd), "\"%s\" \"", cfpromises); } else { snprintf(cmd, sizeof(cmd), "\"%s\" -c \"", cfpromises); } } strlcat(cmd, config->input_file, CF_BUFSIZE); strlcat(cmd, "\"", CF_BUFSIZE); if (config->bundlesequence) { strlcat(cmd, " -b \"", CF_BUFSIZE); for (const Rlist *rp = config->bundlesequence; rp; rp = rp->next) { const char *bundle_ref = RlistScalarValue(rp); strlcat(cmd, bundle_ref, CF_BUFSIZE); if (rp->next) { strlcat(cmd, ",", CF_BUFSIZE); } } strlcat(cmd, "\"", CF_BUFSIZE); } Log(LOG_LEVEL_VERBOSE, "Checking policy with command '%s'", cmd); if (!ShellCommandReturnsZero(cmd, true)) { Log(LOG_LEVEL_ERR, "Policy failed validation with command '%s'", cmd); return false; } return true; } /*****************************************************************************/ #if !defined(__MINGW32__) static void OpenLog(int facility) { openlog(VPREFIX, LOG_PID | LOG_NOWAIT | LOG_ODELAY, facility); } #endif /*****************************************************************************/ #if !defined(__MINGW32__) void CloseLog(void) { closelog(); } #endif ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, GenericAgentAddEditionClasses, EvalContext *, ctx) { EvalContextClassPutHard(ctx, "community_edition", "inventory,attribute_name=none,source=agent"); } void GenericAgentInitialize(EvalContext *ctx, GenericAgentConfig *config) { int force = false; struct stat statbuf, sb; char vbuff[CF_BUFSIZE]; char ebuff[CF_EXPANDSIZE]; #ifdef __MINGW32__ InitializeWindows(); #endif DetermineCfenginePort(); EvalContextClassPutHard(ctx, "any", "source=agent"); GenericAgentAddEditionClasses(ctx); strcpy(VPREFIX, GetConsolePrefix()); /* Define trusted directories */ { const char *workdir = GetWorkDir(); if (!workdir) { FatalError(ctx, "Error determining working directory"); } strcpy(CFWORKDIR, workdir); MapName(CFWORKDIR); } OpenLog(LOG_USER); SetSyslogFacility(LOG_USER); Log(LOG_LEVEL_VERBOSE, "Work directory is %s", CFWORKDIR); snprintf(vbuff, CF_BUFSIZE, "%s%cupdate.conf", GetInputDir(), FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%cbin%ccf-agent -D from_cfexecd", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%coutputs%cspooled_reports", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%clastseen%cintermittencies", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s%creports%cvarious", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, force); snprintf(vbuff, CF_BUFSIZE, "%s", GetInputDir()); if (stat(vbuff, &sb) == -1) { FatalError(ctx, " No access to WORKSPACE/inputs dir"); } else { chmod(vbuff, sb.st_mode | 0700); } snprintf(vbuff, CF_BUFSIZE, "%s%coutputs", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &sb) == -1) { FatalError(ctx, " No access to WORKSPACE/outputs dir"); } else { chmod(vbuff, sb.st_mode | 0700); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%ccf_procs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%ccf_rootprocs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%ccf_otherprocs", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); if (stat(ebuff, &statbuf) == -1) { CreateEmptyFile(ebuff); } snprintf(ebuff, sizeof(ebuff), "%s%cstate%cprevious_state%c", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); snprintf(ebuff, sizeof(ebuff), "%s%cstate%cdiff%c", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); snprintf(ebuff, sizeof(ebuff), "%s%cstate%cuntracked%c", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(ebuff, force); OpenNetwork(); CryptoInitialize(); CheckWorkingDirectories(ctx); /* Initialize keys and networking. cf-key, doesn't need keys. In fact it must function properly even without them, so that it generates them! */ if (config->agent_type != AGENT_TYPE_KEYGEN) { LoadSecretKeys(); char *bootstrapped_policy_server = ReadPolicyServerFile(CFWORKDIR); PolicyHubUpdateKeys(bootstrapped_policy_server); free(bootstrapped_policy_server); cfnet_init(); } size_t cwd_size = PATH_MAX; while (true) { char cwd[cwd_size]; if (!getcwd(cwd, cwd_size)) { if (errno == ERANGE) { cwd_size *= 2; continue; } Log(LOG_LEVEL_WARNING, "Could not determine current directory. (getcwd: '%s')", GetErrorStr()); break; } EvalContextSetLaunchDirectory(ctx, cwd); break; } if (!MINUSF) { GenericAgentConfigSetInputFile(config, GetInputDir(), "promises.cf"); } VIFELAPSED = 1; VEXPIREAFTER = 1; setlinebuf(stdout); if (config->agent_specific.agent.bootstrap_policy_server) { snprintf(vbuff, CF_BUFSIZE, "%s%cfailsafe.cf", GetInputDir(), FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { GenericAgentConfigSetInputFile(config, GetInputDir(), "failsafe.cf"); } else { GenericAgentConfigSetInputFile(config, GetInputDir(), vbuff); } } } void GenericAgentFinalize(EvalContext *ctx, GenericAgentConfig *config) { /* TODO, FIXME: what else from the above do we need to undo here ? */ if (config->agent_type != AGENT_TYPE_KEYGEN) { cfnet_shut(); } CryptoDeInitialize(); GenericAgentConfigDestroy(config); EvalContextDestroy(ctx); } static bool MissingInputFile(const char *input_file) { struct stat sb; if (stat(input_file, &sb) == -1) { Log(LOG_LEVEL_ERR, "There is no readable input file at '%s'. (stat: %s)", input_file, GetErrorStr()); return true; } return false; } // Git only. static bool GeneratePolicyReleaseIDFromGit(char *release_id_out, ARG_UNUSED size_t out_size, const char *policy_dir) { char git_filename[PATH_MAX + 1]; snprintf(git_filename, PATH_MAX, "%s/.git/HEAD", policy_dir); MapName(git_filename); FILE *git_file = fopen(git_filename, "r"); if (git_file) { char git_head[128]; fscanf(git_file, "ref: %127s", git_head); fclose(git_file); snprintf(git_filename, PATH_MAX, "%s/.git/%s", policy_dir, git_head); git_file = fopen(git_filename, "r"); if (git_file) { assert(out_size > 40); fscanf(git_file, "%40s", release_id_out); fclose(git_file); return true; } else { Log(LOG_LEVEL_DEBUG, "While generating policy release ID, found git head ref '%s', but unable to open (errno: %s)", policy_dir, GetErrorStr()); } } else { Log(LOG_LEVEL_DEBUG, "While generating policy release ID, directory is '%s' not a git repository", policy_dir); } return false; } static bool GeneratePolicyReleaseIDFromTree(char *release_id_out, size_t out_size, const char *policy_dir) { if (access(policy_dir, R_OK) != 0) { Log(LOG_LEVEL_ERR, "Cannot access policy directory '%s' to generate release ID", policy_dir); return false; } // fallback, produce some pseudo sha1 hash EVP_MD_CTX crypto_ctx; EVP_DigestInit(&crypto_ctx, EVP_get_digestbyname(HashNameFromId(GENERIC_AGENT_CHECKSUM_METHOD))); bool success = HashDirectoryTree(policy_dir, (const char *[]) { ".cf", ".dat", ".txt", ".conf", NULL}, &crypto_ctx); int md_len; unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; EVP_DigestFinal(&crypto_ctx, digest, &md_len); HashPrintSafe(release_id_out, out_size, digest, GENERIC_AGENT_CHECKSUM_METHOD, false); return success; } static bool GeneratePolicyReleaseID(char *release_id_out, size_t out_size, const char *policy_dir) { if (GeneratePolicyReleaseIDFromGit(release_id_out, out_size, policy_dir)) { return true; } return GeneratePolicyReleaseIDFromTree(release_id_out, out_size, policy_dir); } /** * @brief Gets the promises_validated file name depending on context and options */ static void GetPromisesValidatedFile(char *filename, size_t max_size, const GenericAgentConfig *config, const char *maybe_dirname) { char dirname[PATH_MAX + 1]; GetAutotagDir(dirname, max_size, maybe_dirname); if (NULL == maybe_dirname && MINUSF) { snprintf(filename, max_size, "%s/validated_%s", dirname, CanonifyName(config->original_input_file)); } else { snprintf(filename, max_size, "%s/cf_promises_validated", dirname); } MapName(filename); } /** * @brief Gets the promises_validated file name depending on context and options */ static void GetAutotagDir(char *dirname, size_t max_size, const char *maybe_dirname) { if (NULL != maybe_dirname) { strlcpy(dirname, maybe_dirname, max_size); } else if (MINUSF) { snprintf(dirname, max_size, "%s/state", CFWORKDIR); } else { strlcpy(dirname, GetMasterDir(), max_size); } MapName(dirname); } /** * @brief Gets the release_id file name in the given base_path. */ void GetReleaseIdFile(const char *base_path, char *filename, size_t max_size) { snprintf(filename, max_size, "%s/cf_promises_release_id", base_path); MapName(filename); } static JsonElement *ReadReleaseIdFileFromMasterfiles(const char *maybe_dirname) { char filename[CF_MAXVARSIZE]; GetReleaseIdFile(NULL == maybe_dirname ? GetMasterDir() : maybe_dirname, filename, sizeof(filename)); JsonElement *doc = ReadJsonFile(filename); if (NULL == doc) { Log(LOG_LEVEL_VERBOSE, "Could not parse release_id JSON file %s", filename); } return doc; } static char* ReadReleaseIdFromReleaseIdFileMasterfiles(const char *maybe_dirname) { JsonElement *doc = ReadReleaseIdFileFromMasterfiles(maybe_dirname); char *id = NULL; if (doc) { JsonElement *jid = JsonObjectGet(doc, "releaseId"); if (jid) { id = xstrdup(JsonPrimitiveGetAsString(jid)); } JsonDestroy(doc); } return id; } // TODO: refactor Read*FromPolicyValidatedMasterfiles time_t ReadTimestampFromPolicyValidatedFile(const GenericAgentConfig *config, const char *maybe_dirname) { time_t validated_at = 0; { JsonElement *validated_doc = ReadPolicyValidatedFileFromMasterfiles(config, maybe_dirname); if (validated_doc) { JsonElement *timestamp = JsonObjectGet(validated_doc, "timestamp"); if (timestamp) { validated_at = JsonPrimitiveGetAsInteger(timestamp); } JsonDestroy(validated_doc); } } return validated_at; } // TODO: refactor Read*FromPolicyValidatedMasterfiles char* ReadChecksumFromPolicyValidatedMasterfiles(const GenericAgentConfig *config, const char *maybe_dirname) { char *checksum_str = NULL; { JsonElement *validated_doc = ReadPolicyValidatedFileFromMasterfiles(config, maybe_dirname); if (validated_doc) { JsonElement *checksum = JsonObjectGet(validated_doc, "checksum"); if (checksum ) { checksum_str = xstrdup(JsonPrimitiveGetAsString(checksum)); } JsonDestroy(validated_doc); } } return checksum_str; } /** * @NOTE Updates the config->agent_specific.daemon.last_validated_at timestamp * used by serverd, execd etc daemons when checking for new policies. */ bool GenericAgentIsPolicyReloadNeeded(const GenericAgentConfig *config) { time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); time_t now = time(NULL); if (validated_at > now) { Log(LOG_LEVEL_INFO, "Clock seems to have jumped back in time, mtime of %jd is newer than current time %jd, touching it", (intmax_t) validated_at, (intmax_t) now); GenericAgentTagReleaseDirectory(config, NULL, // use GetAutotagDir true, // write validated false); // write release ID return true; } { struct stat sb; if (stat(config->input_file, &sb) == -1) { Log(LOG_LEVEL_VERBOSE, "There is no readable input file at '%s'. (stat: %s)", config->input_file, GetErrorStr()); return true; } else if (sb.st_mtime > validated_at) { Log(LOG_LEVEL_VERBOSE, "Input file '%s' has changed since the last policy read attempt", config->input_file); return true; } } // Check the directories first for speed and because non-input/data files should trigger an update { if (IsNewerFileTree( (char *)GetInputDir(), validated_at)) { Log(LOG_LEVEL_VERBOSE, "Quick search detected file changes"); return true; } } { char filename[MAX_FILENAME]; snprintf(filename, MAX_FILENAME, "%s/policy_server.dat", CFWORKDIR); MapName(filename); struct stat sb; if ((stat(filename, &sb) != -1) && (sb.st_mtime > validated_at)) { return true; } } return false; } /*******************************************************************/ Seq *ControlBodyConstraints(const Policy *policy, AgentType agent) { for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Body *body = SeqAt(policy->bodies, i); if (strcmp(body->type, CF_AGENTTYPES[agent]) == 0) { if (strcmp(body->name, "control") == 0) { return body->conlist; } } } return NULL; } /*******************************************************************/ static int ParseFacility(const char *name) { if (strcmp(name, "LOG_USER") == 0) { return LOG_USER; } if (strcmp(name, "LOG_DAEMON") == 0) { return LOG_DAEMON; } if (strcmp(name, "LOG_LOCAL0") == 0) { return LOG_LOCAL0; } if (strcmp(name, "LOG_LOCAL1") == 0) { return LOG_LOCAL1; } if (strcmp(name, "LOG_LOCAL2") == 0) { return LOG_LOCAL2; } if (strcmp(name, "LOG_LOCAL3") == 0) { return LOG_LOCAL3; } if (strcmp(name, "LOG_LOCAL4") == 0) { return LOG_LOCAL4; } if (strcmp(name, "LOG_LOCAL5") == 0) { return LOG_LOCAL5; } if (strcmp(name, "LOG_LOCAL6") == 0) { return LOG_LOCAL6; } if (strcmp(name, "LOG_LOCAL7") == 0) { return LOG_LOCAL7; } return -1; } void SetFacility(const char *retval) { Log(LOG_LEVEL_VERBOSE, "SET Syslog FACILITY = %s", retval); CloseLog(); OpenLog(ParseFacility(retval)); SetSyslogFacility(ParseFacility(retval)); } static void CheckWorkingDirectories(EvalContext *ctx) /* NOTE: We do not care about permissions (ACLs) in windows */ { struct stat statbuf; char vbuff[CF_BUFSIZE]; if (uname(&VSYSNAME) == -1) { Log(LOG_LEVEL_ERR, "Couldn't get kernel name info. (uname: %s)", GetErrorStr()); memset(&VSYSNAME, 0, sizeof(VSYSNAME)); } snprintf(vbuff, CF_BUFSIZE, "%s%c.", CFWORKDIR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); Log(LOG_LEVEL_VERBOSE, "Making sure that locks are private..."); if (chown(CFWORKDIR, getuid(), getgid()) == -1) { Log(LOG_LEVEL_ERR, "Unable to set owner on '%s'' to '%ju.%ju'. (chown: %s)", CFWORKDIR, (uintmax_t)getuid(), (uintmax_t)getgid(), GetErrorStr()); } if (stat(CFWORKDIR, &statbuf) != -1) { /* change permissions go-w */ chmod(CFWORKDIR, (mode_t) (statbuf.st_mode & ~022)); } snprintf(vbuff, CF_BUFSIZE, "%s%cstate%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); Log(LOG_LEVEL_VERBOSE, "Checking integrity of the state database"); snprintf(vbuff, CF_BUFSIZE, "%s%cstate", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { snprintf(vbuff, CF_BUFSIZE, "%s%cstate%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); if (chown(vbuff, getuid(), getgid()) == -1) { Log(LOG_LEVEL_ERR, "Unable to set owner on '%s' to '%jd.%jd'. (chown: %s)", vbuff, (uintmax_t)getuid(), (uintmax_t)getgid(), GetErrorStr()); } chmod(vbuff, (mode_t) 0755); } else { #ifndef __MINGW32__ if (statbuf.st_mode & 022) { Log(LOG_LEVEL_ERR, "UNTRUSTED: State directory %s (mode %jo) was not private!", CFWORKDIR, (uintmax_t)(statbuf.st_mode & 0777)); } #endif /* !__MINGW32__ */ } Log(LOG_LEVEL_VERBOSE, "Checking integrity of the module directory"); snprintf(vbuff, CF_BUFSIZE, "%s%cmodules", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { snprintf(vbuff, CF_BUFSIZE, "%s%cmodules%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); if (chown(vbuff, getuid(), getgid()) == -1) { Log(LOG_LEVEL_ERR, "Unable to set owner on '%s' to '%ju.%ju'. (chown: %s)", vbuff, (uintmax_t)getuid(), (uintmax_t)getgid(), GetErrorStr()); } chmod(vbuff, (mode_t) 0700); } else { #ifndef __MINGW32__ if (statbuf.st_mode & 022) { Log(LOG_LEVEL_ERR, "UNTRUSTED: Module directory %s (mode %jo) was not private!", vbuff, (uintmax_t)(statbuf.st_mode & 0777)); } #endif /* !__MINGW32__ */ } Log(LOG_LEVEL_VERBOSE, "Checking integrity of the PKI directory"); snprintf(vbuff, CF_BUFSIZE, "%s%cppkeys", CFWORKDIR, FILE_SEPARATOR); if (stat(vbuff, &statbuf) == -1) { snprintf(vbuff, CF_BUFSIZE, "%s%cppkeys%c.", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); MakeParentDirectory(vbuff, false); chmod(vbuff, (mode_t) 0700); /* Keys must be immutable to others */ } else { #ifndef __MINGW32__ if (statbuf.st_mode & 077) { FatalError(ctx, "UNTRUSTED: Private key directory %s%cppkeys (mode %jo) was not private!\n", CFWORKDIR, FILE_SEPARATOR, (uintmax_t)(statbuf.st_mode & 0777)); } #endif /* !__MINGW32__ */ } } const char *GenericAgentResolveInputPath(const GenericAgentConfig *config, const char *input_file) { static char input_path[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */ switch (FilePathGetType(input_file)) { case FILE_PATH_TYPE_ABSOLUTE: strlcpy(input_path, input_file, CF_BUFSIZE); break; case FILE_PATH_TYPE_NON_ANCHORED: case FILE_PATH_TYPE_RELATIVE: snprintf(input_path, CF_BUFSIZE, "%s%c%s", config->input_dir, FILE_SEPARATOR, input_file); break; } return MapName(input_path); } void GenericAgentWriteHelp(Writer *w, const char *component, const struct option options[], const char *const hints[], bool accepts_file_argument) { WriterWriteF(w, "Usage: %s [OPTION]...%s\n", component, accepts_file_argument ? " [FILE]" : ""); WriterWriteF(w, "\nOptions:\n"); for (int i = 0; options[i].name != NULL; i++) { if (options[i].has_arg) { WriterWriteF(w, " --%-12s, -%c value - %s\n", options[i].name, (char) options[i].val, hints[i]); } else { WriterWriteF(w, " --%-12s, -%-7c - %s\n", options[i].name, (char) options[i].val, hints[i]); } } WriterWriteF(w, "\nWebsite: http://www.cfengine.com\n"); WriterWriteF(w, "This software is Copyright (C) 2008,2010-present CFEngine AS.\n"); } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, GenericAgentWriteVersion, Writer *, w) { WriterWriteF(w, "%s\n", NameVersion()); } /*******************************************************************/ const char *Version(void) { return VERSION; } /*******************************************************************/ const char *NameVersion(void) { return "CFEngine Core " VERSION; } /********************************************************************/ static void CleanPidFile(void) { if (unlink(PIDFILE) != 0) { if (errno != ENOENT) { Log(LOG_LEVEL_ERR, "Unable to remove pid file '%s'. (unlink: %s)", PIDFILE, GetErrorStr()); } } } /********************************************************************/ static void RegisterPidCleanup(void) { RegisterAtExitFunction(&CleanPidFile); } /********************************************************************/ void WritePID(char *filename) { FILE *fp; pthread_once(&pid_cleanup_once, RegisterPidCleanup); snprintf(PIDFILE, CF_BUFSIZE - 1, "%s%c%s", GetPidDir(), FILE_SEPARATOR, filename); if ((fp = fopen(PIDFILE, "w")) == NULL) { Log(LOG_LEVEL_INFO, "Could not write to PID file '%s'. (fopen: %s)", filename, GetErrorStr()); return; } fprintf(fp, "%ju\n", (uintmax_t)getpid()); fclose(fp); } bool GenericAgentConfigParseArguments(GenericAgentConfig *config, int argc, char **argv) { if (argc == 0) { return true; } if (argc > 1) { return false; } GenericAgentConfigSetInputFile(config, NULL, argv[0]); MINUSF = true; return true; } bool GenericAgentConfigParseWarningOptions(GenericAgentConfig *config, const char *warning_options) { if (strlen(warning_options) == 0) { return false; } if (strcmp("error", warning_options) == 0) { config->agent_specific.common.parser_warnings_error |= PARSER_WARNING_ALL; return true; } const char *options_start = warning_options; bool warnings_as_errors = false; if (StringStartsWith(warning_options, "error=")) { options_start = warning_options + strlen("error="); warnings_as_errors = true; } StringSet *warnings_set = StringSetFromString(options_start, ','); StringSetIterator it = StringSetIteratorInit(warnings_set); const char *warning_str = NULL; while ((warning_str = StringSetIteratorNext(&it))) { int warning = ParserWarningFromString(warning_str); if (warning == -1) { Log(LOG_LEVEL_ERR, "Unrecognized warning '%s'", warning_str); StringSetDestroy(warnings_set); return false; } if (warnings_as_errors) { config->agent_specific.common.parser_warnings_error |= warning; } else { config->agent_specific.common.parser_warnings |= warning; } } StringSetDestroy(warnings_set); return true; } bool GenericAgentConfigParseColor(GenericAgentConfig *config, const char *mode) { if (!mode || strcmp("auto", mode) == 0) { config->color = config->tty_interactive; return true; } else if (strcmp("always", mode) == 0) { config->color = true; return true; } else if (strcmp("never", mode) == 0) { config->color = false; return true; } else { Log(LOG_LEVEL_ERR, "Unrecognized color mode '%s'", mode); return false; } } GenericAgentConfig *GenericAgentConfigNewDefault(AgentType agent_type) { GenericAgentConfig *config = xmalloc(sizeof(GenericAgentConfig)); config->agent_type = agent_type; // TODO: system state, perhaps pull out as param config->tty_interactive = isatty(0) && isatty(1); const char *color_env = getenv("CFENGINE_COLOR"); config->color = (color_env && 0 == strcmp(color_env, "1")); config->bundlesequence = NULL; config->original_input_file = NULL; config->input_file = NULL; config->input_dir = NULL; config->check_not_writable_by_others = agent_type != AGENT_TYPE_COMMON && !config->tty_interactive; config->check_runnable = agent_type != AGENT_TYPE_COMMON; config->ignore_missing_bundles = false; config->ignore_missing_inputs = false; config->heap_soft = NULL; config->heap_negated = NULL; config->ignore_locks = false; config->agent_specific.agent.bootstrap_policy_server = NULL; switch (agent_type) { case AGENT_TYPE_COMMON: config->agent_specific.common.eval_functions = true; config->agent_specific.common.show_classes = false; config->agent_specific.common.show_variables = false; config->agent_specific.common.policy_output_format = GENERIC_AGENT_CONFIG_COMMON_POLICY_OUTPUT_FORMAT_NONE; /* Bitfields of warnings to be recorded, or treated as errors. */ config->agent_specific.common.parser_warnings = PARSER_WARNING_ALL; config->agent_specific.common.parser_warnings_error = 0; break; default: break; } return config; } void GenericAgentConfigDestroy(GenericAgentConfig *config) { if (config) { RlistDestroy(config->bundlesequence); StringSetDestroy(config->heap_soft); StringSetDestroy(config->heap_negated); free(config->original_input_file); free(config->input_file); free(config->input_dir); free(config); } } void GenericAgentConfigApply(EvalContext *ctx, const GenericAgentConfig *config) { if (config->heap_soft) { StringSetIterator it = StringSetIteratorInit(config->heap_soft); const char *context = NULL; while ((context = StringSetIteratorNext(&it))) { Class *cls = EvalContextClassGet(ctx, NULL, context); if (cls && !cls->is_soft) { FatalError(ctx, "You cannot use -D to define a reserved class"); } EvalContextClassPutSoft(ctx, context, CONTEXT_SCOPE_NAMESPACE, "source=environment"); } } switch (LogGetGlobalLevel()) { case LOG_LEVEL_DEBUG: EvalContextClassPutHard(ctx, "debug_mode", "cfe_internal,source=agent"); EvalContextClassPutHard(ctx, "opt_debug", "cfe_internal,source=agent"); // intentional fall case LOG_LEVEL_VERBOSE: EvalContextClassPutHard(ctx, "verbose_mode", "cfe_internal,source=agent"); // intentional fall case LOG_LEVEL_INFO: EvalContextClassPutHard(ctx, "inform_mode", "cfe_internal,source=agent"); break; default: break; } if (config->agent_specific.agent.bootstrap_policy_server) { EvalContextClassPutHard(ctx, "bootstrap_mode", "source=environment"); } if (config->color) { LoggingSetColor(config->color); } switch (config->agent_type) { case AGENT_TYPE_COMMON: EvalContextSetEvalOption(ctx, EVAL_OPTION_FULL, false); if (config->agent_specific.common.eval_functions) EvalContextSetEvalOption(ctx, EVAL_OPTION_EVAL_FUNCTIONS, true); break; default: break; } EvalContextSetIgnoreLocks(ctx, config->ignore_locks); if (DONTDO) { EvalContextClassPutHard(ctx, "opt_dry_run", "cfe_internal,source=environment"); } } void GenericAgentConfigSetInputFile(GenericAgentConfig *config, const char *inputdir, const char *input_file) { free(config->original_input_file); free(config->input_file); free(config->input_dir); config->original_input_file = xstrdup(input_file); if (inputdir && FilePathGetType(input_file) == FILE_PATH_TYPE_NON_ANCHORED) { config->input_file = StringFormat("%s%c%s", inputdir, FILE_SEPARATOR, input_file); } else { config->input_file = xstrdup(input_file); } config->input_dir = xstrdup(config->input_file); if (!ChopLastNode(config->input_dir)) { free(config->input_dir); config->input_dir = xstrdup("."); } } void GenericAgentConfigSetBundleSequence(GenericAgentConfig *config, const Rlist *bundlesequence) { RlistDestroy(config->bundlesequence); config->bundlesequence = RlistCopy(bundlesequence); } cfengine-3.6.2/libpromises/chflags.h0000664000175100017510000000224012243421446017126 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CHFLAGS_H #define CFENGINE_CHFLAGS_H /* BSD flags */ #include #include int ParseFlagString(Rlist *flags, u_long *plusmask, u_long *minusmask); #endif cfengine-3.6.2/libpromises/math.pc0000664000175100017510000010703112243421446016627 0ustar00a10038a1003800000000000000/* A recursive-descent parser generated by peg 0.1.12 */ #include #include #include #define YYRULECOUNT 19 #ifndef YY_MALLOC #define YY_MALLOC(C, N) malloc(N) #endif #ifndef YY_REALLOC #define YY_REALLOC(C, P, N) realloc(P, N) #endif #ifndef YY_FREE #define YY_FREE free #endif #ifndef YY_LOCAL #define YY_LOCAL(T) static T #endif #ifndef YY_ACTION #define YY_ACTION(T) static T #endif #ifndef YY_RULE #define YY_RULE(T) static T #endif #ifndef YY_PARSE #define YY_PARSE(T) T #endif #ifndef YYPARSE #define YYPARSE yyparse #endif #ifndef YYPARSEFROM #define YYPARSEFROM yyparsefrom #endif #ifndef YYRELEASE #define YYRELEASE yyrelease #endif #ifndef YY_BEGIN #define YY_BEGIN ( yy->__begin= yy->__pos, 1) #endif #ifndef YY_END #define YY_END ( yy->__end= yy->__pos, 1) #endif #ifdef YY_DEBUG # define yyprintf(args) fprintf args #else # define yyprintf(args) #endif #ifndef YYSTYPE #define YYSTYPE int #endif #ifndef YY_STACK_SIZE #define YY_STACK_SIZE 128 #endif #ifndef YY_BUFFER_SIZE #define YY_BUFFER_SIZE 1024 #endif #ifndef YY_PART typedef struct _yycontext yycontext; typedef void (*yyaction)(yycontext *yy, char *yytext, int yyleng); typedef struct _yythunk { int begin, end; yyaction action; struct _yythunk *next; } yythunk; struct _yycontext { char *__buf; int __buflen; int __pos; int __limit; char *__text; int __textlen; int __begin; int __end; int __textmax; yythunk *__thunks; int __thunkslen; int __thunkpos; YYSTYPE __; YYSTYPE *__val; YYSTYPE *__vals; int __valslen; #ifdef YY_CTX_MEMBERS YY_CTX_MEMBERS #endif }; #ifdef YY_CTX_LOCAL #define YY_CTX_PARAM_ yycontext *yyctx, #define YY_CTX_PARAM yycontext *yyctx #define YY_CTX_ARG_ yyctx, #define YY_CTX_ARG yyctx #ifndef YY_INPUT #define YY_INPUT(yy, buf, result, max_size) \ { \ int yyc= getchar(); \ result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ yyprintf((stderr, "<%c>", yyc)); \ } #endif #else #define YY_CTX_PARAM_ #define YY_CTX_PARAM #define YY_CTX_ARG_ #define YY_CTX_ARG yycontext _yyctx= { 0, 0 }; yycontext *yyctx= &_yyctx; #ifndef YY_INPUT #define YY_INPUT(buf, result, max_size) \ { \ int yyc= getchar(); \ result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \ yyprintf((stderr, "<%c>", yyc)); \ } #endif #endif YY_LOCAL(int) yyrefill(yycontext *yy) { int yyn; while (yy->__buflen - yy->__pos < 512) { yy->__buflen *= 2; yy->__buf= (char *)YY_REALLOC(yy, yy->__buf, yy->__buflen); } #ifdef YY_CTX_LOCAL YY_INPUT(yy, (yy->__buf + yy->__pos), yyn, (yy->__buflen - yy->__pos)); #else YY_INPUT((yy->__buf + yy->__pos), yyn, (yy->__buflen - yy->__pos)); #endif if (!yyn) return 0; yy->__limit += yyn; return 1; } YY_LOCAL(int) yymatchDot(yycontext *yy) { if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0; ++yy->__pos; return 1; } YY_LOCAL(int) yymatchChar(yycontext *yy, int c) { if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0; if ((unsigned char)yy->__buf[yy->__pos] == c) { ++yy->__pos; yyprintf((stderr, " ok yymatchChar(yy, %c) @ %s\n", c, yy->__buf+yy->__pos)); return 1; } yyprintf((stderr, " fail yymatchChar(yy, %c) @ %s\n", c, yy->__buf+yy->__pos)); return 0; } YY_LOCAL(int) yymatchString(yycontext *yy, const char *s) { int yysav= yy->__pos; while (*s) { if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0; if (yy->__buf[yy->__pos] != *s) { yy->__pos= yysav; return 0; } ++s; ++yy->__pos; } return 1; } YY_LOCAL(int) yymatchClass(yycontext *yy, unsigned char *bits) { int c; if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0; c= (unsigned char)yy->__buf[yy->__pos]; if (bits[c >> 3] & (1 << (c & 7))) { ++yy->__pos; yyprintf((stderr, " ok yymatchClass @ %s\n", yy->__buf+yy->__pos)); return 1; } yyprintf((stderr, " fail yymatchClass @ %s\n", yy->__buf+yy->__pos)); return 0; } YY_LOCAL(void) yyDo(yycontext *yy, yyaction action, int begin, int end) { while (yy->__thunkpos >= yy->__thunkslen) { yy->__thunkslen *= 2; yy->__thunks= (yythunk *)YY_REALLOC(yy, yy->__thunks, sizeof(yythunk) * yy->__thunkslen); } yy->__thunks[yy->__thunkpos].begin= begin; yy->__thunks[yy->__thunkpos].end= end; yy->__thunks[yy->__thunkpos].action= action; ++yy->__thunkpos; } YY_LOCAL(int) yyText(yycontext *yy, int begin, int end) { int yyleng= end - begin; if (yyleng <= 0) yyleng= 0; else { while (yy->__textlen < (yyleng + 1)) { yy->__textlen *= 2; yy->__text= (char *)YY_REALLOC(yy, yy->__text, yy->__textlen); } memcpy(yy->__text, yy->__buf + begin, yyleng); } yy->__text[yyleng]= '\0'; return yyleng; } YY_LOCAL(void) yyDone(yycontext *yy) { int pos; for (pos= 0; pos < yy->__thunkpos; ++pos) { yythunk *thunk= &yy->__thunks[pos]; int yyleng= thunk->end ? yyText(yy, thunk->begin, thunk->end) : thunk->begin; yyprintf((stderr, "DO [%d] %p %s\n", pos, thunk->action, yy->__text)); thunk->action(yy, yy->__text, yyleng); } yy->__thunkpos= 0; } YY_LOCAL(void) yyCommit(yycontext *yy) { if ((yy->__limit -= yy->__pos)) { memmove(yy->__buf, yy->__buf + yy->__pos, yy->__limit); } yy->__begin -= yy->__pos; yy->__end -= yy->__pos; yy->__pos= yy->__thunkpos= 0; } YY_LOCAL(int) yyAccept(yycontext *yy, int tp0) { if (tp0) { fprintf(stderr, "accept denied at %d\n", tp0); return 0; } else { yyDone(yy); yyCommit(yy); } return 1; } YY_LOCAL(void) yyPush(yycontext *yy, char *text, int count) { yy->__val += count; while (yy->__valslen <= yy->__val - yy->__vals) { long offset= yy->__val - yy->__vals; yy->__valslen *= 2; yy->__vals= (YYSTYPE *)YY_REALLOC(yy, yy->__vals, sizeof(YYSTYPE) * yy->__valslen); yy->__val= yy->__vals + offset; } } YY_LOCAL(void) yyPop(yycontext *yy, char *text, int count) { yy->__val -= count; } YY_LOCAL(void) yySet(yycontext *yy, char *text, int count) { yy->__val[count]= yy->__; } #endif /* YY_PART */ #define YYACCEPT yyAccept(yy, yythunkpos0) YY_RULE(int) yy_Fname(yycontext *yy); /* 19 */ YY_RULE(int) yy_CLOSE(yycontext *yy); /* 18 */ YY_RULE(int) yy_OPEN(yycontext *yy); /* 17 */ YY_RULE(int) yy_Funcall(yycontext *yy); /* 16 */ YY_RULE(int) yy_Constant(yycontext *yy); /* 15 */ YY_RULE(int) yy_SI_Unit(yycontext *yy); /* 14 */ YY_RULE(int) yy_F_NUMBER(yycontext *yy); /* 13 */ YY_RULE(int) yy_MOD(yycontext *yy); /* 12 */ YY_RULE(int) yy_DIVIDE(yycontext *yy); /* 11 */ YY_RULE(int) yy_TIMES(yycontext *yy); /* 10 */ YY_RULE(int) yy_POW(yycontext *yy); /* 9 */ YY_RULE(int) yy_Value(yycontext *yy); /* 8 */ YY_RULE(int) yy_CLOSE_ENOUGH(yycontext *yy); /* 7 */ YY_RULE(int) yy_MINUS(yycontext *yy); /* 6 */ YY_RULE(int) yy_PLUS(yycontext *yy); /* 5 */ YY_RULE(int) yy_Product(yycontext *yy); /* 4 */ YY_RULE(int) yy_Sum(yycontext *yy); /* 3 */ YY_RULE(int) yy_SPACE(yycontext *yy); /* 2 */ YY_RULE(int) yy_Expr(yycontext *yy); /* 1 */ YY_ACTION(void) yy_5_SI_Unit(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_5_SI_Unit\n")); { math_eval_push(1000000000000000, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_4_SI_Unit(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_4_SI_Unit\n")); { math_eval_push(1000000000000, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_3_SI_Unit(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_3_SI_Unit\n")); { math_eval_push(1000000000, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_2_SI_Unit(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_2_SI_Unit\n")); { math_eval_push(1000000, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_SI_Unit(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_SI_Unit\n")); { math_eval_push(1000, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_13_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_13_Constant\n")); { math_eval_push(0.70710678118654752440, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_12_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_12_Constant\n")); { math_eval_push(1.41421356237309504880, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_11_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_11_Constant\n")); { math_eval_push(1.12837916709551257390, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_10_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_10_Constant\n")); { math_eval_push(0.63661977236758134308, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_9_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_9_Constant\n")); { math_eval_push(0.31830988618379067154, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_8_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_8_Constant\n")); { math_eval_push(0.78539816339744830962, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_7_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_7_Constant\n")); { math_eval_push(1.57079632679489661923, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_6_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_6_Constant\n")); { math_eval_push(3.14159265358979323846, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_5_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_5_Constant\n")); { math_eval_push(2.30258509299404568402, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_4_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_4_Constant\n")); { math_eval_push(0.69314718055994530942, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_3_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_3_Constant\n")); { math_eval_push(0.43429448190325182765, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_2_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_2_Constant\n")); { math_eval_push(1.4426950408889634074, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Constant(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Constant\n")); { math_eval_push(2.7182818284590452354, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Fname(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Fname\n")); { strcpy(yy->fname, yytext); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Funcall(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Funcall\n")); { math_eval_push(EvaluateMathFunction(yy->fname, math_eval_pop(yy->stack, &(yy->stackp))), yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_2_Value(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_2_Value\n")); { double scanned = 0; sscanf(yytext, "%lf", &scanned); math_eval_push(scanned, yy->stack, &(yy->stackp)); /*Log(LOG_LEVEL_ERR, "YY: read FP %lf", scanned);*/ ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Value(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Value\n")); { double scanned = 0; sscanf(yytext, "%lf", &scanned); math_eval_push(math_eval_pop(yy->stack, &(yy->stackp)) * scanned, yy->stack, &(yy->stackp)); Log(LOG_LEVEL_ERR, "YY: read FP %lf", scanned); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_4_Product(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_4_Product\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push((long)l % (long)r, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_3_Product(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_3_Product\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l / r, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_2_Product(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_2_Product\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l * r, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Product(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Product\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(pow(l, r), yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_3_Sum(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_3_Sum\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(fabs(l - r) < 0.00000000000000001, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_2_Sum(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_2_Sum\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l - r, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Sum(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Sum\n")); { double r= math_eval_pop(yy->stack, &(yy->stackp)), l= math_eval_pop(yy->stack, &(yy->stackp)); math_eval_push(l + r, yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_2_Expr(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_2_Expr\n")); { strcpy(yy->failure, "expression could not be parsed"); ; } #undef yythunkpos #undef yypos #undef yy } YY_ACTION(void) yy_1_Expr(yycontext *yy, char *yytext, int yyleng) { #define __ yy->__ #define yypos yy->__pos #define yythunkpos yy->__thunkpos yyprintf((stderr, "do yy_1_Expr\n")); { yy->result = math_eval_pop(yy->stack, &(yy->stackp)); ; } #undef yythunkpos #undef yypos #undef yy } YY_RULE(int) yy_Fname(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Fname")); yyText(yy, yy->__begin, yy->__end); if (!(YY_BEGIN)) goto l1; { int yypos2= yy->__pos, yythunkpos2= yy->__thunkpos; if (!yymatchString(yy, "ceil")) goto l3; goto l2; l3:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "floor")) goto l4; goto l2; l4:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "log10")) goto l5; goto l2; l5:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "log2")) goto l6; goto l2; l6:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "log")) goto l7; goto l2; l7:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "sqrt")) goto l8; goto l2; l8:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "sin")) goto l9; goto l2; l9:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "cos")) goto l10; goto l2; l10:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "tan")) goto l11; goto l2; l11:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "asin")) goto l12; goto l2; l12:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "acos")) goto l13; goto l2; l13:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "atan")) goto l14; goto l2; l14:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "abs")) goto l15; goto l2; l15:; yy->__pos= yypos2; yy->__thunkpos= yythunkpos2; if (!yymatchString(yy, "step")) goto l1; } l2:; yyText(yy, yy->__begin, yy->__end); if (!(YY_END)) goto l1; yyDo(yy, yy_1_Fname, yy->__begin, yy->__end); yyprintf((stderr, " ok %s @ %s\n", "Fname", yy->__buf+yy->__pos)); return 1; l1:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Fname", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_CLOSE(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "CLOSE")); if (!yymatchChar(yy, ')')) goto l16; if (!yy_SPACE(yy)) goto l16; yyprintf((stderr, " ok %s @ %s\n", "CLOSE", yy->__buf+yy->__pos)); return 1; l16:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "CLOSE", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_OPEN(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "OPEN")); if (!yymatchChar(yy, '(')) goto l17; if (!yy_SPACE(yy)) goto l17; yyprintf((stderr, " ok %s @ %s\n", "OPEN", yy->__buf+yy->__pos)); return 1; l17:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "OPEN", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_Funcall(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Funcall")); if (!yy_Fname(yy)) goto l18; if (!yy_OPEN(yy)) goto l18; if (!yy_Value(yy)) goto l18; if (!yy_CLOSE(yy)) goto l18; yyDo(yy, yy_1_Funcall, yy->__begin, yy->__end); yyprintf((stderr, " ok %s @ %s\n", "Funcall", yy->__buf+yy->__pos)); return 1; l18:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Funcall", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_Constant(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Constant")); { int yypos20= yy->__pos, yythunkpos20= yy->__thunkpos; if (!yymatchChar(yy, 'e')) goto l21; yyDo(yy, yy_1_Constant, yy->__begin, yy->__end); goto l20; l21:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "log2e")) goto l22; yyDo(yy, yy_2_Constant, yy->__begin, yy->__end); goto l20; l22:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "log10e")) goto l23; yyDo(yy, yy_3_Constant, yy->__begin, yy->__end); goto l20; l23:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "ln2")) goto l24; yyDo(yy, yy_4_Constant, yy->__begin, yy->__end); goto l20; l24:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "ln10")) goto l25; yyDo(yy, yy_5_Constant, yy->__begin, yy->__end); goto l20; l25:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "pi")) goto l26; yyDo(yy, yy_6_Constant, yy->__begin, yy->__end); goto l20; l26:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "pi_2")) goto l27; yyDo(yy, yy_7_Constant, yy->__begin, yy->__end); goto l20; l27:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "pi_4")) goto l28; yyDo(yy, yy_8_Constant, yy->__begin, yy->__end); goto l20; l28:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "1_pi")) goto l29; yyDo(yy, yy_9_Constant, yy->__begin, yy->__end); goto l20; l29:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "2_pi")) goto l30; yyDo(yy, yy_10_Constant, yy->__begin, yy->__end); goto l20; l30:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "2_sqrtpi")) goto l31; yyDo(yy, yy_11_Constant, yy->__begin, yy->__end); goto l20; l31:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "sqrt2")) goto l32; yyDo(yy, yy_12_Constant, yy->__begin, yy->__end); goto l20; l32:; yy->__pos= yypos20; yy->__thunkpos= yythunkpos20; if (!yymatchString(yy, "sqrt1_2")) goto l19; yyDo(yy, yy_13_Constant, yy->__begin, yy->__end); } l20:; yyprintf((stderr, " ok %s @ %s\n", "Constant", yy->__buf+yy->__pos)); return 1; l19:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Constant", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_SI_Unit(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "SI_Unit")); { int yypos34= yy->__pos, yythunkpos34= yy->__thunkpos; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\000\000\000\010\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l35; if (!yy_SPACE(yy)) goto l35; yyDo(yy, yy_1_SI_Unit, yy->__begin, yy->__end); goto l34; l35:; yy->__pos= yypos34; yy->__thunkpos= yythunkpos34; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\000\000\000\040\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l36; if (!yy_SPACE(yy)) goto l36; yyDo(yy, yy_2_SI_Unit, yy->__begin, yy->__end); goto l34; l36:; yy->__pos= yypos34; yy->__thunkpos= yythunkpos34; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\000\000\200\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l37; if (!yy_SPACE(yy)) goto l37; yyDo(yy, yy_3_SI_Unit, yy->__begin, yy->__end); goto l34; l37:; yy->__pos= yypos34; yy->__thunkpos= yythunkpos34; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\000\000\000\000\020\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l38; if (!yy_SPACE(yy)) goto l38; yyDo(yy, yy_4_SI_Unit, yy->__begin, yy->__end); goto l34; l38:; yy->__pos= yypos34; yy->__thunkpos= yythunkpos34; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l33; if (!yy_SPACE(yy)) goto l33; yyDo(yy, yy_5_SI_Unit, yy->__begin, yy->__end); } l34:; yyprintf((stderr, " ok %s @ %s\n", "SI_Unit", yy->__buf+yy->__pos)); return 1; l33:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "SI_Unit", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_F_NUMBER(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "F_NUMBER")); yyText(yy, yy->__begin, yy->__end); if (!(YY_BEGIN)) goto l39; { int yypos40= yy->__pos, yythunkpos40= yy->__thunkpos; if (!yymatchChar(yy, '-')) goto l40; goto l41; l40:; yy->__pos= yypos40; yy->__thunkpos= yythunkpos40; } l41:; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l39; l42:; { int yypos43= yy->__pos, yythunkpos43= yy->__thunkpos; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l43; goto l42; l43:; yy->__pos= yypos43; yy->__thunkpos= yythunkpos43; } { int yypos44= yy->__pos, yythunkpos44= yy->__thunkpos; if (!yymatchChar(yy, '.')) goto l44; goto l45; l44:; yy->__pos= yypos44; yy->__thunkpos= yythunkpos44; } l45:; l46:; { int yypos47= yy->__pos, yythunkpos47= yy->__thunkpos; if (!yymatchClass(yy, (unsigned char *)"\000\000\000\000\000\000\377\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l47; goto l46; l47:; yy->__pos= yypos47; yy->__thunkpos= yythunkpos47; } yyText(yy, yy->__begin, yy->__end); if (!(YY_END)) goto l39; if (!yy_SPACE(yy)) goto l39; yyprintf((stderr, " ok %s @ %s\n", "F_NUMBER", yy->__buf+yy->__pos)); return 1; l39:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "F_NUMBER", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_MOD(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "MOD")); if (!yymatchChar(yy, '%')) goto l48; if (!yy_SPACE(yy)) goto l48; yyprintf((stderr, " ok %s @ %s\n", "MOD", yy->__buf+yy->__pos)); return 1; l48:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "MOD", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_DIVIDE(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "DIVIDE")); if (!yymatchChar(yy, '/')) goto l49; if (!yy_SPACE(yy)) goto l49; yyprintf((stderr, " ok %s @ %s\n", "DIVIDE", yy->__buf+yy->__pos)); return 1; l49:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "DIVIDE", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_TIMES(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "TIMES")); if (!yymatchChar(yy, '*')) goto l50; if (!yy_SPACE(yy)) goto l50; yyprintf((stderr, " ok %s @ %s\n", "TIMES", yy->__buf+yy->__pos)); return 1; l50:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "TIMES", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_POW(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "POW")); { int yypos52= yy->__pos, yythunkpos52= yy->__thunkpos; if (!yymatchChar(yy, '^')) goto l53; if (!yy_SPACE(yy)) goto l53; goto l52; l53:; yy->__pos= yypos52; yy->__thunkpos= yythunkpos52; if (!yymatchString(yy, "**")) goto l51; if (!yy_SPACE(yy)) goto l51; } l52:; yyprintf((stderr, " ok %s @ %s\n", "POW", yy->__buf+yy->__pos)); return 1; l51:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "POW", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_Value(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Value")); { int yypos55= yy->__pos, yythunkpos55= yy->__thunkpos; if (!yy_F_NUMBER(yy)) goto l56; if (!yy_SI_Unit(yy)) goto l56; yyDo(yy, yy_1_Value, yy->__begin, yy->__end); goto l55; l56:; yy->__pos= yypos55; yy->__thunkpos= yythunkpos55; if (!yy_F_NUMBER(yy)) goto l57; yyDo(yy, yy_2_Value, yy->__begin, yy->__end); goto l55; l57:; yy->__pos= yypos55; yy->__thunkpos= yythunkpos55; if (!yy_Constant(yy)) goto l58; goto l55; l58:; yy->__pos= yypos55; yy->__thunkpos= yythunkpos55; if (!yy_Funcall(yy)) goto l59; goto l55; l59:; yy->__pos= yypos55; yy->__thunkpos= yythunkpos55; if (!yy_OPEN(yy)) goto l54; if (!yy_Sum(yy)) goto l54; if (!yy_CLOSE(yy)) goto l54; } l55:; yyprintf((stderr, " ok %s @ %s\n", "Value", yy->__buf+yy->__pos)); return 1; l54:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Value", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_CLOSE_ENOUGH(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "CLOSE_ENOUGH")); if (!yymatchString(yy, "==")) goto l60; if (!yy_SPACE(yy)) goto l60; yyprintf((stderr, " ok %s @ %s\n", "CLOSE_ENOUGH", yy->__buf+yy->__pos)); return 1; l60:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "CLOSE_ENOUGH", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_MINUS(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "MINUS")); if (!yymatchChar(yy, '-')) goto l61; if (!yy_SPACE(yy)) goto l61; yyprintf((stderr, " ok %s @ %s\n", "MINUS", yy->__buf+yy->__pos)); return 1; l61:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "MINUS", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_PLUS(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "PLUS")); if (!yymatchChar(yy, '+')) goto l62; if (!yy_SPACE(yy)) goto l62; yyprintf((stderr, " ok %s @ %s\n", "PLUS", yy->__buf+yy->__pos)); return 1; l62:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "PLUS", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_Product(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Product")); if (!yy_Value(yy)) goto l63; l64:; { int yypos65= yy->__pos, yythunkpos65= yy->__thunkpos; { int yypos66= yy->__pos, yythunkpos66= yy->__thunkpos; if (!yy_POW(yy)) goto l67; if (!yy_Value(yy)) goto l67; yyDo(yy, yy_1_Product, yy->__begin, yy->__end); goto l66; l67:; yy->__pos= yypos66; yy->__thunkpos= yythunkpos66; if (!yy_TIMES(yy)) goto l68; if (!yy_Value(yy)) goto l68; yyDo(yy, yy_2_Product, yy->__begin, yy->__end); goto l66; l68:; yy->__pos= yypos66; yy->__thunkpos= yythunkpos66; if (!yy_DIVIDE(yy)) goto l69; if (!yy_Value(yy)) goto l69; yyDo(yy, yy_3_Product, yy->__begin, yy->__end); goto l66; l69:; yy->__pos= yypos66; yy->__thunkpos= yythunkpos66; if (!yy_MOD(yy)) goto l65; if (!yy_Value(yy)) goto l65; yyDo(yy, yy_4_Product, yy->__begin, yy->__end); } l66:; goto l64; l65:; yy->__pos= yypos65; yy->__thunkpos= yythunkpos65; } yyprintf((stderr, " ok %s @ %s\n", "Product", yy->__buf+yy->__pos)); return 1; l63:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Product", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_Sum(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Sum")); if (!yy_Product(yy)) goto l70; l71:; { int yypos72= yy->__pos, yythunkpos72= yy->__thunkpos; { int yypos73= yy->__pos, yythunkpos73= yy->__thunkpos; if (!yy_PLUS(yy)) goto l74; if (!yy_Product(yy)) goto l74; yyDo(yy, yy_1_Sum, yy->__begin, yy->__end); goto l73; l74:; yy->__pos= yypos73; yy->__thunkpos= yythunkpos73; if (!yy_MINUS(yy)) goto l75; if (!yy_Product(yy)) goto l75; yyDo(yy, yy_2_Sum, yy->__begin, yy->__end); goto l73; l75:; yy->__pos= yypos73; yy->__thunkpos= yythunkpos73; if (!yy_CLOSE_ENOUGH(yy)) goto l72; if (!yy_Product(yy)) goto l72; yyDo(yy, yy_3_Sum, yy->__begin, yy->__end); } l73:; goto l71; l72:; yy->__pos= yypos72; yy->__thunkpos= yythunkpos72; } yyprintf((stderr, " ok %s @ %s\n", "Sum", yy->__buf+yy->__pos)); return 1; l70:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Sum", yy->__buf+yy->__pos)); return 0; } YY_RULE(int) yy_SPACE(yycontext *yy) { yyprintf((stderr, "%s\n", "SPACE")); l77:; { int yypos78= yy->__pos, yythunkpos78= yy->__thunkpos; if (!yymatchClass(yy, (unsigned char *)"\000\002\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000")) goto l78; goto l77; l78:; yy->__pos= yypos78; yy->__thunkpos= yythunkpos78; } yyprintf((stderr, " ok %s @ %s\n", "SPACE", yy->__buf+yy->__pos)); return 1; } YY_RULE(int) yy_Expr(yycontext *yy) { int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos; yyprintf((stderr, "%s\n", "Expr")); { int yypos80= yy->__pos, yythunkpos80= yy->__thunkpos; if (!yy_SPACE(yy)) goto l81; if (!yy_Sum(yy)) goto l81; yyDo(yy, yy_1_Expr, yy->__begin, yy->__end); goto l80; l81:; yy->__pos= yypos80; yy->__thunkpos= yythunkpos80; if (!yymatchDot(yy)) goto l79; yyDo(yy, yy_2_Expr, yy->__begin, yy->__end); } l80:; yyprintf((stderr, " ok %s @ %s\n", "Expr", yy->__buf+yy->__pos)); return 1; l79:; yy->__pos= yypos0; yy->__thunkpos= yythunkpos0; yyprintf((stderr, " fail %s @ %s\n", "Expr", yy->__buf+yy->__pos)); return 0; } #ifndef YY_PART typedef int (*yyrule)(yycontext *yy); YY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart) { int yyok; if (!yyctx->__buflen) { yyctx->__buflen= YY_BUFFER_SIZE; yyctx->__buf= (char *)YY_MALLOC(yyctx, yyctx->__buflen); yyctx->__textlen= YY_BUFFER_SIZE; yyctx->__text= (char *)YY_MALLOC(yyctx, yyctx->__textlen); yyctx->__thunkslen= YY_STACK_SIZE; yyctx->__thunks= (yythunk *)YY_MALLOC(yyctx, sizeof(yythunk) * yyctx->__thunkslen); yyctx->__valslen= YY_STACK_SIZE; yyctx->__vals= (YYSTYPE *)YY_MALLOC(yyctx, sizeof(YYSTYPE) * yyctx->__valslen); yyctx->__begin= yyctx->__end= yyctx->__pos= yyctx->__limit= yyctx->__thunkpos= 0; } yyctx->__begin= yyctx->__end= yyctx->__pos; yyctx->__thunkpos= 0; yyctx->__val= yyctx->__vals; yyok= yystart(yyctx); if (yyok) yyDone(yyctx); yyCommit(yyctx); return yyok; } YY_PARSE(int) YYPARSE(YY_CTX_PARAM) { return YYPARSEFROM(YY_CTX_ARG_ yy_Expr); } YY_PARSE(yycontext *) YYRELEASE(yycontext *yyctx) { if (yyctx->__buflen) { yyctx->__buflen= 0; YY_FREE(yyctx->__buf); YY_FREE(yyctx->__text); YY_FREE(yyctx->__thunks); YY_FREE(yyctx->__vals); } return yyctx; } #endif cfengine-3.6.2/libpromises/files_lib.h0000644000175100017510000000412512352557236017461 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_LIB_H #define CFENGINE_FILES_LIB_H #include #include void PurgeItemList(Item **list, char *name); bool FileWriteOver(char *filename, char *contents); int LoadFileAsItemList(Item **liststart, const char *file, EditDefaults edits); bool MakeParentDirectory(const char *parentandchild, bool force); int MakeParentDirectory2(char *parentandchild, int force, bool enforce_promise); void RotateFiles(char *name, int number); void CreateEmptyFile(char *name); /** * @brief This is a somewhat simpler version of nftw that support user_data. * Callback function must return 0 to indicate success, -1 for failure. * @param path Path to traverse * @param user_data User data carry * @return True if successful */ bool TraverseDirectoryTree(const char *path, int (*callback)(const char *path, const struct stat *sb, void *user_data), void *user_data); bool HashDirectoryTree(const char *path, const char **extensions_filter, EVP_MD_CTX *crypto_context); #include #endif cfengine-3.6.2/libpromises/mod_common.h0000664000175100017510000000405012411001073017632 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_COMMON_H #define CFENGINE_MOD_COMMON_H #include typedef enum { SERVER_CONTROL_ALLOW_ALL_CONNECTS, SERVER_CONTROL_ALLOW_CONNECTS, SERVER_CONTROL_ALLOW_USERS, SERVER_CONTROL_AUDITING, SERVER_CONTROL_BIND_TO_INTERFACE, SERVER_CONTROL_CF_RUN_COMMAND, SERVER_CONTROL_CALL_COLLECT_INTERVAL, SERVER_CONTROL_CALL_COLLECT_WINDOW, SERVER_CONTROL_DENY_BAD_CLOCKS, SERVER_CONTROL_DENY_CONNECTS, SERVER_CONTROL_DYNAMIC_ADDRESSES, SERVER_CONTROL_HOSTNAME_KEYS, SERVER_CONTROL_KEY_TTL, SERVER_CONTROL_LOG_ALL_CONNECTIONS, SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS, SERVER_CONTROL_MAX_CONNECTIONS, SERVER_CONTROL_PORT_NUMBER, SERVER_CONTROL_SERVER_FACILITY, SERVER_CONTROL_SKIP_VERIFY, SERVER_CONTROL_TRUST_KEYS_FROM, SERVER_CONTROL_LISTEN, SERVER_CONTROL_ALLOWCIPHERS, SERVER_CONTROL_ALLOWLEGACYCONNECTS, SERVER_CONTROL_NONE } ServerControl; extern const ConstraintSyntax CFS_CONTROLBODY[SERVER_CONTROL_NONE + 1]; CommonControl CommonControlFromString(const char *lval); #endif cfengine-3.6.2/libpromises/mutex.c0000644000175100017510000000524512352022221016647 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* Log */ static pthread_mutex_t MUTEXES[] = /* GLOBAL_T */ { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, }; pthread_mutex_t *cft_lock = &MUTEXES[0]; /* GLOBAL_T */ pthread_mutex_t *cft_count = &MUTEXES[1]; /* GLOBAL_T */ pthread_mutex_t *cft_getaddr = &MUTEXES[2]; /* GLOBAL_T */ pthread_mutex_t *cft_server_children = &MUTEXES[3]; /* GLOBAL_T */ pthread_mutex_t *cft_server_filter = &MUTEXES[4]; /* GLOBAL_T */ int __ThreadLock(pthread_mutex_t *mutex, const char *funcname, const char *filename, int lineno) { int result = pthread_mutex_lock(mutex); if (result != 0) { /* Log() is blocking on mutexes itself inside malloc(), so maybe not * the best idea here. */ Log(LOG_LEVEL_ERR, "Locking failure at %s:%d function %s! (pthread_mutex_lock: %s)", filename, lineno, funcname, GetErrorStrFromCode(result)); return false; } return true; } int __ThreadUnlock(pthread_mutex_t *mutex, const char *funcname, const char *filename, int lineno) { int result = pthread_mutex_unlock(mutex); if (result != 0) { /* Log() is blocking on mutexes itself inside malloc(), so maybe not * the best idea here. */ Log(LOG_LEVEL_ERR, "Locking failure at %s:%d function %s! (pthread_mutex_unlock: %s)", filename, lineno, funcname, GetErrorStrFromCode(result)); return false; } return true; } cfengine-3.6.2/libpromises/class.h0000664000175100017510000000245012411001073016612 0ustar00a10038a1003800000000000000#ifndef CFENGINE_CLASS_H #define CFENGINE_CLASS_H #include #include typedef struct { char *ns; char *name; size_t hash; ContextScope scope; bool is_soft; StringSet *tags; } Class; typedef struct ClassTable_ ClassTable; typedef struct ClassTableIterator_ ClassTableIterator; ClassTable *ClassTableNew(void); void ClassTableDestroy(ClassTable *table); bool ClassTablePut(ClassTable *table, const char *ns, const char *name, bool is_soft, ContextScope scope, const char *tags); Class *ClassTableGet(const ClassTable *table, const char *ns, const char *name); Class *ClassTableMatch(const ClassTable *table, const char *regex); bool ClassTableRemove(ClassTable *table, const char *ns, const char *name); bool ClassTableClear(ClassTable *table); ClassTableIterator *ClassTableIteratorNew(const ClassTable *table, const char *ns, bool is_hard, bool is_soft); Class *ClassTableIteratorNext(ClassTableIterator *iter); void ClassTableIteratorDestroy(ClassTableIterator *iter); typedef struct { char *ns; char *name; } ClassRef; ClassRef ClassRefParse(const char *expr); char *ClassRefToString(const char *ns, const char *name); bool ClassRefIsQualified(ClassRef ref); void ClassRefQualify(ClassRef *ref, const char *ns); void ClassRefDestroy(ClassRef ref); #endif cfengine-3.6.2/libpromises/mod_exec.c0000644000175100017510000000615012316547775017316 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax contain_constraints[] = { ConstraintSyntaxNewOption("useshell", "noshell,useshell,powershell," CF_BOOL, "noshell/useshell/powershell embed the command in the given shell environment. Default value: noshell", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("umask", "", "The umask value for the child process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("exec_owner", "", "The user name or id under which to run the process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("exec_group", "", "The group name or id under which to run the process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("exec_timeout", "1,3600", "Timeout in seconds for command completion", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("chdir", CF_ABSPATHRANGE, "Directory for setting current/base directory for the process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("chroot", CF_ABSPATHRANGE, "Directory of root sandbox for process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("preview", "true/false preview command when running in dry-run mode (with -n). Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("no_output", "true/false discard all output from the command. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax contain_body = BodySyntaxNew("contain", contain_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax commands_constraints[] = { ConstraintSyntaxNewString("args", "", "Alternative string of arguments for the command (concatenated with promiser string)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("contain", &contain_body, "Containment options for the execution process", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("module", "true/false whether to expect the cfengine module protocol. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_EXEC_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "commands", commands_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/mod_storage.h0000664000175100017510000000216712243421446020032 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_STORAGE_H #define CFENGINE_MOD_STORAGE_H #include extern const PromiseTypeSyntax CF_STORAGE_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/known_dirs.h0000644000175100017510000000227212316547775017716 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_KNOWN_DIRS_H #define CFENGINE_KNOWN_DIRS_H const char *GetWorkDir(void); const char *GetLogDir(void); const char *GetPidDir(void); const char *GetMasterDir(void); const char *GetInputDir(void); #endif cfengine-3.6.2/libpromises/policy.c0000664000175100017510000024561412411001073017012 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const char *const POLICY_ERROR_POLICY_NOT_RUNNABLE = "Policy is not runnable (does not contain a body common control)"; static const char *const POLICY_ERROR_BUNDLE_NAME_RESERVED = "Use of a reserved container name as a bundle name \"%s\""; static const char *const POLICY_ERROR_BUNDLE_REDEFINITION = "Duplicate definition of bundle %s with type %s"; static const char *const POLICY_ERROR_BUNDLE_UNDEFINED = "Undefined bundle %s with type %s"; static const char *const POLICY_ERROR_BODY_REDEFINITION = "Duplicate definition of body %s with type %s"; static const char *const POLICY_ERROR_BODY_UNDEFINED = "Undefined body %s with type %s"; static const char *const POLICY_ERROR_BODY_CONTROL_ARGS = "Control bodies cannot take arguments, body %s control"; static const char *const POLICY_ERROR_PROMISE_UNCOMMENTED = "Promise is missing a comment attribute, and comments are required " "by policy"; static const char *const POLICY_ERROR_PROMISE_DUPLICATE_HANDLE = "Duplicate promise handle %s found"; static const char *const POLICY_ERROR_LVAL_INVALID = "Promise type %s has unknown attribute %s"; static const char *const POLICY_ERROR_CONSTRAINT_TYPE_MISMATCH = "Type mismatch in constraint: %s"; static const char *const POLICY_ERROR_EMPTY_VARREF = "Empty variable reference"; //************************************************************************ static void BundleDestroy(Bundle *bundle); static void BodyDestroy(Body *body); static SyntaxTypeMatch ConstraintCheckType(const Constraint *cp); static bool PromiseCheck(const Promise *pp, Seq *errors); const char *NamespaceDefault(void) { return "default"; } Policy *PolicyNew(void) { Policy *policy = xcalloc(1, sizeof(Policy)); policy->release_id = NULL; policy->bundles = SeqNew(100, BundleDestroy); policy->bodies = SeqNew(100, BodyDestroy); return policy; } int PolicyCompare(const void *a, const void *b) { return a - b; } void PolicyDestroy(Policy *policy) { if (policy) { SeqDestroy(policy->bundles); SeqDestroy(policy->bodies); free(policy->release_id); free(policy); } } static unsigned ConstraintHash(const Constraint *cp, unsigned seed, unsigned max) { unsigned hash = seed; hash = StringHash(cp->lval, hash, max); hash = StringHash(cp->classes, hash, max); hash = RvalHash(cp->rval, hash, max); return hash; } static unsigned BodyHash(const Body *body, unsigned seed, unsigned max) { unsigned hash = seed; for (size_t i = 0; i < SeqLength(body->conlist); i++) { const Constraint *cp = SeqAt(body->conlist, i); hash = ConstraintHash(cp, hash, max); } return hash; } static unsigned PromiseHash(const Promise *pp, unsigned seed, unsigned max) { unsigned hash = seed; hash = StringHash(pp->promiser, seed, max); hash = RvalHash(pp->promisee, seed, max); for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); hash = ConstraintHash(cp, hash, max); } return hash; } static unsigned PromiseTypeHash(const PromiseType *pt, unsigned seed, unsigned max) { unsigned hash = seed; hash = StringHash(pt->name, hash, max); for (size_t i = 0; i < SeqLength(pt->promises); i++) { const Promise *pp = SeqAt(pt->promises, i); hash = PromiseHash(pp, hash, max); } return hash; } static unsigned BundleHash(const Bundle *bundle, unsigned seed, unsigned max) { unsigned hash = seed; hash = StringHash(bundle->type, hash, max); hash = StringHash(bundle->ns, hash, max); hash = StringHash(bundle->name, hash, max); hash = RlistHash(bundle->args, hash, max); for (size_t i = 0; i < SeqLength(bundle->promise_types); i++) { const PromiseType *pt = SeqAt(bundle->promise_types, i); hash = PromiseTypeHash(pt, hash, max); } return hash; } unsigned PolicyHash(const Policy *policy) { static const unsigned max = UINT_MAX; unsigned hash = 0; for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Body *body = SeqAt(policy->bodies, i); hash = BodyHash(body, hash, max); } for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *bundle = SeqAt(policy->bundles, i); hash = BundleHash(bundle, hash, max); } return hash; } StringSet *PolicySourceFiles(const Policy *policy) { StringSet *files = StringSetNew(); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *bp = SeqAt(policy->bundles, i); if (bp->source_path) { StringSetAdd(files, xstrdup(bp->source_path)); } } for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Bundle *bp = SeqAt(policy->bodies, i); if (bp->source_path) { StringSetAdd(files, xstrdup(bp->source_path)); } } return files; } static char *StripNamespace(const char *full_symbol) { char *sep = strchr(full_symbol, CF_NS); if (sep) { return xstrdup(sep + 1); } else { return xstrdup(full_symbol); } } Body *PolicyGetBody(const Policy *policy, const char *ns, const char *type, const char *name) { for (size_t i = 0; i < SeqLength(policy->bodies); i++) { Body *bp = SeqAt(policy->bodies, i); char *body_symbol = StripNamespace(bp->name); if (strcmp(bp->type, type) == 0 && strcmp(body_symbol, name) == 0) { free(body_symbol); // allow namespace to be optionally matched if (ns && strcmp(bp->ns, ns) != 0) { continue; } return bp; } free(body_symbol); } return NULL; } Bundle *PolicyGetBundle(const Policy *policy, const char *ns, const char *type, const char *name) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); char *bundle_symbol = StripNamespace(name); if ((!type || strcmp(bp->type, type) == 0) && ((strcmp(bundle_symbol, bp->name) == 0) || (strcmp(bp->name, name) == 0))) { free(bundle_symbol); // allow namespace to be optionally matched if (ns && strcmp(bp->ns, ns) != 0) { continue; } return bp; } free(bundle_symbol); } return NULL; } bool PolicyIsRunnable(const Policy *policy) { return PolicyGetBody(policy, NULL, "common", "control") != NULL; } Policy *PolicyMerge(Policy *a, Policy *b) { Policy *result = PolicyNew(); SeqAppendSeq(result->bundles, a->bundles); SeqSoftDestroy(a->bundles); SeqAppendSeq(result->bundles, b->bundles); SeqSoftDestroy(b->bundles); for (size_t i = 0; i < SeqLength(result->bundles); i++) { Bundle *bp = SeqAt(result->bundles, i); bp->parent_policy = result; } SeqAppendSeq(result->bodies, a->bodies); SeqSoftDestroy(a->bodies); SeqAppendSeq(result->bodies, b->bodies); SeqSoftDestroy(b->bodies); for (size_t i = 0; i < SeqLength(result->bodies); i++) { Body *bdp = SeqAt(result->bodies, i); bdp->parent_policy = result; } /* Should result take over a release_id ? */ free(a->release_id); free(b->release_id); free(a); free(b); return result; } const char *ConstraintGetNamespace(const Constraint *cp) { switch (cp->type) { case POLICY_ELEMENT_TYPE_BODY: return cp->parent.body->ns; case POLICY_ELEMENT_TYPE_PROMISE: return cp->parent.promise->parent_promise_type->parent_bundle->ns; default: ProgrammingError("Constraint has parent type: %d", cp->type); } } /*************************************************************************/ const Policy *PolicyFromPromise(const Promise *promise) { assert(promise); PromiseType *promise_type = promise->parent_promise_type; assert(promise_type); Bundle *bundle = promise_type->parent_bundle; assert(bundle); return bundle->parent_policy; } char *BundleQualifiedName(const Bundle *bundle) { assert(bundle); if (!bundle) { return NULL; } if (bundle->name) { const char *ns = bundle->ns ? bundle->ns : NamespaceDefault(); return StringConcatenate(3, ns, ":", bundle->name); // CF_NS == ':' } return NULL; } static bool RvalTypeCheckDataType(RvalType rval_type, DataType expected_datatype) { if (rval_type == RVAL_TYPE_FNCALL) { return true; } switch (expected_datatype) { case CF_DATA_TYPE_BODY: case CF_DATA_TYPE_BUNDLE: return rval_type == RVAL_TYPE_SCALAR; case CF_DATA_TYPE_CONTEXT: case CF_DATA_TYPE_COUNTER: case CF_DATA_TYPE_INT: case CF_DATA_TYPE_INT_RANGE: case CF_DATA_TYPE_OPTION: case CF_DATA_TYPE_REAL: case CF_DATA_TYPE_REAL_RANGE: case CF_DATA_TYPE_STRING: return rval_type == RVAL_TYPE_SCALAR; case CF_DATA_TYPE_CONTEXT_LIST: case CF_DATA_TYPE_INT_LIST: case CF_DATA_TYPE_OPTION_LIST: case CF_DATA_TYPE_REAL_LIST: case CF_DATA_TYPE_STRING_LIST: return (rval_type == RVAL_TYPE_SCALAR) || (rval_type == RVAL_TYPE_LIST); case CF_DATA_TYPE_CONTAINER: return (rval_type == RVAL_TYPE_CONTAINER); default: ProgrammingError("Unhandled expected datatype in switch: %d", expected_datatype); } } /*************************************************************************/ /* Check if a constraint's syntax is correct according to its promise_type and lvalue. */ static bool ConstraintCheckSyntax(const Constraint *constraint, Seq *errors) { if (constraint->type != POLICY_ELEMENT_TYPE_PROMISE) { ProgrammingError("Attempted to check the syntax for a constraint" " not belonging to a promise"); } const PromiseType *promise_type = constraint->parent.promise->parent_promise_type; const Bundle *bundle = promise_type->parent_bundle; /* Check if lvalue is valid for the bundle's specific promise_type. */ const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(bundle->type, promise_type->name); for (size_t i = 0; promise_type_syntax->constraints[i].lval != NULL; i++) { const ConstraintSyntax *body_syntax = &promise_type_syntax->constraints[i]; if (strcmp(body_syntax->lval, constraint->lval) == 0) { if (!RvalTypeCheckDataType(constraint->rval.type, body_syntax->dtype)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_CONSTRAINT_TYPE_MISMATCH, constraint->lval)); return false; } return true; } } /* FIX: Call a VerifyConstraint() hook for the specific promise_type, defined in verify_TYPE.c, that checks for promise_type-specific constraint syntax. */ /* Check if lvalue is valid for all bodies. */ for (size_t i = 0; CF_COMMON_BODIES[i].lval != NULL; i++) { if (strcmp(constraint->lval, CF_COMMON_BODIES[i].lval) == 0) { if (!RvalTypeCheckDataType(constraint->rval.type, CF_COMMON_BODIES[i].dtype)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_CONSTRAINT_TYPE_MISMATCH, constraint->lval)); return false; } return true; } } for (size_t i = 0; CF_COMMON_EDITBODIES[i].lval != NULL; i++) { if (strcmp(constraint->lval, CF_COMMON_EDITBODIES[i].lval) == 0) { if (!RvalTypeCheckDataType(constraint->rval.type, CF_COMMON_EDITBODIES[i].dtype)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_CONSTRAINT_TYPE_MISMATCH, constraint->lval)); return false; } return true; } } for (size_t i = 0; CF_COMMON_XMLBODIES[i].lval != NULL; i++) { if (strcmp(constraint->lval, CF_COMMON_XMLBODIES[i].lval) == 0) { if (!RvalTypeCheckDataType(constraint->rval.type, CF_COMMON_XMLBODIES[i].dtype)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_CONSTRAINT_TYPE_MISMATCH, constraint->lval)); return false; } return true; } } /* lval is unknown for this promise type */ SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_LVAL_INVALID, constraint->parent.promise->parent_promise_type->name, constraint->lval)); return false; } /*************************************************************************/ static bool PolicyCheckPromiseType(const PromiseType *promise_type, Seq *errors) { assert(promise_type); assert(promise_type->parent_bundle); bool success = true; for (size_t i = 0; i < SeqLength(promise_type->promises); i++) { const Promise *pp = SeqAt(promise_type->promises, i); success &= PromiseCheck(pp, errors); } return success; } /*************************************************************************/ static bool PolicyCheckBundle(const Bundle *bundle, Seq *errors) { assert(bundle); bool success = true; // ensure no reserved bundle names are used { static const char *const reserved_names[] = { "sys", "const", "mon", "edit", "match", "mon", "this", NULL }; if (IsStrIn(bundle->name, reserved_names)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BUNDLE, bundle, POLICY_ERROR_BUNDLE_NAME_RESERVED, bundle->name)); success = false; } } for (size_t i = 0; i < SeqLength(bundle->promise_types); i++) { const PromiseType *type = SeqAt(bundle->promise_types, i); success &= PolicyCheckPromiseType(type, errors); } return success; } static bool PolicyCheckBody(const Body *body, Seq *errors) { bool success = true; if (strcmp("control", body->name) == 0) { if (RlistLen(body->args) > 0) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, POLICY_ERROR_BODY_CONTROL_ARGS, body->type)); success = false; } } for (size_t i = 0; i < SeqLength(body->conlist); i++) { Constraint *cp = SeqAt(body->conlist, i); SyntaxTypeMatch err = ConstraintCheckType(cp); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp, POLICY_ERROR_CONSTRAINT_TYPE_MISMATCH, cp->lval)); success = false; } } const BodySyntax *body_syntax = BodySyntaxGet(body->type); assert(body_syntax && "Should have been checked at parse time"); if (body_syntax->check_body) { success &= body_syntax->check_body(body, errors); } return success; } /*************************************************************************/ /* Get the syntax of a constraint according to its promise_type and lvalue. Make sure you've already checked the constraint's validity. */ static const ConstraintSyntax *ConstraintGetSyntax(const Constraint *constraint) { if (constraint->type != POLICY_ELEMENT_TYPE_PROMISE) { ProgrammingError("Attempted to get the syntax for a constraint not belonging to a promise"); } const Promise *promise = constraint->parent.promise; const PromiseType *promise_type = promise->parent_promise_type; const Bundle *bundle = promise_type->parent_bundle; const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(bundle->type, promise_type->name); /* Check if lvalue is valid for the bundle's specific promise_type. */ for (size_t i = 0; promise_type_syntax->constraints[i].lval != NULL; i++) { const ConstraintSyntax *body_syntax = &promise_type_syntax->constraints[i]; if (strcmp(body_syntax->lval, constraint->lval) == 0) { return body_syntax; } } /* Check if lvalue is valid for all bodies. */ for (size_t i = 0; CF_COMMON_BODIES[i].lval != NULL; i++) { if (strcmp(constraint->lval, CF_COMMON_BODIES[i].lval) == 0) { return &CF_COMMON_BODIES[i]; } } for (size_t i = 0; CF_COMMON_EDITBODIES[i].lval != NULL; i++) { if (strcmp(constraint->lval, CF_COMMON_EDITBODIES[i].lval) == 0) { return &CF_COMMON_EDITBODIES[i]; } } for (size_t i = 0; CF_COMMON_XMLBODIES[i].lval != NULL; i++) { if (strcmp(constraint->lval, CF_COMMON_XMLBODIES[i].lval) == 0) { return &CF_COMMON_XMLBODIES[i]; } } /* Syntax must have been checked first during PolicyCheckPartial(). */ ProgrammingError("ConstraintGetSyntax() was called for constraint with " "invalid lvalue: %s", constraint->lval); return NULL; } /*************************************************************************/ /** * @return A reference to the full symbol value of the Rval regardless of type, e.g. "foo:bar""foo:bar" */ static const char *RvalFullSymbol(const Rval *rval) { switch (rval->type) { case RVAL_TYPE_SCALAR: return rval->item; break; case RVAL_TYPE_FNCALL: return ((FnCall *)rval->item)->name; default: ProgrammingError("Cannot get full symbol value from Rval of type %c", rval->type); return NULL; } } /** * @return A copy of the namespace compoent of an Rval, or NULL. e.g. "foo:bar""foo" */ char *QualifiedNameNamespaceComponent(const char *qualified_name) { if (strchr(qualified_name, CF_NS)) { char ns[CF_BUFSIZE] = { 0 }; sscanf(qualified_name, "%[^:]", ns); return xstrdup(ns); } else { return NULL; } } /** * @return A copy of the symbol compoent of an Rval, or NULL. e.g. "foo:bar""bar" */ char *QualifiedNameScopeComponent(const char *qualified_name) { char *sep = strchr(qualified_name, CF_NS); if (sep) { return xstrdup(sep + 1); } else { return xstrdup(qualified_name); } } static bool PolicyCheckUndefinedBodies(const Policy *policy, Seq *errors) { bool success = true; for (size_t bpi = 0; bpi < SeqLength(policy->bundles); bpi++) { Bundle *bundle = SeqAt(policy->bundles, bpi); for (size_t sti = 0; sti < SeqLength(bundle->promise_types); sti++) { PromiseType *promise_type = SeqAt(bundle->promise_types, sti); for (size_t ppi = 0; ppi < SeqLength(promise_type->promises); ppi++) { Promise *promise = SeqAt(promise_type->promises, ppi); for (size_t cpi = 0; cpi < SeqLength(promise->conlist); cpi++) { Constraint *constraint = SeqAt(promise->conlist, cpi); const ConstraintSyntax *syntax = ConstraintGetSyntax(constraint); if (syntax->dtype == CF_DATA_TYPE_BODY) { char *ns = QualifiedNameNamespaceComponent(RvalFullSymbol(&constraint->rval)); char *symbol = QualifiedNameScopeComponent(RvalFullSymbol(&constraint->rval)); Body *referenced_body = PolicyGetBody(policy, ns, constraint->lval, symbol); if (!referenced_body) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_BODY_UNDEFINED, symbol, constraint->lval)); success = false; } free(ns); free(symbol); } } // constraints } // promises } // promise_types } // bundles return success; } static bool PolicyCheckUndefinedBundles(const Policy *policy, Seq *errors) { bool success = true; for (size_t bpi = 0; bpi < SeqLength(policy->bundles); bpi++) { Bundle *bundle = SeqAt(policy->bundles, bpi); for (size_t sti = 0; sti < SeqLength(bundle->promise_types); sti++) { PromiseType *promise_type = SeqAt(bundle->promise_types, sti); for (size_t ppi = 0; ppi < SeqLength(promise_type->promises); ppi++) { Promise *promise = SeqAt(promise_type->promises, ppi); for (size_t cpi = 0; cpi < SeqLength(promise->conlist); cpi++) { Constraint *constraint = SeqAt(promise->conlist, cpi); const ConstraintSyntax *syntax = ConstraintGetSyntax(constraint); if (syntax->dtype == CF_DATA_TYPE_BUNDLE && !IsCf3VarString(RvalFullSymbol(&constraint->rval))) { char *ns = QualifiedNameNamespaceComponent(RvalFullSymbol(&constraint->rval)); char *symbol = QualifiedNameScopeComponent(RvalFullSymbol(&constraint->rval)); const Bundle *referenced_bundle = NULL; if (strcmp(constraint->lval, "usebundle") == 0 || strcmp(constraint->lval, "home_bundle") == 0) { referenced_bundle = PolicyGetBundle(policy, ns, "agent", symbol); if (!referenced_bundle) { referenced_bundle = PolicyGetBundle(policy, ns, "common", symbol); } } else { referenced_bundle = PolicyGetBundle(policy, ns, constraint->lval, symbol); } if (!referenced_bundle) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, constraint, POLICY_ERROR_BUNDLE_UNDEFINED, symbol, constraint->lval)); success = false; } free(ns); free(symbol); } } // constraints } // promises } // promise_types } // bundles return success; } static bool PolicyCheckRequiredComments(const EvalContext *ctx, const Policy *policy, Seq *errors) { const Body *common_control = PolicyGetBody(policy, NULL, "common", "control"); if (common_control) { bool require_comments = ConstraintsGetAsBoolean(ctx, "require_comments", common_control->conlist); if (!require_comments) { return true; } bool success = true; for (size_t bpi = 0; bpi < SeqLength(policy->bundles); bpi++) { Bundle *bundle = SeqAt(policy->bundles, bpi); for (size_t sti = 0; sti < SeqLength(bundle->promise_types); sti++) { PromiseType *promise_type = SeqAt(bundle->promise_types, sti); for (size_t ppi = 0; ppi < SeqLength(promise_type->promises); ppi++) { Promise *promise = SeqAt(promise_type->promises, ppi); bool promise_has_comment = false; for (size_t cpi = 0; cpi < SeqLength(promise->conlist); cpi++) { Constraint *constraint = SeqAt(promise->conlist, cpi); if (strcmp(constraint->lval, "comment") == 0) { promise_has_comment = true; break; } } // constraints if (!promise_has_comment) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, promise, POLICY_ERROR_PROMISE_UNCOMMENTED)); success = false; } } // promises } // promise_types } // bundles return success; } else { return true; } } bool PolicyCheckDuplicateHandles(const Policy *policy, Seq *errors) { bool success = true; Map *recorded = MapNew((MapHashFn)StringHash, (MapKeyEqualFn)StringSafeEqual, NULL, NULL); for (size_t bpi = 0; bpi < SeqLength(policy->bundles); bpi++) { Bundle *bundle = SeqAt(policy->bundles, bpi); for (size_t sti = 0; sti < SeqLength(bundle->promise_types); sti++) { PromiseType *promise_type = SeqAt(bundle->promise_types, sti); for (size_t ppi = 0; ppi < SeqLength(promise_type->promises); ppi++) { Promise *promise = SeqAt(promise_type->promises, ppi); const char *handle = PromiseGetHandle(promise); if (handle) { if (IsCf3VarString(handle)) { // can't check dynamic handles continue; } const Promise *other_promise = MapGet(recorded, handle); if (other_promise) { // Need to make this smarter by comparing parsed expressions for equivalency. if (strcmp(promise->classes, other_promise->classes) == 0) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, promise, POLICY_ERROR_PROMISE_DUPLICATE_HANDLE, handle)); success = false; } } else { MapInsert(recorded, (void *)handle, (void *)promise); } } } } } MapDestroy(recorded); return success; } bool PolicyCheckRunnable(const EvalContext *ctx, const Policy *policy, Seq *errors, bool ignore_missing_bundles) { // check has body common control { const Body *common_control = PolicyGetBody(policy, NULL, "common", "control"); if (!common_control) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_POLICY, policy, POLICY_ERROR_POLICY_NOT_RUNNABLE)); return false; } } bool success = true; success &= PolicyCheckRequiredComments(ctx, policy, errors); success &= PolicyCheckUndefinedBodies(policy, errors); if (!ignore_missing_bundles) { success &= PolicyCheckUndefinedBundles(policy, errors); } success &= PolicyCheckDuplicateHandles(policy, errors); return success; } bool PolicyCheckPartial(const Policy *policy, Seq *errors) { bool success = true; // ensure bundle names are not duplicated for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); for (size_t j = 0; j < SeqLength(policy->bundles); j++) { Bundle *bp2 = SeqAt(policy->bundles, j); if (bp != bp2 && strcmp(bp->type, bp2->type) == 0 && strcmp(bp->ns, bp2->ns) == 0 && strcmp(bp->name, bp2->name) == 0) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BUNDLE, bp, POLICY_ERROR_BUNDLE_REDEFINITION, bp->name, bp->type)); success = false; } } } for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); success &= PolicyCheckBundle(bp, errors); } // ensure body names are not duplicated for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Body *bp = SeqAt(policy->bodies, i); for (size_t j = 0; j < SeqLength(policy->bodies); j++) { const Body *bp2 = SeqAt(policy->bodies, j); if (bp != bp2 && strcmp(bp->type, bp2->type) == 0 && strcmp(bp->ns, bp2->ns) == 0 && strcmp(bp->name, bp2->name) == 0) { if (strcmp(bp->type,"file") != 0) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, bp, POLICY_ERROR_BODY_REDEFINITION, bp->name, bp->type)); success = false; } } } } for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Body *body = SeqAt(policy->bodies, i); success &= PolicyCheckBody(body, errors); } success &= PolicyCheckDuplicateHandles(policy, errors); return success; } /*************************************************************************/ PolicyError *PolicyErrorNew(PolicyElementType type, const void *subject, const char *error_msg, ...) { PolicyError *error = xmalloc(sizeof(PolicyError)); error->type = type; error->subject = subject; va_list args; va_start(args, error_msg); xvasprintf(&error->message, error_msg, args); va_end(args); return error; } /*************************************************************************/ void PolicyErrorDestroy(PolicyError *error) { free(error->message); free(error); } /*************************************************************************/ static SourceOffset PolicyElementSourceOffset(PolicyElementType type, const void *element) { assert(element); switch (type) { case POLICY_ELEMENT_TYPE_POLICY: { return (SourceOffset) { 0 }; } case POLICY_ELEMENT_TYPE_BUNDLE: { const Bundle *bundle = (const Bundle *)element; return bundle->offset; } case POLICY_ELEMENT_TYPE_BODY: { const Body *body = (const Body *)element; return body->offset; } case POLICY_ELEMENT_TYPE_PROMISE_TYPE: { const PromiseType *type = (const PromiseType *)element; return type->offset; } case POLICY_ELEMENT_TYPE_PROMISE: { const Promise *promise = (const Promise *)element; return promise->offset; } case POLICY_ELEMENT_TYPE_CONSTRAINT: { const Constraint *constraint = (const Constraint *)element; return constraint->offset; } default: assert(false && "Invalid policy element"); return (SourceOffset) { 0 }; } } /*************************************************************************/ static const char *PolicyElementSourceFile(PolicyElementType type, const void *element) { assert(element); switch (type) { case POLICY_ELEMENT_TYPE_POLICY: return ""; case POLICY_ELEMENT_TYPE_BUNDLE: { const Bundle *bundle = (const Bundle *)element; return bundle->source_path; } case POLICY_ELEMENT_TYPE_BODY: { const Body *body = (const Body *)element; return body->source_path; } case POLICY_ELEMENT_TYPE_PROMISE_TYPE: { const PromiseType *type = (const PromiseType *)element; return PolicyElementSourceFile(POLICY_ELEMENT_TYPE_BUNDLE, type->parent_bundle); } case POLICY_ELEMENT_TYPE_PROMISE: { const Promise *promise = (const Promise *)element; return PolicyElementSourceFile(POLICY_ELEMENT_TYPE_PROMISE_TYPE, promise->parent_promise_type); } case POLICY_ELEMENT_TYPE_CONSTRAINT: { const Constraint *constraint = (const Constraint *)element; switch (constraint->type) { case POLICY_ELEMENT_TYPE_BODY: return PolicyElementSourceFile(POLICY_ELEMENT_TYPE_BODY, constraint->parent.body); case POLICY_ELEMENT_TYPE_PROMISE: return PolicyElementSourceFile(POLICY_ELEMENT_TYPE_PROMISE, constraint->parent.promise); default: assert(false && "Constraint has invalid parent element type"); return NULL; } } default: assert(false && "Invalid policy element"); return NULL; } } /*************************************************************************/ void PolicyErrorWrite(Writer *writer, const PolicyError *error) { SourceOffset offset = PolicyElementSourceOffset(error->type, error->subject); const char *path = PolicyElementSourceFile(error->type, error->subject); // FIX: need to track columns in SourceOffset WriterWriteF(writer, "%s:%zu:%zu: error: %s\n", path, offset.line, (size_t)0, error->message); } static char *PolicyErrorToString(const PolicyError *error) { SourceOffset offset = PolicyElementSourceOffset(error->type, error->subject); const char *path = PolicyElementSourceFile(error->type, error->subject); Writer *msg = StringWriter(); WriterWriteF(msg, "%s:%zu:%zu: %s.", path, offset.line, (size_t)0, error->message); switch (error->type) { case POLICY_ELEMENT_TYPE_CONSTRAINT: { const Constraint *cp = error->subject; WriterWrite(msg, " Given attribute value '"); RvalWrite(msg, cp->rval); WriterWriteChar(msg, '\''); } break; default: break; } return StringWriterClose(msg); } /*************************************************************************/ void PromiseTypeDestroy(PromiseType *promise_type) { if (promise_type) { SeqDestroy(promise_type->promises); free(promise_type->name); free(promise_type); } } Bundle *PolicyAppendBundle(Policy *policy, const char *ns, const char *name, const char *type, const Rlist *args, const char *source_path) { Bundle *bundle = xcalloc(1, sizeof(Bundle)); bundle->parent_policy = policy; SeqAppend(policy->bundles, bundle); bundle->name = xstrdup(name); bundle->type = xstrdup(type); bundle->ns = xstrdup(ns); bundle->args = RlistCopy(args); bundle->source_path = SafeStringDuplicate(source_path); bundle->promise_types = SeqNew(10, PromiseTypeDestroy); return bundle; } /*******************************************************************/ Body *PolicyAppendBody(Policy *policy, const char *ns, const char *name, const char *type, Rlist *args, const char *source_path) { Body *body = xcalloc(1, sizeof(Body)); body->parent_policy = policy; SeqAppend(policy->bodies, body); body->name = xstrdup(name); body->type = xstrdup(type); body->ns = xstrdup(ns); body->args = RlistCopy(args); body->source_path = SafeStringDuplicate(source_path); body->conlist = SeqNew(10, ConstraintDestroy); // TODO: move to standard callback if (strcmp("service_method", body->name) == 0) { Rlist *args = NULL; RlistAppendRval(&args, RvalNew("$(this.promiser)", RVAL_TYPE_SCALAR)); RlistAppendRval(&args, RvalNew("$(this.service_policy)", RVAL_TYPE_SCALAR)); FnCall *service_bundle = FnCallNew("standard_services", args); BodyAppendConstraint(body, "service_bundle", (Rval) { service_bundle, RVAL_TYPE_FNCALL }, "any", false); } return body; } PromiseType *BundleAppendPromiseType(Bundle *bundle, const char *name) { if (bundle == NULL) { ProgrammingError("Attempt to add a type without a bundle"); } // TODO: review SeqLookup for (size_t i = 0; i < SeqLength(bundle->promise_types); i++) { PromiseType *existing = SeqAt(bundle->promise_types, i); if (strcmp(existing->name, name) == 0) { return existing; } } PromiseType *tp = xcalloc(1, sizeof(PromiseType)); tp->parent_bundle = bundle; tp->name = xstrdup(name); tp->promises = SeqNew(10, PromiseDestroy); SeqAppend(bundle->promise_types, tp); return tp; } /*******************************************************************/ Promise *PromiseTypeAppendPromise(PromiseType *type, const char *promiser, Rval promisee, const char *classes) { assert(promiser && "Missing promiser"); assert(type && "Missing promise type"); Promise *pp = xcalloc(1, sizeof(Promise)); pp->promiser = xstrdup(promiser); if (classes && strlen(classes) > 0) { pp->classes = xstrdup(classes); } else { pp->classes = xstrdup("any"); } SeqAppend(type->promises, pp); pp->parent_promise_type = type; pp->promisee = promisee; pp->has_subbundles = false; pp->conlist = SeqNew(10, ConstraintDestroy); pp->org_pp = pp; // TODO: move into promise type syntax callbacks for default values if (strcmp("packages", type->name) == 0) { PromiseAppendConstraint(pp, "package_method", RvalNew("generic", RVAL_TYPE_SCALAR), true); } return pp; } static void BundleDestroy(Bundle *bundle) { if (bundle) { free(bundle->name); free(bundle->type); free(bundle->ns); free(bundle->source_path); RlistDestroy(bundle->args); SeqDestroy(bundle->promise_types); free(bundle); } } static void BodyDestroy(Body *body) { if (body) { free(body->name); free(body->type); free(body->ns); free(body->source_path); RlistDestroy(body->args); SeqDestroy(body->conlist); free(body); } } void PromiseDestroy(Promise *pp) { if (pp) { free(pp->promiser); if (pp->promisee.item) { RvalDestroy(pp->promisee); } free(pp->classes); free(pp->comment); SeqDestroy(pp->conlist); free(pp); } } /*******************************************************************/ static Constraint *ConstraintNew(const char *lval, Rval rval, const char *classes, bool references_body) { Constraint *cp = xcalloc(1, sizeof(Constraint)); cp->lval = SafeStringDuplicate(lval); cp->rval = rval; cp->classes = SafeStringDuplicate(classes); cp->references_body = references_body; return cp; } Constraint *PromiseAppendConstraint(Promise *pp, const char *lval, Rval rval, bool references_body) { Constraint *cp = ConstraintNew(lval, rval, "any", references_body); cp->type = POLICY_ELEMENT_TYPE_PROMISE; cp->parent.promise = pp; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *old_cp = SeqAt(pp->conlist, i); if (strcmp(old_cp->lval, lval) == 0) { SeqSet(pp->conlist, i, cp); return cp; } } SeqAppend(pp->conlist, cp); return cp; } Constraint *BodyAppendConstraint(Body *body, const char *lval, Rval rval, const char *classes, bool references_body) { Constraint *cp = ConstraintNew(lval, rval, classes, references_body); cp->type = POLICY_ELEMENT_TYPE_BODY; cp->parent.body = body; for (size_t i = 0; i < SeqLength(body->conlist); i++) { Constraint *old_cp = SeqAt(body->conlist, i); if (strcmp(old_cp->lval, lval) == 0 && strcmp(old_cp->classes, classes) == 0) { SeqSet(body->conlist, i, cp); return cp; } } SeqAppend(body->conlist, cp); return cp; } /*******************************************************************/ const PromiseType *BundleGetPromiseType(const Bundle *bp, const char *name) { // TODO: hiding error, remove and see what will crash if (bp == NULL) { return NULL; } for (size_t i = 0; i < SeqLength(bp->promise_types); i++) { PromiseType *sp = SeqAt(bp->promise_types, i); if (strcmp(name, sp->name) == 0) { return sp; } } return NULL; } /****************************************************************************/ static char *EscapeQuotes(const char *s, char *out, int outSz) { char *spt; const char *spf; int i = 0; memset(out, 0, outSz); for (spf = s, spt = out; (i < outSz - 2) && (*spf != '\0'); spf++, spt++, i++) { switch (*spf) { case '\'': case '\"': *spt++ = '\\'; *spt = *spf; i += 3; break; default: *spt = *spf; i++; break; } } return out; } static JsonElement *AttributeValueToJson(Rval rval, bool symbolic_reference) { JsonElement *json_attribute = JsonObjectCreate(10); switch (rval.type) { case RVAL_TYPE_SCALAR: { char buffer[CF_BUFSIZE]; EscapeQuotes((const char *) rval.item, buffer, sizeof(buffer)); if (symbolic_reference) { JsonObjectAppendString(json_attribute, "type", "symbol"); } else { JsonObjectAppendString(json_attribute, "type", "string"); } JsonObjectAppendString(json_attribute, "value", buffer); return json_attribute; } case RVAL_TYPE_LIST: { Rlist *rp = NULL; JsonElement *list = JsonArrayCreate(10); JsonObjectAppendString(json_attribute, "type", "list"); for (rp = (Rlist *) rval.item; rp != NULL; rp = rp->next) { JsonArrayAppendObject(list, AttributeValueToJson(rp->val, false)); } JsonObjectAppendArray(json_attribute, "value", list); return json_attribute; } case RVAL_TYPE_FNCALL: { Rlist *argp = NULL; FnCall *call = (FnCall *) rval.item; JsonObjectAppendString(json_attribute, "type", "functionCall"); JsonObjectAppendString(json_attribute, "name", call->name); { JsonElement *arguments = JsonArrayCreate(10); for (argp = call->args; argp != NULL; argp = argp->next) { JsonArrayAppendObject(arguments, AttributeValueToJson(argp->val, false)); } JsonObjectAppendArray(json_attribute, "arguments", arguments); } return json_attribute; } case RVAL_TYPE_CONTAINER: case RVAL_TYPE_NOPROMISEE: ProgrammingError("Attempted to export attribute of type: %c", rval.type); return NULL; } assert(false); return NULL; } static JsonElement *CreateContextAsJson(const char *name, const char *children_name, JsonElement *children) { JsonElement *json = JsonObjectCreate(10); JsonObjectAppendString(json, "name", name); JsonObjectAppendArray(json, children_name, children); return json; } static JsonElement *BodyContextsToJson(const Seq *constraints) { JsonElement *json_contexts = JsonArrayCreate(10); JsonElement *json_attributes = JsonArrayCreate(10); char *current_context = "any"; for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); JsonElement *json_attribute = JsonObjectCreate(10); if (strcmp(current_context, cp->classes) != 0) { JsonArrayAppendObject(json_contexts, CreateContextAsJson(current_context, "attributes", json_attributes)); json_attributes = JsonArrayCreate(10); current_context = cp->classes; } JsonObjectAppendInteger(json_attribute, "line", cp->offset.line); JsonObjectAppendString(json_attribute, "lval", cp->lval); JsonObjectAppendObject(json_attribute, "rval", AttributeValueToJson(cp->rval, false)); JsonArrayAppendObject(json_attributes, json_attribute); } JsonArrayAppendObject(json_contexts, CreateContextAsJson(current_context, "attributes", json_attributes)); return json_contexts; } static JsonElement *BundleContextsToJson(const Seq *promises) { JsonElement *json_contexts = JsonArrayCreate(10); JsonElement *json_promises = JsonArrayCreate(10); char *current_context = NULL; for (size_t ppi = 0; ppi < SeqLength(promises); ppi++) { Promise *pp = SeqAt(promises, ppi); if (!current_context) { current_context = pp->classes; } JsonElement *json_promise = JsonObjectCreate(10); if (strcmp(current_context, pp->classes) != 0) { JsonArrayAppendObject(json_contexts, CreateContextAsJson(current_context, "promises", json_promises)); json_promises = JsonArrayCreate(10); current_context = pp->classes; } JsonObjectAppendInteger(json_promise, "line", pp->offset.line); { JsonElement *json_promise_attributes = JsonArrayCreate(10); for (size_t k = 0; k < SeqLength(pp->conlist); k++) { Constraint *cp = SeqAt(pp->conlist, k); JsonElement *json_attribute = JsonObjectCreate(10); JsonObjectAppendInteger(json_attribute, "line", cp->offset.line); JsonObjectAppendString(json_attribute, "lval", cp->lval); JsonObjectAppendObject(json_attribute, "rval", AttributeValueToJson(cp->rval, cp->references_body)); JsonArrayAppendObject(json_promise_attributes, json_attribute); } JsonObjectAppendString(json_promise, "promiser", pp->promiser); switch (pp->promisee.type) { case RVAL_TYPE_SCALAR: JsonObjectAppendString(json_promise, "promisee", pp->promisee.item); break; case RVAL_TYPE_LIST: { JsonElement *promisee_list = JsonArrayCreate(10); for (const Rlist *rp = pp->promisee.item; rp; rp = rp->next) { JsonArrayAppendString(promisee_list, RlistScalarValue(rp)); } JsonObjectAppendArray(json_promise, "promisee", promisee_list); } break; default: break; } JsonObjectAppendArray(json_promise, "attributes", json_promise_attributes); } JsonArrayAppendObject(json_promises, json_promise); } if (JsonLength(json_promises) > 0) { JsonArrayAppendObject(json_contexts, CreateContextAsJson(current_context, "promises", json_promises)); } return json_contexts; } static JsonElement *BundleToJson(const Bundle *bundle) { JsonElement *json_bundle = JsonObjectCreate(10); if (bundle->source_path) { JsonObjectAppendString(json_bundle, "sourcePath", bundle->source_path); } JsonObjectAppendInteger(json_bundle, "line", bundle->offset.line); JsonObjectAppendString(json_bundle, "namespace", bundle->ns); JsonObjectAppendString(json_bundle, "name", bundle->name); JsonObjectAppendString(json_bundle, "bundleType", bundle->type); { JsonElement *json_args = JsonArrayCreate(10); Rlist *argp = NULL; for (argp = bundle->args; argp != NULL; argp = argp->next) { JsonArrayAppendString(json_args, RlistScalarValue(argp)); } JsonObjectAppendArray(json_bundle, "arguments", json_args); } { JsonElement *json_promise_types = JsonArrayCreate(10); for (size_t i = 0; i < SeqLength(bundle->promise_types); i++) { const PromiseType *sp = SeqAt(bundle->promise_types, i); JsonElement *json_promise_type = JsonObjectCreate(10); JsonObjectAppendInteger(json_promise_type, "line", sp->offset.line); JsonObjectAppendString(json_promise_type, "name", sp->name); JsonObjectAppendArray(json_promise_type, "contexts", BundleContextsToJson(sp->promises)); JsonArrayAppendObject(json_promise_types, json_promise_type); } JsonObjectAppendArray(json_bundle, "promiseTypes", json_promise_types); } return json_bundle; } static JsonElement *BodyToJson(const Body *body) { JsonElement *json_body = JsonObjectCreate(10); if (body->source_path) { JsonObjectAppendString(json_body, "sourcePath", body->source_path); } JsonObjectAppendInteger(json_body, "line", body->offset.line); JsonObjectAppendString(json_body, "namespace", body->ns); JsonObjectAppendString(json_body, "name", body->name); JsonObjectAppendString(json_body, "bodyType", body->type); { JsonElement *json_args = JsonArrayCreate(10); Rlist *argp = NULL; for (argp = body->args; argp != NULL; argp = argp->next) { JsonArrayAppendString(json_args, RlistScalarValue(argp)); } JsonObjectAppendArray(json_body, "arguments", json_args); } JsonObjectAppendArray(json_body, "contexts", BodyContextsToJson(body->conlist)); return json_body; } JsonElement *PolicyToJson(const Policy *policy) { JsonElement *json_policy = JsonObjectCreate(10); { JsonElement *json_bundles = JsonArrayCreate(10); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *bp = SeqAt(policy->bundles, i); JsonArrayAppendObject(json_bundles, BundleToJson(bp)); } JsonObjectAppendArray(json_policy, "bundles", json_bundles); } { JsonElement *json_bodies = JsonArrayCreate(10); for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Body *bdp = SeqAt(policy->bodies, i); JsonArrayAppendObject(json_bodies, BodyToJson(bdp)); } JsonObjectAppendArray(json_policy, "bodies", json_bodies); } return json_policy; } /****************************************************************************/ static void IndentPrint(Writer *writer, int indent_level) { static const int PRETTY_PRINT_SPACES_PER_INDENT = 2; int i = 0; for (i = 0; i < PRETTY_PRINT_SPACES_PER_INDENT * indent_level; i++) { WriterWriteChar(writer, ' '); } } static void AttributeToString(Writer *writer, Constraint *attribute, bool symbolic_reference) { WriterWriteF(writer, "%s => ", attribute->lval); if (attribute->rval.type == RVAL_TYPE_SCALAR && !symbolic_reference) { WriterWriteChar(writer, '"'); RvalWrite(writer, attribute->rval); WriterWriteChar(writer, '"'); } else { RvalWrite(writer, attribute->rval); } } static void ArgumentsToString(Writer *writer, Rlist *args) { Rlist *argp = NULL; WriterWriteChar(writer, '('); for (argp = args; argp != NULL; argp = argp->next) { WriterWriteF(writer, "%s", RlistScalarValue(argp)); if (argp->next != NULL) { WriterWrite(writer, ", "); } } WriterWriteChar(writer, ')'); } void BodyToString(Writer *writer, Body *body) { char *current_class = NULL; WriterWriteF(writer, "body %s %s", body->type, body->name); ArgumentsToString(writer, body->args); WriterWrite(writer, "\n{"); for (size_t i = 0; i < SeqLength(body->conlist); i++) { Constraint *cp = SeqAt(body->conlist, i); if (current_class == NULL || strcmp(cp->classes, current_class) != 0) { current_class = cp->classes; if (strcmp(current_class, "any") == 0) { WriterWrite(writer, "\n"); } else { WriterWriteF(writer, "\n\n%s::", current_class); } } WriterWriteChar(writer, '\n'); IndentPrint(writer, 1); AttributeToString(writer, cp, false); } WriterWrite(writer, "\n}\n"); } void BundleToString(Writer *writer, Bundle *bundle) { WriterWriteF(writer, "bundle %s %s", bundle->type, bundle->name); ArgumentsToString(writer, bundle->args); WriterWrite(writer, "\n{"); for (size_t i = 0; i < SeqLength(bundle->promise_types); i++) { PromiseType *promise_type = SeqAt(bundle->promise_types, i); WriterWriteF(writer, "\n%s:\n", promise_type->name); for (size_t ppi = 0; ppi < SeqLength(promise_type->promises); ppi++) { Promise *pp = SeqAt(promise_type->promises, ppi); char *current_class = NULL; if (current_class == NULL || strcmp(pp->classes, current_class) != 0) { current_class = pp->classes; if (strcmp(current_class, "any") != 0) { IndentPrint(writer, 1); WriterWriteF(writer, "%s::", current_class); } } IndentPrint(writer, 2); WriterWriteF(writer, "\"%s\"", pp->promiser); /* FIX: add support * if (pp->promisee != NULL) { fprintf(out, "%s", pp->promisee); } */ for (size_t k = 0; k < SeqLength(pp->conlist); k++) { Constraint *cp = SeqAt(pp->conlist, k); WriterWriteChar(writer, '\n'); IndentPrint(writer, 4); AttributeToString(writer, cp, cp->references_body); } } if (i == (SeqLength(bundle->promise_types) - 1)) { WriterWriteChar(writer, '\n'); } } WriterWrite(writer, "\n}\n"); } void PolicyToString(const Policy *policy, Writer *writer) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); BundleToString(writer, bundle); WriterWriteChar(writer, '\n'); } for (size_t i = 0; i < SeqLength(policy->bodies); i++) { Body *body = SeqAt(policy->bodies, i); BodyToString(writer, body); WriterWriteChar(writer, '\n'); } } //***************************************************************************** static Rval RvalFromJson(JsonElement *json_rval) { const char *type = JsonObjectGetAsString(json_rval, "type"); if (strcmp("string", type) == 0 || strcmp("symbol", type) == 0) { const char *value = JsonObjectGetAsString(json_rval, "value"); return ((Rval) { xstrdup(value), RVAL_TYPE_SCALAR }); } else if (strcmp("list", type) == 0) { JsonElement *json_list = JsonObjectGetAsArray(json_rval, "value"); Rlist *rlist = NULL; for (size_t i = 0; i < JsonLength(json_list); i++) { Rval list_value = RvalFromJson(JsonArrayGetAsObject(json_list, i)); RlistAppend(&rlist, list_value.item, list_value.type); } return ((Rval) { rlist, RVAL_TYPE_LIST }); } else if (strcmp("functionCall", type) == 0) { const char *name = JsonObjectGetAsString(json_rval, "name"); JsonElement *json_args = JsonObjectGetAsArray(json_rval, "arguments"); Rlist *args = NULL; for (size_t i = 0; i < JsonLength(json_args); i++) { JsonElement *json_arg = JsonArrayGetAsObject(json_args, i); Rval arg = RvalFromJson(json_arg); RlistAppend(&args, arg.item, arg.type); } FnCall *fn = FnCallNew(name, args); return ((Rval) { fn, RVAL_TYPE_FNCALL }); } else { ProgrammingError("Unexpected rval type: %s", type); } } static Constraint *PromiseAppendConstraintJson(Promise *promise, JsonElement *json_constraint) { const char *lval = JsonObjectGetAsString(json_constraint, "lval"); JsonElement *json_rval = JsonObjectGetAsObject(json_constraint, "rval"); const char *type = JsonObjectGetAsString(json_rval, "type"); Rval rval = RvalFromJson(json_rval); Constraint *cp = PromiseAppendConstraint(promise, lval, rval, (strcmp("symbol", type) == 0)); return cp; } static Promise *PromiseTypeAppendPromiseJson(PromiseType *promise_type, JsonElement *json_promise, const char *context) { const char *promiser = JsonObjectGetAsString(json_promise, "promiser"); Promise *promise = PromiseTypeAppendPromise(promise_type, promiser, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, context); JsonElement *json_attributes = JsonObjectGetAsArray(json_promise, "attributes"); for (size_t i = 0; i < JsonLength(json_attributes); i++) { JsonElement *json_attribute = JsonArrayGetAsObject(json_attributes, i); PromiseAppendConstraintJson(promise, json_attribute); } return promise; } static PromiseType *BundleAppendPromiseTypeJson(Bundle *bundle, JsonElement *json_promise_type) { const char *name = JsonObjectGetAsString(json_promise_type, "name"); PromiseType *promise_type = BundleAppendPromiseType(bundle, name); JsonElement *json_contexts = JsonObjectGetAsArray(json_promise_type, "contexts"); for (size_t i = 0; i < JsonLength(json_contexts); i++) { JsonElement *json_context = JsonArrayGetAsObject(json_contexts, i); const char *context = JsonObjectGetAsString(json_context, "name"); JsonElement *json_context_promises = JsonObjectGetAsArray(json_context, "promises"); for (size_t j = 0; j < JsonLength(json_context_promises); j++) { JsonElement *json_promise = JsonArrayGetAsObject(json_context_promises, j); PromiseTypeAppendPromiseJson(promise_type, json_promise, context); } } return promise_type; } static Bundle *PolicyAppendBundleJson(Policy *policy, JsonElement *json_bundle) { const char *ns = JsonObjectGetAsString(json_bundle, "namespace"); const char *name = JsonObjectGetAsString(json_bundle, "name"); const char *type = JsonObjectGetAsString(json_bundle, "bundleType"); const char *source_path = JsonObjectGetAsString(json_bundle, "sourcePath"); Rlist *args = NULL; { JsonElement *json_args = JsonObjectGetAsArray(json_bundle, "arguments"); for (size_t i = 0; i < JsonLength(json_args); i++) { RlistAppendScalar(&args, JsonArrayGetAsString(json_args, i)); } } Bundle *bundle = PolicyAppendBundle(policy, ns, name, type, args, source_path); { JsonElement *json_promise_types = JsonObjectGetAsArray(json_bundle, "promiseTypes"); for (size_t i = 0; i < JsonLength(json_promise_types); i++) { JsonElement *json_promise_type = JsonArrayGetAsObject(json_promise_types, i); BundleAppendPromiseTypeJson(bundle, json_promise_type); } } return bundle; } static Constraint *BodyAppendConstraintJson(Body *body, JsonElement *json_constraint, const char *context) { const char *lval = JsonObjectGetAsString(json_constraint, "lval"); JsonElement *json_rval = JsonObjectGetAsObject(json_constraint, "rval"); const char *type = JsonObjectGetAsString(json_rval, "type"); Rval rval = RvalFromJson(json_rval); Constraint *cp = BodyAppendConstraint(body, lval, rval, context, (strcmp("symbol", type) == 0)); return cp; } static Body *PolicyAppendBodyJson(Policy *policy, JsonElement *json_body) { const char *ns = JsonObjectGetAsString(json_body, "namespace"); const char *name = JsonObjectGetAsString(json_body, "name"); const char *type = JsonObjectGetAsString(json_body, "bodyType"); const char *source_path = JsonObjectGetAsString(json_body, "sourcePath"); Rlist *args = NULL; { JsonElement *json_args = JsonObjectGetAsArray(json_body, "arguments"); for (size_t i = 0; i < JsonLength(json_args); i++) { RlistAppendScalar(&args, JsonArrayGetAsString(json_args, i)); } } Body *body = PolicyAppendBody(policy, ns, name, type, args, source_path); { JsonElement *json_contexts = JsonObjectGetAsArray(json_body, "contexts"); for (size_t i = 0; i < JsonLength(json_contexts); i++) { JsonElement *json_context = JsonArrayGetAsObject(json_contexts, i); const char *context = JsonObjectGetAsString(json_context, "name"); { JsonElement *json_attributes = JsonObjectGetAsArray(json_context, "attributes"); for (size_t j = 0; j < JsonLength(json_attributes); j++) { JsonElement *json_attribute = JsonArrayGetAsObject(json_attributes, j); BodyAppendConstraintJson(body, json_attribute, context); } } } } return body; } Policy *PolicyFromJson(JsonElement *json_policy) { Policy *policy = PolicyNew(); { JsonElement *json_bundles = JsonObjectGetAsArray(json_policy, "bundles"); for (size_t i = 0; i < JsonLength(json_bundles); i++) { JsonElement *json_bundle = JsonArrayGetAsObject(json_bundles, i); PolicyAppendBundleJson(policy, json_bundle); } } { JsonElement *json_bodies = JsonObjectGetAsArray(json_policy, "bodies"); for (size_t i = 0; i < JsonLength(json_bodies); i++) { JsonElement *json_body = JsonArrayGetAsObject(json_bodies, i); PolicyAppendBodyJson(policy, json_body); } } return policy; } Seq *BodyGetConstraint(Body *body, const char *lval) { Seq *matches = SeqNew(5, NULL); for (size_t i = 0; i < SeqLength(body->conlist); i++) { Constraint *cp = SeqAt(body->conlist, i); if (strcmp(cp->lval, lval) == 0) { SeqAppend(matches, cp); } } return matches; } bool BodyHasConstraint(const Body *body, const char *lval) { for (int i = 0; i < SeqLength(body->conlist); i++) { Constraint *cp = SeqAt(body->conlist, i); if (strcmp(lval, cp->lval) == 0) { return true; } } return false; } const char *ConstraintContext(const Constraint *cp) { switch (cp->type) { case POLICY_ELEMENT_TYPE_BODY: return cp->classes; case POLICY_ELEMENT_TYPE_BUNDLE: return cp->parent.promise->classes; default: ProgrammingError("Constraint had parent element type: %d", cp->type); return NULL; } } Constraint *EffectiveConstraint(const EvalContext *ctx, Seq *constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); const char *context = ConstraintContext(cp); if (IsDefinedClass(ctx, context)) { return cp; } } return NULL; } void ConstraintDestroy(Constraint *cp) { if (cp) { RvalDestroy(cp->rval); free(cp->lval); free(cp->classes); free(cp); } } /*****************************************************************************/ int PromiseGetConstraintAsBoolean(const EvalContext *ctx, const char *lval, const Promise *pp) { int retval = CF_UNDEFINED; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, lval) == 0) { if (IsDefinedClass(ctx, cp->classes)) { if (retval != CF_UNDEFINED) { Log(LOG_LEVEL_ERR, "Multiple '%s' (boolean) constraints break this promise", lval); PromiseRef(LOG_LEVEL_ERR, pp); } } else { continue; } if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Type mismatch on rhs - expected type %c for boolean constraint '%s'", cp->rval.type, lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } if (strcmp(cp->rval.item, "true") == 0 || strcmp(cp->rval.item, "yes") == 0) { retval = true; continue; } if (strcmp(cp->rval.item, "false") == 0 || strcmp(cp->rval.item, "no") == 0) { retval = false; } } } if (retval == CF_UNDEFINED) { retval = false; } return retval; } /*****************************************************************************/ int ConstraintsGetAsBoolean(const EvalContext *ctx, const char *lval, const Seq *constraints) { int retval = CF_UNDEFINED; for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (strcmp(cp->lval, lval) == 0) { if (IsDefinedClass(ctx, cp->classes)) { if (retval != CF_UNDEFINED) { Log(LOG_LEVEL_ERR, "Multiple '%s' (boolean) body constraints break this promise", lval); } } else { continue; } if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Type mismatch - expected type %c for boolean constraint '%s'", cp->rval.type, lval); FatalError(ctx, "Aborted"); } if (strcmp(cp->rval.item, "true") == 0 || strcmp(cp->rval.item, "yes") == 0) { retval = true; continue; } if (strcmp(cp->rval.item, "false") == 0 || strcmp(cp->rval.item, "no") == 0) { retval = false; } } } if (retval == CF_UNDEFINED) { retval = false; } return retval; } /*****************************************************************************/ bool PromiseBundleConstraintExists(const EvalContext *ctx, const char *lval, const Promise *pp) { int retval = CF_UNDEFINED; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, lval) == 0) { if (IsDefinedClass(ctx, cp->classes)) { if (retval != CF_UNDEFINED) { Log(LOG_LEVEL_ERR, "Multiple '%s' constraints break this promise", lval); PromiseRef(LOG_LEVEL_ERR, pp); } } else { continue; } if (!(cp->rval.type == RVAL_TYPE_FNCALL || cp->rval.type == RVAL_TYPE_SCALAR)) { Log(LOG_LEVEL_ERR, "Anomalous type mismatch - type %c for bundle constraint '%s' did not match internals", cp->rval.type, lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } return true; } } return false; } static bool CheckScalarNotEmptyVarRef(const char *scalar) { return (strcmp("$()", scalar) != 0) && (strcmp("${}", scalar) != 0); } static bool PromiseCheck(const Promise *pp, Seq *errors) { bool success = true; if (!CheckScalarNotEmptyVarRef(pp->promiser)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp, POLICY_ERROR_EMPTY_VARREF)); success = false; } // check if promise's constraints are valid for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *constraint = SeqAt(pp->conlist, i); success &= ConstraintCheckSyntax(constraint, errors); } const PromiseTypeSyntax *pts = PromiseTypeSyntaxGet(pp->parent_promise_type->parent_bundle->type, pp->parent_promise_type->name); if (pts->check_promise) { success &= pts->check_promise(pp, errors); } return success; } const char *PromiseGetNamespace(const Promise *pp) { return pp->parent_promise_type->parent_bundle->ns; } const Bundle *PromiseGetBundle(const Promise *pp) { return pp->parent_promise_type->parent_bundle; } const Policy *PromiseGetPolicy(const Promise *pp) { return PromiseGetBundle(pp)->parent_policy; } static void BundlePath(Writer *w, const Bundle *bp) { WriterWriteChar(w, '/'); WriterWrite(w, bp->ns); WriterWriteChar(w, '/'); WriterWrite(w, bp->name); } static void PromiseTypePath(Writer *w, const PromiseType *pt) { BundlePath(w, pt->parent_bundle); WriterWriteChar(w, '/'); WriterWrite(w, pt->name); } void PromisePath(Writer *w, const Promise *pp) { PromiseTypePath(w, pp->parent_promise_type); WriterWriteChar(w, '/'); WriterWriteChar(w, '\''); WriterWrite(w, pp->promiser); WriterWriteChar(w, '\''); } const char *PromiseGetHandle(const Promise *pp) { return (const char *)PromiseGetImmediateRvalValue("handle", pp, RVAL_TYPE_SCALAR); } int PromiseGetConstraintAsInt(const EvalContext *ctx, const char *lval, const Promise *pp) { int retval = CF_NOINT; const Constraint *cp = PromiseGetConstraint(pp, lval); if (cp) { if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Anomalous type mismatch - expected type for int constraint %s did not match internals", lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } retval = (int) IntFromString((char *) cp->rval.item); } return retval; } /*****************************************************************************/ bool PromiseGetConstraintAsReal(const EvalContext *ctx, const char *lval, const Promise *pp, double *value_out) { const Constraint *cp = PromiseGetConstraint(pp, lval); if (cp) { if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Anomalous type mismatch - expected type for int constraint '%s' did not match internals", lval); FatalError(ctx, "Aborted"); } *value_out = DoubleFromString((char *) cp->rval.item, value_out); return true; } return false; } /*****************************************************************************/ /** * @return true if successful */ static bool Str2Mode(const char *s, mode_t *mode_out) { int a = CF_UNDEFINED; if (s == NULL) { *mode_out = (mode_t)0; return true; } sscanf(s, "%o", &a); if (a == CF_UNDEFINED) { return false; } *mode_out = (mode_t)a; return true; } mode_t PromiseGetConstraintAsOctal(const EvalContext *ctx, const char *lval, const Promise *pp) { mode_t retval = 077; // We could handle units here, like kb,b,mb const Constraint *cp = PromiseGetConstraint(pp, lval); if (cp) { if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Anomalous type mismatch - expected type for int constraint %s did not match internals", lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } if (!Str2Mode(cp->rval.item, &retval)) { Log(LOG_LEVEL_ERR, "Error reading assumed octal value '%s'", (const char *)cp->rval.item); PromiseRef(LOG_LEVEL_ERR, pp); } } return retval; } /*****************************************************************************/ #ifdef __MINGW32__ uid_t PromiseGetConstraintAsUid(const EvalContext *ctx, const char *lval, const Promise *pp) { // we use sids on windows instead return CF_SAME_OWNER; } #else /* !__MINGW32__ */ uid_t PromiseGetConstraintAsUid(const EvalContext *ctx, const char *lval, const Promise *pp) { int retval = CF_SAME_OWNER; char buffer[CF_MAXVARSIZE]; const Constraint *cp = PromiseGetConstraint(pp, lval); if (cp) { if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Anomalous type mismatch - expected type for owner constraint %s did not match internals", lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } retval = Str2Uid((char *) cp->rval.item, buffer, pp); } return retval; } #endif /* !__MINGW32__ */ /*****************************************************************************/ #ifdef __MINGW32__ gid_t PromiseGetConstraintAsGid(const EvalContext *ctx, char *lval, const Promise *pp) { // not applicable on windows: processes have no group return CF_SAME_GROUP; } #else /* !__MINGW32__ */ gid_t PromiseGetConstraintAsGid(const EvalContext *ctx, char *lval, const Promise *pp) { int retval = CF_SAME_GROUP; char buffer[CF_MAXVARSIZE]; const Constraint *cp = PromiseGetConstraint(pp, lval); if (cp) { if (cp->rval.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Anomalous type mismatch - expected type for group constraint '%s' did not match internals", lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } retval = Str2Gid((char *) cp->rval.item, buffer, pp); } return retval; } #endif /* !__MINGW32__ */ /*****************************************************************************/ // FIX: promise constrained classed? Rlist *PromiseGetConstraintAsList(const EvalContext *ctx, const char *lval, const Promise *pp) { const Constraint *cp = PromiseGetConstraint(pp, lval); if (cp) { if (cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_ERR, "Type mismatch on rhs - expected type for list constraint '%s'", lval); PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Aborted"); } return RvalRlistValue(cp->rval); } return NULL; } Constraint *PromiseGetConstraint(const Promise *pp, const char *lval) { Constraint *retval = NULL; if (!pp) { return NULL; } for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, lval) == 0) { return cp; } } return retval; } Constraint *PromiseGetImmediateConstraint(const Promise *pp, const char *lval) { if (pp == NULL) { return NULL; } for (size_t i = 0; i < SeqLength(pp->conlist); ++i) { Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, lval) == 0) { /* It would be nice to check whether the constraint we have asked for is defined in promise (not in referenced body), but there seem to be no way to do it easily. Checking for absence of classes does not work, as constrains obtain classes defined on promise itself. */ return cp; } } return NULL; } void *PromiseGetImmediateRvalValue(const char *lval, const Promise *pp, RvalType rtype) { const Constraint *constraint = PromiseGetImmediateConstraint(pp, lval); if (constraint && constraint->rval.type == rtype) { return constraint->rval.item; } else { return NULL; } } /*****************************************************************************/ void *PromiseGetConstraintAsRval(const Promise *pp, const char *lval, RvalType rtype) { const Constraint *constraint = PromiseGetConstraint(pp, lval); if (constraint && constraint->rval.type == rtype) { return constraint->rval.item; } else { return NULL; } } /*****************************************************************************/ void PromiseRecheckAllConstraints(const EvalContext *ctx, const Promise *pp) { static Item *EDIT_ANCHORS = NULL; /* GLOBAL_X */ for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); SyntaxTypeMatch err = ConstraintCheckType(cp); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { PolicyError *error = PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp, "In attribute '%s', %s", cp->lval, SyntaxTypeMatchToString(err)); char *error_str = PolicyErrorToString(error); PolicyErrorDestroy(error); Log(LOG_LEVEL_ERR, "%s", error_str); free(error_str); FatalError(ctx, "Cannot continue"); } } if (strcmp(pp->parent_promise_type->name, "insert_lines") == 0) { /* Multiple additions with same criterion will not be convergent -- but ignore for empty file baseline */ const char *sp = PromiseGetConstraintAsRval(pp, "select_line_matching", RVAL_TYPE_SCALAR); if (sp) { if (!IsExpandable(sp)) { const Item *ptr = NULL; if ((ptr = ReturnItemIn(EDIT_ANCHORS, sp))) { if (strcmp(ptr->classes, PromiseGetBundle(pp)->name) == 0) { Log(LOG_LEVEL_INFO, "insert_lines promise uses the same select_line_matching anchor '%s' as another promise. This will lead to non-convergent behaviour unless 'empty_file_before_editing' is set", sp); PromiseRef(LOG_LEVEL_INFO, pp); } } else { PrependItem(&EDIT_ANCHORS, sp, PromiseGetBundle(pp)->name); } } } } } /*****************************************************************************/ static SyntaxTypeMatch ConstraintCheckType(const Constraint *cp) { // Check class for (size_t i = 0; CF_CLASSBODY[i].lval != NULL; i++) { if (strcmp(cp->lval, CF_CLASSBODY[i].lval) == 0) { SyntaxTypeMatch err = CheckConstraintTypeMatch(cp->lval, cp->rval, CF_CLASSBODY[i].dtype, CF_CLASSBODY[i].range.validation_string, 0); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { return err; } } } if (cp->type == POLICY_ELEMENT_TYPE_PROMISE) { PromiseType *promise_type = cp->parent.promise->parent_promise_type; for (size_t i = 0; i < CF3_MODULES; i++) { const PromiseTypeSyntax *ssp = CF_ALL_PROMISE_TYPES[i]; if (!ssp) { continue; } for (size_t j = 0; ssp[j].bundle_type != NULL; j++) { PromiseTypeSyntax ss = ssp[j]; if (ss.promise_type != NULL) { if (strcmp(ss.promise_type, promise_type->name) == 0) { const ConstraintSyntax *bs = ss.constraints; for (size_t l = 0; bs[l].lval != NULL; l++) { if (bs[l].dtype == CF_DATA_TYPE_BUNDLE) { } else if (bs[l].dtype == CF_DATA_TYPE_BODY) { const ConstraintSyntax *bs2 = bs[l].range.body_type_syntax->constraints; for (size_t m = 0; bs2[m].lval != NULL; m++) { if (strcmp(cp->lval, bs2[m].lval) == 0) { return CheckConstraintTypeMatch(cp->lval, cp->rval, bs2[m].dtype, bs2[m].range.validation_string, 0); } } } if (strcmp(cp->lval, bs[l].lval) == 0) { return CheckConstraintTypeMatch(cp->lval, cp->rval, bs[l].dtype, bs[l].range.validation_string, 0); } } } } } } } /* Now check the functional modules - extra level of indirection */ for (size_t i = 0; CF_COMMON_BODIES[i].lval != NULL; i++) { if (CF_COMMON_BODIES[i].dtype == CF_DATA_TYPE_BODY) { continue; } if (strcmp(cp->lval, CF_COMMON_BODIES[i].lval) == 0) { return CheckConstraintTypeMatch(cp->lval, cp->rval, CF_COMMON_BODIES[i].dtype, CF_COMMON_BODIES[i].range.validation_string, 0); } } return SYNTAX_TYPE_MATCH_OK; } /* FIXME: need to be done automatically */ bool BundleTypeCheck(const char *name) { /* FIXME: export size of CF_AGENTTYPES somewhere */ for (int i = 0; strcmp(CF_AGENTTYPES[i], "") != 0; ++i) { if (!strcmp(CF_AGENTTYPES[i], name)) { return true; } } if (!strcmp("knowledge", name)) { return true; } if (!strcmp("edit_line", name)) { return true; } if (!strcmp("edit_xml", name)) { return true; } return false; } cfengine-3.6.2/libpromises/eval_context.c0000664000175100017510000021254212411001073020200 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static bool BundleAborted(const EvalContext *ctx); static void SetBundleAborted(EvalContext *ctx); static bool EvalContextStackFrameContainsSoft(const EvalContext *ctx, const char *context); static bool EvalContextHeapContainsSoft(const EvalContext *ctx, const char *ns, const char *name); static bool EvalContextHeapContainsHard(const EvalContext *ctx, const char *name); static bool EvalContextClassPut(EvalContext *ctx, const char *ns, const char *name, bool is_soft, ContextScope scope, const char *tags); static const char *EvalContextCurrentNamespace(const EvalContext *ctx); static ClassRef IDRefQualify(const EvalContext *ctx, const char *id); struct EvalContext_ { int eval_options; bool bundle_aborted; bool checksum_updates_default; Item *ip_addresses; bool ignore_locks; Item *heap_abort; Item *heap_abort_current_bundle; Seq *stack; ClassTable *global_classes; VariableTable *global_variables; VariableTable *match_variables; StringSet *promise_lock_cache; StringSet *dependency_handles; RBTree *function_cache; uid_t uid; uid_t gid; pid_t pid; pid_t ppid; // Full path to directory that the binary was launched from. char *launch_directory; }; static StackFrame *LastStackFrame(const EvalContext *ctx, size_t offset) { if (SeqLength(ctx->stack) <= offset) { return NULL; } return SeqAt(ctx->stack, SeqLength(ctx->stack) - 1 - offset); } static StackFrame *LastStackFrameByType(const EvalContext *ctx, StackFrameType type) { for (size_t i = 0; i < SeqLength(ctx->stack); i++) { StackFrame *frame = LastStackFrame(ctx, i); if (frame->type == type) { return frame; } } return NULL; } static LogLevel AdjustLogLevel(LogLevel base, LogLevel adjust) { if (adjust == -1) { return base; } else { return MAX(base, adjust); } } static LogLevel StringToLogLevel(const char *value) { if (value) { if (!strcmp(value, "verbose")) { return LOG_LEVEL_VERBOSE; } if (!strcmp(value, "inform")) { return LOG_LEVEL_INFO; } if (!strcmp(value, "error")) { return LOG_LEVEL_NOTICE; /* Error level includes warnings and notices */ } } return -1; } static LogLevel GetLevelForPromise(const Promise *pp, const char *attr_name) { return StringToLogLevel(PromiseGetConstraintAsRval(pp, attr_name, RVAL_TYPE_SCALAR)); } static LogLevel CalculateLogLevel(const Promise *pp) { LogLevel log_level = LogGetGlobalLevel(); if (pp) { log_level = AdjustLogLevel(log_level, GetLevelForPromise(pp, "log_level")); } /* Disable system log for dry-runs */ if (DONTDO) { log_level = LOG_LEVEL_NOTHING; } return log_level; } static LogLevel CalculateReportLevel(const Promise *pp) { LogLevel report_level = LogGetGlobalLevel(); if (pp) { report_level = AdjustLogLevel(report_level, GetLevelForPromise(pp, "report_level")); } return report_level; } static char *LogHook(LoggingPrivContext *pctx, LogLevel level, const char *message) { const EvalContext *ctx = pctx->param; StackFrame *last_frame = LastStackFrame(ctx, 0); if (last_frame) { if (last_frame->type == STACK_FRAME_TYPE_PROMISE_ITERATION) { if (level <= LOG_LEVEL_INFO) { RingBufferAppend(last_frame->data.promise_iteration.log_messages, xstrdup(message)); } } return StringConcatenate(3, last_frame->path, ": ", message); } else { return xstrdup(message); } } static const char *GetAgentAbortingContext(const EvalContext *ctx) { for (const Item *ip = ctx->heap_abort; ip != NULL; ip = ip->next) { if (IsDefinedClass(ctx, ip->classes)) { const char *regex = ip->name; Class *cls = EvalContextClassMatch(ctx, regex); if (cls) { return regex; } } } return NULL; } static void EvalContextStackFrameAddSoft(EvalContext *ctx, const char *context, const char *tags) { assert(SeqLength(ctx->stack) > 0); StackFrameBundle frame; { StackFrame *last_frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); if (!last_frame) { ProgrammingError("Attempted to add a soft class on the stack, but stack had no bundle frame"); } frame = last_frame->data.bundle; } char copy[CF_BUFSIZE]; if (strcmp(frame.owner->ns, "default") != 0) { snprintf(copy, CF_MAXVARSIZE, "%s:%s", frame.owner->ns, context); } else { strlcpy(copy, context, CF_MAXVARSIZE); } if (Chop(copy, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } if (strlen(copy) == 0) { return; } if (EvalContextHeapContainsSoft(ctx, frame.owner->ns, context)) { Log(LOG_LEVEL_WARNING, "Private class '%s' in bundle '%s' shadows a global class - you should choose a different name to avoid conflicts", copy, frame.owner->name); } if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, copy)) { Log(LOG_LEVEL_ERR, "Bundle aborted on defined class '%s'", copy); SetBundleAborted(ctx); } if (IsRegexItemIn(ctx, ctx->heap_abort, copy)) { FatalError(ctx, "cf-agent aborted on defined class '%s'", copy); } if (EvalContextStackFrameContainsSoft(ctx, copy)) { return; } ClassTablePut(frame.classes, frame.owner->ns, context, true, CONTEXT_SCOPE_BUNDLE, tags); if (!BundleAborted(ctx)) { for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next) { if (IsDefinedClass(ctx, ip->name)) { Log(LOG_LEVEL_ERR, "Setting abort for '%s' when setting '%s'", ip->name, context); SetBundleAborted(ctx); break; } } } } static ExpressionValue EvalTokenAsClass(const char *classname, void *param) { const EvalContext *ctx = param; ClassRef ref = ClassRefParse(classname); if (ClassRefIsQualified(ref)) { if (strcmp(ref.ns, NamespaceDefault()) == 0) { if (EvalContextHeapContainsHard(ctx, ref.name)) { ClassRefDestroy(ref); return true; } } } else { if (EvalContextHeapContainsHard(ctx, ref.name)) { ClassRefDestroy(ref); return true; } const char *ns = EvalContextCurrentNamespace(ctx); if (ns) { ClassRefQualify(&ref, ns); } else { ClassRefQualify(&ref, NamespaceDefault()); } } assert(ClassRefIsQualified(ref)); bool classy = (strcmp("any", ref.name) == 0 || EvalContextHeapContainsSoft(ctx, ref.ns, ref.name) || EvalContextStackFrameContainsSoft(ctx, ref.name)); ClassRefDestroy(ref); return classy; /* ExpressionValue is just an enum extending bool... */ } /**********************************************************************/ static char *EvalVarRef(ARG_UNUSED const char *varname, ARG_UNUSED VarRefType type, ARG_UNUSED void *param) { /* * There should be no unexpanded variables when we evaluate any kind of * logic expressions, until parsing of logic expression changes and they are * not pre-expanded before evaluation. */ return NULL; } /**********************************************************************/ bool IsDefinedClass(const EvalContext *ctx, const char *context) { ParseResult res; if (!context) { return true; } res = ParseExpression(context, 0, strlen(context)); if (!res.result) { Log(LOG_LEVEL_ERR, "Unable to parse class expression '%s'", context); return false; } else { ExpressionValue r = EvalExpression(res.result, &EvalTokenAsClass, &EvalVarRef, (void *)ctx); // controlled cast. None of these should modify EvalContext FreeExpression(res.result); /* r is EvalResult which could be ERROR */ return r == true; } } /**********************************************************************/ static ExpressionValue EvalTokenFromList(const char *token, void *param) { StringSet *set = param; return StringSetContains(set, token); } /**********************************************************************/ static bool EvalWithTokenFromList(const char *expr, StringSet *token_set) { ParseResult res = ParseExpression(expr, 0, strlen(expr)); if (!res.result) { Log(LOG_LEVEL_ERR, "Syntax error in expression '%s'", expr); return false; /* FIXME: return error */ } else { ExpressionValue r = EvalExpression(res.result, &EvalTokenFromList, &EvalVarRef, token_set); FreeExpression(res.result); /* r is EvalResult which could be ERROR */ return r == true; } } /**********************************************************************/ /* Process result expression */ bool EvalProcessResult(const char *process_result, StringSet *proc_attr) { return EvalWithTokenFromList(process_result, proc_attr); } /**********************************************************************/ /* File result expressions */ bool EvalFileResult(const char *file_result, StringSet *leaf_attr) { return EvalWithTokenFromList(file_result, leaf_attr); } /*****************************************************************************/ void EvalContextHeapPersistentSave(EvalContext *ctx, const char *name, unsigned int ttl_minutes, PersistentClassPolicy policy, const char *tags) { assert(tags); time_t now = time(NULL); CF_DB *dbp; if (!OpenDB(&dbp, dbid_state)) { char *db_path = DBIdToPath(GetWorkDir(), dbid_state); Log(LOG_LEVEL_ERR, "While persisting class, unable to open database at '%s' (OpenDB: %s)", db_path, GetErrorStr()); free(db_path); return; } ClassRef ref = IDRefQualify(ctx, name); char *key = ClassRefToString(ref.ns, ref.name); ClassRefDestroy(ref); size_t tags_length = strlen(tags) + 1; size_t new_info_size = sizeof(PersistentClassInfo) + tags_length; PersistentClassInfo *new_info = xcalloc(1, new_info_size); new_info->expires = now + ttl_minutes * 60; new_info->policy = policy; strlcpy(new_info->tags, tags, tags_length); // first see if we have an existing record, and if we should bother to update { int existing_info_size = ValueSizeDB(dbp, key, strlen(key)); if (existing_info_size > 0) { PersistentClassInfo *existing_info = xcalloc(existing_info_size, 1); if (ReadDB(dbp, key, existing_info, existing_info_size)) { if (existing_info->policy == CONTEXT_STATE_POLICY_PRESERVE && now < existing_info->expires && strcmp(existing_info->tags, new_info->tags) == 0) { Log(LOG_LEVEL_VERBOSE, "Persisent class '%s' is already in a preserved state -- %jd minutes to go", key, (intmax_t)((existing_info->expires - now) / 60)); CloseDB(dbp); free(key); free(new_info); return; } } else { Log(LOG_LEVEL_ERR, "While persisting class '%s', error reading existing value", key); CloseDB(dbp); free(key); free(new_info); return; } } } Log(LOG_LEVEL_VERBOSE, "Updating persistent class '%s'", key); WriteDB(dbp, key, new_info, new_info_size); CloseDB(dbp); free(key); free(new_info); } /*****************************************************************************/ void EvalContextHeapPersistentRemove(const char *context) { CF_DB *dbp; if (!OpenDB(&dbp, dbid_state)) { return; } DeleteDB(dbp, context); Log(LOG_LEVEL_DEBUG, "Deleted persistent class '%s'", context); CloseDB(dbp); } /*****************************************************************************/ void EvalContextHeapPersistentLoadAll(EvalContext *ctx) { time_t now = time(NULL); Banner("Loading persistent classes"); CF_DB *dbp; if (!OpenDB(&dbp, dbid_state)) { return; } CF_DBC *dbcp; if (!NewDBCursor(dbp, &dbcp)) { Log(LOG_LEVEL_INFO, "Unable to scan persistence cache"); return; } const char *key; int key_size = 0; void *info_p; int info_size = 0; while (NextDB(dbcp, (char **)&key, &key_size, &info_p, &info_size)) { Log(LOG_LEVEL_DEBUG, "Found key persistent class key '%s'", key); /* Info points to db-owned data, which is not aligned properly and * dereferencing might be slow or even cause SIGBUS! */ PersistentClassInfo info = { 0 }; memcpy(&info, info_p, info_size < sizeof(info) ? info_size : sizeof(info)); const char *tags = NULL; if (info_size > sizeof(PersistentClassInfo)) { /* This is char pointer, it can point to unaligned data. */ tags = ((PersistentClassInfo *) info_p)->tags; } if (now > info.expires) { Log(LOG_LEVEL_VERBOSE, "Persistent class '%s' expired", key); DBCursorDeleteEntry(dbcp); } else { Log(LOG_LEVEL_VERBOSE, "Persistent class '%s' for %jd more minutes", key, (intmax_t) ((info.expires - now) / 60)); Log(LOG_LEVEL_VERBOSE, "Adding persistent class '%s' to heap", key); ClassRef ref = ClassRefParse(key); EvalContextClassPut(ctx, ref.ns, ref.name, true, CONTEXT_SCOPE_NAMESPACE, tags); StringSet *tag_set = EvalContextClassTags(ctx, ref.ns, ref.name); assert(tag_set); StringSetAdd(tag_set, xstrdup("source=persistent")); ClassRefDestroy(ref); } } DeleteDBCursor(dbcp); CloseDB(dbp); Banner("Loaded persistent memory"); } bool Abort(EvalContext *ctx) { if (ctx->bundle_aborted) { ctx->bundle_aborted = false; return true; } return false; } bool BundleAborted(const EvalContext* ctx) { return ctx->bundle_aborted; } void SetBundleAborted(EvalContext *ctx) { ctx->bundle_aborted = true; } bool VarClassExcluded(const EvalContext *ctx, const Promise *pp, char **classes) { Constraint *cp = PromiseGetConstraint(pp, "ifvarclass"); if (!cp) { return false; } if (cp->rval.type == RVAL_TYPE_FNCALL) { return false; } *classes = PromiseGetConstraintAsRval(pp, "ifvarclass", RVAL_TYPE_SCALAR); if (*classes == NULL) { return true; } if (strchr(*classes, '$') || strchr(*classes, '@')) { Log(LOG_LEVEL_DEBUG, "Class expression did not evaluate"); return true; } if (*classes && IsDefinedClass(ctx, *classes)) { return false; } else { return true; } } bool EvalContextPromiseIsActive(const EvalContext *ctx, const Promise *pp) { if (!IsDefinedClass(ctx, pp->classes)) { return false; } else { char *classes = NULL; if (VarClassExcluded(ctx, pp, &classes)) { return false; } } return true; } void EvalContextHeapAddAbort(EvalContext *ctx, const char *context, const char *activated_on_context) { if (!IsItemIn(ctx->heap_abort, context)) { AppendItem(&ctx->heap_abort, context, activated_on_context); } if (GetAgentAbortingContext(ctx)) { FatalError(ctx, "cf-agent aborted on context '%s'", GetAgentAbortingContext(ctx)); } } void EvalContextHeapAddAbortCurrentBundle(EvalContext *ctx, const char *context, const char *activated_on_context) { if (!IsItemIn(ctx->heap_abort_current_bundle, context)) { AppendItem(&ctx->heap_abort_current_bundle, context, activated_on_context); } } /*****************************************************************************/ bool MissingDependencies(EvalContext *ctx, const Promise *pp) { const Rlist *dependenies = PromiseGetConstraintAsList(ctx, "depends_on", pp); if (RlistIsNullList(dependenies)) { return false; } for (const Rlist *rp = PromiseGetConstraintAsList(ctx, "depends_on", pp); rp; rp = rp->next) { if (rp->val.type != RVAL_TYPE_SCALAR) { return true; } if (!StringSetContains(ctx->dependency_handles, RlistScalarValue(rp))) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); Log(LOG_LEVEL_VERBOSE, "Skipping whole next promise (%s), as promise dependency %s has not yet been kept", pp->promiser, RlistScalarValue(rp)); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); } else { Log(LOG_LEVEL_VERBOSE, "Skipping next promise '%s', as promise dependency '%s' has not yet been kept", pp->promiser, RlistScalarValue(rp)); } return true; } } return false; } static void StackFrameBundleDestroy(StackFrameBundle frame) { ClassTableDestroy(frame.classes); VariableTableDestroy(frame.vars); } static void StackFrameBodyDestroy(ARG_UNUSED StackFrameBody frame) { VariableTableDestroy(frame.vars); } static void StackFramePromiseDestroy(StackFramePromise frame) { VariableTableDestroy(frame.vars); } static void StackFramePromiseIterationDestroy(StackFramePromiseIteration frame) { PromiseDestroy(frame.owner); RingBufferDestroy(frame.log_messages); } static void StackFrameDestroy(StackFrame *frame) { if (frame) { switch (frame->type) { case STACK_FRAME_TYPE_BUNDLE: StackFrameBundleDestroy(frame->data.bundle); break; case STACK_FRAME_TYPE_BODY: StackFrameBodyDestroy(frame->data.body); break; case STACK_FRAME_TYPE_PROMISE_TYPE: break; case STACK_FRAME_TYPE_PROMISE: StackFramePromiseDestroy(frame->data.promise); break; case STACK_FRAME_TYPE_PROMISE_ITERATION: StackFramePromiseIterationDestroy(frame->data.promise_iteration); break; default: ProgrammingError("Unhandled stack frame type"); } free(frame->path); free(frame); } } EvalContext *EvalContextNew(void) { EvalContext *ctx = xmalloc(sizeof(EvalContext)); ctx->eval_options = EVAL_OPTION_FULL; ctx->bundle_aborted = false; ctx->checksum_updates_default = false; ctx->ip_addresses = NULL; ctx->ignore_locks = false; ctx->heap_abort = NULL; ctx->heap_abort_current_bundle = NULL; ctx->stack = SeqNew(10, StackFrameDestroy); ctx->global_classes = ClassTableNew(); ctx->global_variables = VariableTableNew(); ctx->match_variables = VariableTableNew(); ctx->dependency_handles = StringSetNew(); ctx->uid = getuid(); ctx->gid = getgid(); ctx->pid = getpid(); #ifdef __MINGW32__ ctx->ppid = 0; #else ctx->ppid = getppid(); #endif ctx->promise_lock_cache = StringSetNew(); ctx->function_cache = RBTreeNew(NULL, NULL, NULL, NULL, NULL, NULL); { LoggingPrivContext *pctx = LoggingPrivGetContext(); assert(!pctx && "Logging context bound to something else"); pctx = xcalloc(1, sizeof(LoggingPrivContext)); pctx->param = ctx; pctx->log_hook = &LogHook; LoggingPrivSetContext(pctx); } ctx->launch_directory = NULL; return ctx; } void EvalContextDestroy(EvalContext *ctx) { if (ctx) { free(ctx->launch_directory); { LoggingPrivContext *pctx = LoggingPrivGetContext(); free(pctx); LoggingPrivSetContext(NULL); } EvalContextDeleteIpAddresses(ctx); DeleteItemList(ctx->heap_abort); DeleteItemList(ctx->heap_abort_current_bundle); SeqDestroy(ctx->stack); ClassTableDestroy(ctx->global_classes); VariableTableDestroy(ctx->global_variables); VariableTableDestroy(ctx->match_variables); StringSetDestroy(ctx->dependency_handles); StringSetDestroy(ctx->promise_lock_cache); { RBTreeIterator *it = RBTreeIteratorNew(ctx->function_cache); Rval *rval = NULL; while (RBTreeIteratorNext(it, NULL, (void **)&rval)) { RvalDestroy(*rval); free(rval); } RBTreeIteratorDestroy(it); RBTreeDestroy(ctx->function_cache); } free(ctx); } } static bool EvalContextHeapContainsSoft(const EvalContext *ctx, const char *ns, const char *name) { const Class *cls = ClassTableGet(ctx->global_classes, ns, name); return cls && cls->is_soft; } static bool EvalContextHeapContainsHard(const EvalContext *ctx, const char *name) { const Class *cls = ClassTableGet(ctx->global_classes, NULL, name); return cls && !cls->is_soft; } bool StackFrameContainsSoftRecursive(const EvalContext *ctx, const char *context, size_t stack_index) { StackFrame *frame = SeqAt(ctx->stack, stack_index); if (frame->type == STACK_FRAME_TYPE_BUNDLE && ClassTableGet(frame->data.bundle.classes, frame->data.bundle.owner->ns, context) != NULL) { return true; } else if (stack_index > 0 && frame->inherits_previous) { return StackFrameContainsSoftRecursive(ctx, context, stack_index - 1); } else { return false; } } static bool EvalContextStackFrameContainsSoft(const EvalContext *ctx, const char *context) { if (SeqLength(ctx->stack) == 0) { return false; } size_t stack_index = SeqLength(ctx->stack) - 1; return StackFrameContainsSoftRecursive(ctx, context, stack_index); } bool EvalContextHeapRemoveSoft(EvalContext *ctx, const char *ns, const char *name) { return ClassTableRemove(ctx->global_classes, ns, name); } bool EvalContextHeapRemoveHard(EvalContext *ctx, const char *name) { return ClassTableRemove(ctx->global_classes, NULL, name); } void EvalContextClear(EvalContext *ctx) { ClassTableClear(ctx->global_classes); EvalContextDeleteIpAddresses(ctx); VariableTableClear(ctx->global_variables, NULL, NULL, NULL); VariableTableClear(ctx->match_variables, NULL, NULL, NULL); StringSetClear(ctx->promise_lock_cache); SeqClear(ctx->stack); { RBTreeIterator *it = RBTreeIteratorNew(ctx->function_cache); Rval *rval = NULL; while (RBTreeIteratorNext(it, NULL, (void **)&rval)) { RvalDestroy(*rval); free(rval); } RBTreeIteratorDestroy(it); RBTreeClear(ctx->function_cache); } } static StackFrame *StackFrameNew(StackFrameType type, bool inherit_previous) { StackFrame *frame = xmalloc(sizeof(StackFrame)); frame->type = type; frame->inherits_previous = inherit_previous; frame->path = NULL; return frame; } static StackFrame *StackFrameNewBundle(const Bundle *owner, bool inherit_previous) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_BUNDLE, inherit_previous); frame->data.bundle.owner = owner; frame->data.bundle.classes = ClassTableNew(); frame->data.bundle.vars = VariableTableNew(); return frame; } static StackFrame *StackFrameNewBody(const Body *owner) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_BODY, false); frame->data.body.owner = owner; frame->data.body.vars = VariableTableNew(); return frame; } static StackFrame *StackFrameNewPromiseType(const PromiseType *owner) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_PROMISE_TYPE, true); frame->data.promise_type.owner = owner; return frame; } static StackFrame *StackFrameNewPromise(const Promise *owner) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_PROMISE, true); frame->data.promise.owner = owner; return frame; } static StackFrame *StackFrameNewPromiseIteration(Promise *owner, const PromiseIterator *iter_ctx, unsigned index) { StackFrame *frame = StackFrameNew(STACK_FRAME_TYPE_PROMISE_ITERATION, true); frame->data.promise_iteration.owner = owner; frame->data.promise_iteration.iter_ctx = iter_ctx; frame->data.promise_iteration.index = index; frame->data.promise_iteration.log_messages = RingBufferNew(5, NULL, free); return frame; } void EvalContextStackFrameRemoveSoft(EvalContext *ctx, const char *context) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); assert(frame); ClassTableRemove(frame->data.bundle.classes, frame->data.bundle.owner->ns, context); } static void EvalContextStackPushFrame(EvalContext *ctx, StackFrame *frame) { StackFrame *last_frame = LastStackFrame(ctx, 0); if (last_frame) { if (last_frame->type == STACK_FRAME_TYPE_PROMISE_ITERATION) { LoggingPrivSetLevels(LogGetGlobalLevel(), LogGetGlobalLevel()); } } SeqAppend(ctx->stack, frame); assert(!frame->path); frame->path = EvalContextStackPath(ctx); } void EvalContextStackPushBundleFrame(EvalContext *ctx, const Bundle *owner, const Rlist *args, bool inherits_previous) { assert(!LastStackFrame(ctx, 0) || LastStackFrame(ctx, 0)->type == STACK_FRAME_TYPE_PROMISE_ITERATION); EvalContextStackPushFrame(ctx, StackFrameNewBundle(owner, inherits_previous)); if (RlistLen(args) > 0) { const Promise *caller = EvalContextStackCurrentPromise(ctx); if (caller) { VariableTable *table = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE)->data.bundle.vars; VariableTableClear(table, NULL, NULL, NULL); } ScopeAugment(ctx, owner, caller, args); } { VariableTableIterator *iter = VariableTableIteratorNew(ctx->global_variables, owner->ns, owner->name, NULL); Variable *var = NULL; while ((var = VariableTableIteratorNext(iter))) { Rval retval = ExpandPrivateRval(ctx, owner->ns, owner->name, var->rval.item, var->rval.type); RvalDestroy(var->rval); var->rval = retval; } VariableTableIteratorDestroy(iter); } } void EvalContextStackPushBodyFrame(EvalContext *ctx, const Promise *caller, const Body *body, const Rlist *args) { #ifndef NDEBUG StackFrame *last_frame = LastStackFrame(ctx, 0); if (last_frame) { assert(last_frame->type == STACK_FRAME_TYPE_PROMISE_TYPE); } else { assert(strcmp("control", body->name) == 0); } #endif EvalContextStackPushFrame(ctx, StackFrameNewBody(body)); if (RlistLen(body->args) != RlistLen(args)) { if (caller) { Log(LOG_LEVEL_ERR, "Argument arity mismatch in body '%s' at line %zu in file '%s', expected %d, got %d", body->name, caller->offset.line, PromiseGetBundle(caller)->source_path, RlistLen(body->args), RlistLen(args)); } else { assert(strcmp("control", body->name) == 0); ProgrammingError("Control body stack frame was pushed with arguments. This should have been caught before"); } return; } else { ScopeMapBodyArgs(ctx, body, args); } } void EvalContextStackPushPromiseTypeFrame(EvalContext *ctx, const PromiseType *owner) { assert(LastStackFrame(ctx, 0) && LastStackFrame(ctx, 0)->type == STACK_FRAME_TYPE_BUNDLE); StackFrame *frame = StackFrameNewPromiseType(owner); EvalContextStackPushFrame(ctx, frame); } void EvalContextStackPushPromiseFrame(EvalContext *ctx, const Promise *owner, bool copy_bundle_context) { assert(LastStackFrame(ctx, 0)); assert(LastStackFrame(ctx, 0)->type == STACK_FRAME_TYPE_PROMISE_TYPE); EvalContextVariableClearMatch(ctx); StackFrame *frame = StackFrameNewPromise(owner); EvalContextStackPushFrame(ctx, frame); if (copy_bundle_context) { frame->data.promise.vars = VariableTableCopyLocalized(ctx->global_variables, EvalContextStackCurrentBundle(ctx)->ns, EvalContextStackCurrentBundle(ctx)->name); } else { frame->data.promise.vars = VariableTableNew(); } if (PromiseGetBundle(owner)->source_path) { char path[CF_BUFSIZE]; if (!IsAbsoluteFileName(PromiseGetBundle(owner)->source_path) && ctx->launch_directory) { snprintf(path, CF_BUFSIZE, "%s%c%s", ctx->launch_directory, FILE_SEPARATOR, PromiseGetBundle(owner)->source_path); } else { strlcpy(path, PromiseGetBundle(owner)->source_path, CF_BUFSIZE); } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_filename", path, CF_DATA_TYPE_STRING, "source=promise"); // We now make path just the directory name! DeleteSlash(path); ChopLastNode(path); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_dirname", path, CF_DATA_TYPE_STRING, "source=promise"); char number[PRINTSIZE(uintmax_t)]; xsnprintf(number, CF_SMALLBUF, "%ju", (uintmax_t) owner->offset.line); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promise_linenumber", number, CF_DATA_TYPE_STRING, "source=promise"); } char v[PRINTSIZE(int)]; xsnprintf(v, sizeof(v), "%d", (int) ctx->uid); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_uid", v, CF_DATA_TYPE_INT, "source=agent"); xsnprintf(v, sizeof(v), "%d", (int) ctx->gid); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_gid", v, CF_DATA_TYPE_INT, "source=agent"); xsnprintf(v, sizeof(v), "%d", (int) ctx->pid); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_pid", v, CF_DATA_TYPE_INT, "source=agent"); xsnprintf(v, sizeof(v), "%d", (int) ctx->ppid); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser_ppid", v, CF_DATA_TYPE_INT, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "bundle", PromiseGetBundle(owner)->name, CF_DATA_TYPE_STRING, "source=promise"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "namespace", PromiseGetNamespace(owner), CF_DATA_TYPE_STRING, "source=promise"); } Promise *EvalContextStackPushPromiseIterationFrame(EvalContext *ctx, size_t iteration_index, const PromiseIterator *iter_ctx) { assert(LastStackFrame(ctx, 0) && LastStackFrame(ctx, 0)->type == STACK_FRAME_TYPE_PROMISE); if (iter_ctx) { PromiseIteratorUpdateVariable(ctx, iter_ctx); } bool excluded = false; Promise *pexp = ExpandDeRefPromise(ctx, LastStackFrame(ctx, 0)->data.promise.owner, &excluded); if (excluded) { PromiseDestroy(pexp); return NULL; } EvalContextStackPushFrame(ctx, StackFrameNewPromiseIteration(pexp, iter_ctx, iteration_index)); LoggingPrivSetLevels(CalculateLogLevel(pexp), CalculateReportLevel(pexp)); return pexp; } void EvalContextStackPopFrame(EvalContext *ctx) { assert(SeqLength(ctx->stack) > 0); StackFrame *last_frame = LastStackFrame(ctx, 0); StackFrameType last_frame_type = last_frame->type; switch (last_frame_type) { case STACK_FRAME_TYPE_BUNDLE: { const Bundle *bp = last_frame->data.bundle.owner; if (strcmp(bp->type, "edit_line") == 0 || strcmp(bp->type, "edit_xml") == 0) { VariableTableClear(last_frame->data.bundle.vars, "default", "edit", NULL); } } break; case STACK_FRAME_TYPE_PROMISE_ITERATION: LoggingPrivSetLevels(LogGetGlobalLevel(), LogGetGlobalLevel()); break; default: break; } SeqRemove(ctx->stack, SeqLength(ctx->stack) - 1); last_frame = LastStackFrame(ctx, 0); if (last_frame) { if (last_frame->type == STACK_FRAME_TYPE_PROMISE_ITERATION) { const Promise *pp = EvalContextStackCurrentPromise(ctx); LoggingPrivSetLevels(CalculateLogLevel(pp), CalculateReportLevel(pp)); } } } bool EvalContextClassRemove(EvalContext *ctx, const char *ns, const char *name) { for (size_t i = 0; i < SeqLength(ctx->stack); i++) { StackFrame *frame = SeqAt(ctx->stack, i); if (frame->type != STACK_FRAME_TYPE_BUNDLE) { continue; } ClassTableRemove(frame->data.bundle.classes, ns, name); } return ClassTableRemove(ctx->global_classes, ns, name); } Class *EvalContextClassGet(const EvalContext *ctx, const char *ns, const char *name) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); if (frame) { Class *cls = ClassTableGet(frame->data.bundle.classes, ns, name); if (cls) { return cls; } } return ClassTableGet(ctx->global_classes, ns, name); } Class *EvalContextClassMatch(const EvalContext *ctx, const char *regex) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); if (frame) { Class *cls = ClassTableMatch(frame->data.bundle.classes, regex); if (cls) { return cls; } } return ClassTableMatch(ctx->global_classes, regex); } static bool EvalContextClassPut(EvalContext *ctx, const char *ns, const char *name, bool is_soft, ContextScope scope, const char *tags) { { char context_copy[CF_MAXVARSIZE]; char canonified_context[CF_MAXVARSIZE]; strcpy(canonified_context, name); if (Chop(canonified_context, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } CanonifyNameInPlace(canonified_context); if (ns && strcmp(ns, "default") != 0) { snprintf(context_copy, CF_MAXVARSIZE, "%s:%s", ns, canonified_context); } else { strlcpy(context_copy, canonified_context, CF_MAXVARSIZE); } if (strlen(context_copy) == 0) { return false; } if (IsRegexItemIn(ctx, ctx->heap_abort_current_bundle, context_copy)) { Log(LOG_LEVEL_ERR, "Bundle aborted on defined class '%s'", context_copy); SetBundleAborted(ctx); } if (IsRegexItemIn(ctx, ctx->heap_abort, context_copy)) { FatalError(ctx, "cf-agent aborted on defined class '%s'", context_copy); } } Class *existing_class = EvalContextClassGet(ctx, ns, name); if (existing_class && existing_class->scope == scope) { return false; } switch (scope) { case CONTEXT_SCOPE_BUNDLE: { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); if (!frame) { ProgrammingError("Attempted to add bundle class '%s' while not evaluating a bundle", name); } ClassTablePut(frame->data.bundle.classes, ns, name, is_soft, scope, tags); } break; case CONTEXT_SCOPE_NAMESPACE: ClassTablePut(ctx->global_classes, ns, name, is_soft, scope, tags); break; case CONTEXT_SCOPE_NONE: ProgrammingError("Attempted to add a class without a set scope"); } if (!BundleAborted(ctx)) { for (const Item *ip = ctx->heap_abort_current_bundle; ip != NULL; ip = ip->next) { const char *class_expr = ip->name; if (IsDefinedClass(ctx, class_expr)) { Log(LOG_LEVEL_ERR, "Setting abort for '%s' when setting class '%s'", ip->name, name); SetBundleAborted(ctx); break; } } } return true; } static const char *EvalContextCurrentNamespace(const EvalContext *ctx) { size_t i = SeqLength(ctx->stack); while (i > 0) { i--; StackFrame *frame = SeqAt(ctx->stack, i); switch (frame->type) { case STACK_FRAME_TYPE_BUNDLE: return frame->data.bundle.owner->ns; case STACK_FRAME_TYPE_BODY: return frame->data.body.owner->ns; default: break; /* out of the switch but not the loop ! */ } } return NULL; } bool EvalContextClassPutHard(EvalContext *ctx, const char *name, const char *tags) { return EvalContextClassPut(ctx, NULL, name, false, CONTEXT_SCOPE_NAMESPACE, tags); } bool EvalContextClassPutSoft(EvalContext *ctx, const char *name, ContextScope scope, const char *tags) { return EvalContextClassPut(ctx, EvalContextCurrentNamespace(ctx), name, true, scope, tags); } ClassTableIterator *EvalContextClassTableIteratorNewGlobal(const EvalContext *ctx, const char *ns, bool is_hard, bool is_soft) { return ClassTableIteratorNew(ctx->global_classes, ns, is_hard, is_soft); } ClassTableIterator *EvalContextClassTableIteratorNewLocal(const EvalContext *ctx) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); if (!frame) { return NULL; } return ClassTableIteratorNew(frame->data.bundle.classes, frame->data.bundle.owner->ns, false, true); } const Promise *EvalContextStackCurrentPromise(const EvalContext *ctx) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_PROMISE_ITERATION); return frame ? frame->data.promise_iteration.owner : NULL; } const Bundle *EvalContextStackCurrentBundle(const EvalContext *ctx) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); return frame ? frame->data.bundle.owner : NULL; } const RingBuffer *EvalContextStackCurrentMessages(const EvalContext *ctx) { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_PROMISE_ITERATION); return frame ? frame->data.promise_iteration.log_messages : NULL; } char *EvalContextStackPath(const EvalContext *ctx) { Buffer *path = BufferNew(); for (size_t i = 0; i < SeqLength(ctx->stack); i++) { StackFrame *frame = SeqAt(ctx->stack, i); switch (frame->type) { case STACK_FRAME_TYPE_BODY: BufferAppendChar(path, '/'); BufferAppend(path, frame->data.body.owner->name, CF_BUFSIZE); break; case STACK_FRAME_TYPE_BUNDLE: BufferAppendChar(path, '/'); BufferAppend(path, frame->data.bundle.owner->ns, CF_BUFSIZE); BufferAppendChar(path, '/'); BufferAppend(path, frame->data.bundle.owner->name, CF_BUFSIZE); break; case STACK_FRAME_TYPE_PROMISE_TYPE: BufferAppendChar(path, '/'); BufferAppend(path, frame->data.promise_type.owner->name, CF_BUFSIZE); case STACK_FRAME_TYPE_PROMISE: break; case STACK_FRAME_TYPE_PROMISE_ITERATION: BufferAppendChar(path, '/'); BufferAppendChar(path, '\''); for (const char *ch = frame->data.promise_iteration.owner->promiser; *ch != '\0'; ch++) { switch (*ch) { case '*': BufferAppendChar(path, ':'); break; case '#': BufferAppendChar(path, '.'); break; default: BufferAppendChar(path, *ch); break; } } BufferAppendChar(path, '\''); if (i == SeqLength(ctx->stack) - 1) { BufferAppendF(path, "[%zd]", frame->data.promise_iteration.index); } break; } } return BufferClose(path); } StringSet *EvalContextStackPromisees(const EvalContext *ctx) { StringSet *promisees = StringSetNew(); for (size_t i = 0; i < SeqLength(ctx->stack); i++) { StackFrame *frame = SeqAt(ctx->stack, i); if (frame->type != STACK_FRAME_TYPE_PROMISE_ITERATION) { continue; } Rval promisee = frame->data.promise_iteration.owner->promisee; switch (promisee.type) { case RVAL_TYPE_SCALAR: StringSetAdd(promisees, xstrdup(RvalScalarValue(promisee))); break; case RVAL_TYPE_LIST: { for (const Rlist *rp = RvalRlistValue(promisee); rp; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR) { StringSetAdd(promisees, xstrdup(RvalScalarValue(rp->val))); } else { assert(false && "Canary: promisee list contained non-scalar value"); } } } break; case RVAL_TYPE_NOPROMISEE: break; default: assert(false && "Canary: promisee not scalar or list"); } } return promisees; } bool EvalContextVariablePutSpecial(EvalContext *ctx, SpecialScope scope, const char *lval, const void *value, DataType type, const char *tags) { if (strchr(lval, '[')) { // dealing with (legacy) array reference in lval, must parse VarRef *ref = VarRefParseFromScope(lval, SpecialScopeToString(scope)); bool ret = EvalContextVariablePut(ctx, ref, value, type, tags); VarRefDestroy(ref); return ret; } else { // plain lval, skip parsing const VarRef ref = VarRefConst(NULL, SpecialScopeToString(scope), lval); return EvalContextVariablePut(ctx, &ref, value, type, tags); } } bool EvalContextVariableRemoveSpecial(const EvalContext *ctx, SpecialScope scope, const char *lval) { switch (scope) { case SPECIAL_SCOPE_SYS: case SPECIAL_SCOPE_MON: case SPECIAL_SCOPE_CONST: case SPECIAL_SCOPE_EDIT: case SPECIAL_SCOPE_BODY: case SPECIAL_SCOPE_THIS: { VarRef *ref = VarRefParseFromScope(lval, SpecialScopeToString(scope)); bool ret = EvalContextVariableRemove(ctx, ref); VarRefDestroy(ref); return ret; } case SPECIAL_SCOPE_NONE: assert(false && "Attempted to remove none-special variable"); return false; default: assert(false && "Unhandled case in switch"); return false; } } static VariableTable *GetVariableTableForScope(const EvalContext *ctx, #ifdef NDEBUG ARG_UNUSED #endif /* ns is only used in assertions ... */ const char *ns, const char *scope) { switch (SpecialScopeFromString(scope)) { case SPECIAL_SCOPE_SYS: case SPECIAL_SCOPE_MON: case SPECIAL_SCOPE_CONST: assert(!ns || strcmp("default", ns) == 0); return ctx->global_variables; case SPECIAL_SCOPE_MATCH: assert(!ns || strcmp("default", ns) == 0); return ctx->match_variables; case SPECIAL_SCOPE_EDIT: assert(!ns || strcmp("default", ns) == 0); { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BUNDLE); assert(frame); return frame->data.bundle.vars; } case SPECIAL_SCOPE_BODY: assert(!ns || strcmp("default", ns) == 0); { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_BODY); return frame ? frame->data.body.vars : NULL; } case SPECIAL_SCOPE_THIS: { StackFrame *frame = LastStackFrameByType(ctx, STACK_FRAME_TYPE_PROMISE); return frame ? frame->data.promise.vars : NULL; } case SPECIAL_SCOPE_NONE: return ctx->global_variables; default: assert(false && "Unhandled case in switch"); return NULL; } } bool EvalContextVariableRemove(const EvalContext *ctx, const VarRef *ref) { VariableTable *table = GetVariableTableForScope(ctx, ref->ns, ref->scope); return VariableTableRemove(table, ref); } static bool IsVariableSelfReferential(const VarRef *ref, const void *value, RvalType rval_type) { switch (rval_type) { case RVAL_TYPE_SCALAR: if (StringContainsVar(value, ref->lval)) { char *ref_str = VarRefToString(ref, true); Log(LOG_LEVEL_ERR, "The value of variable '%s' contains a reference to itself, '%s'", ref_str, (char *)value); free(ref_str); return true; } break; case RVAL_TYPE_LIST: for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (rp->val.type != RVAL_TYPE_SCALAR) { continue; } if (StringContainsVar(RlistScalarValue(rp), ref->lval)) { char *ref_str = VarRefToString(ref, true); Log(LOG_LEVEL_ERR, "An item in list variable '%s' contains a reference to itself", ref_str); free(ref_str); return true; } } break; case RVAL_TYPE_FNCALL: case RVAL_TYPE_CONTAINER: case RVAL_TYPE_NOPROMISEE: break; } return false; } static void VarRefStackQualify(const EvalContext *ctx, VarRef *ref) { StackFrame *last_frame = LastStackFrame(ctx, 0); assert(last_frame); switch (last_frame->type) { case STACK_FRAME_TYPE_BODY: VarRefQualify(ref, NULL, SpecialScopeToString(SPECIAL_SCOPE_BODY)); break; case STACK_FRAME_TYPE_PROMISE_TYPE: { StackFrame *last_last_frame = LastStackFrame(ctx, 1); assert(last_last_frame); assert(last_last_frame->type == STACK_FRAME_TYPE_BUNDLE); VarRefQualify(ref, last_last_frame->data.bundle.owner->ns, last_last_frame->data.bundle.owner->name); } break; case STACK_FRAME_TYPE_BUNDLE: VarRefQualify(ref, last_frame->data.bundle.owner->ns, last_frame->data.bundle.owner->name); break; case STACK_FRAME_TYPE_PROMISE: case STACK_FRAME_TYPE_PROMISE_ITERATION: VarRefQualify(ref, NULL, SpecialScopeToString(SPECIAL_SCOPE_THIS)); break; } } bool EvalContextVariablePut(EvalContext *ctx, const VarRef *ref, const void *value, DataType type, const char *tags) { assert(type != CF_DATA_TYPE_NONE); assert(ref); assert(ref->lval); assert(value); if (!value) { return false; } if (strlen(ref->lval) > CF_MAXVARSIZE) { char *lval_str = VarRefToString(ref, true); Log(LOG_LEVEL_ERR, "Variable '%s'' cannot be added because " "its length exceeds the maximum length allowed ('%d' characters)", lval_str, CF_MAXVARSIZE); free(lval_str); return false; } if (strcmp(ref->scope, "body") != 0 && IsVariableSelfReferential(ref, value, DataTypeToRvalType(type))) { return false; } Rval rval = (Rval) { (void *)value, DataTypeToRvalType(type) }; VariableTable *table = GetVariableTableForScope(ctx, ref->ns, ref->scope); const Promise *pp = EvalContextStackCurrentPromise(ctx); VariableTablePut(table, ref, &rval, type, tags, pp ? pp->org_pp : pp); return true; } /* * Looks up a variable in the the context of the 'current scope'. This basically * means that an unqualified reference will be looked up in the context of the top * stack frame. Note that when evaluating a promise, this will qualify a reference * to the 'this' scope. * * Ideally, this function should resolve a variable by walking down the stack, but * this is pending rework in variable iteration. */ static Variable *VariableResolve(const EvalContext *ctx, const VarRef *ref) { assert(ref->lval); if (!VarRefIsQualified(ref)) { VarRef *qref = VarRefCopy(ref); VarRefStackQualify(ctx, qref); Variable *ret = VariableResolve(ctx, qref); VarRefDestroy(qref); return ret; } VariableTable *table = GetVariableTableForScope(ctx, ref->ns, ref->scope); if (table) { Variable *var = VariableTableGet(table, ref); if (var) { return var; } else if (ref->num_indices > 0) { VarRef *base_ref = VarRefCopyIndexless(ref); var = VariableTableGet(table, base_ref); VarRefDestroy(base_ref); if (var && var->type == CF_DATA_TYPE_CONTAINER) { return var; } } } return NULL; } const void *EvalContextVariableGet(const EvalContext *ctx, const VarRef *ref, DataType *type_out) { Variable *var = VariableResolve(ctx, ref); if (var) { if (var->ref->num_indices == 0 && ref->num_indices > 0 && var->type == CF_DATA_TYPE_CONTAINER) { JsonElement *child = JsonSelect(RvalContainerValue(var->rval), ref->num_indices, ref->indices); if (child) { if (type_out) { *type_out = CF_DATA_TYPE_CONTAINER; } return child; } } else { if (type_out) { *type_out = var->type; } return var->rval.item; } } else if (!VarRefIsQualified(ref)) { /* * FALLBACK: Because VariableResolve currently does not walk the stack (rather, it looks at * only the top frame), we do an explicit retry here to qualify an unqualified reference to * the current bundle. * * This is overly complicated, and will go away as soon as VariableResolve can walk the stack * (which is pending rework in variable iteration). */ const Bundle *bp = EvalContextStackCurrentBundle(ctx); if (bp) { VarRef *qref = VarRefCopy(ref); VarRefQualify(qref, bp->ns, bp->name); const void *ret = EvalContextVariableGet(ctx, qref, type_out); VarRefDestroy(qref); return ret; } } if (type_out) { *type_out = CF_DATA_TYPE_NONE; } return NULL; } const Promise *EvalContextVariablePromiseGet(const EvalContext *ctx, const VarRef *ref) { Variable *var = VariableResolve(ctx, ref); return var ? var->promise : NULL; } StringSet *EvalContextClassTags(const EvalContext *ctx, const char *ns, const char *name) { Class *cls = EvalContextClassGet(ctx, ns, name); if (!cls) { return NULL; } if (!cls->tags) { cls->tags = StringSetNew(); } return cls->tags; } StringSet *EvalContextVariableTags(const EvalContext *ctx, const VarRef *ref) { Variable *var = VariableResolve(ctx, ref); if (!var) { return NULL; } if (!var->tags) { var->tags = StringSetNew(); } return var->tags; } bool EvalContextVariableClearMatch(EvalContext *ctx) { return VariableTableClear(ctx->match_variables, NULL, NULL, NULL); } VariableTableIterator *EvalContextVariableTableIteratorNew(const EvalContext *ctx, const char *ns, const char *scope, const char *lval) { VariableTable *table = scope ? GetVariableTableForScope(ctx, ns, scope) : ctx->global_variables; return table ? VariableTableIteratorNew(table, ns, scope, lval) : NULL; } const void *EvalContextVariableControlCommonGet(const EvalContext *ctx, CommonControl lval) { if (lval >= COMMON_CONTROL_MAX) { return NULL; } VarRef *ref = VarRefParseFromScope(CFG_CONTROLBODY[lval].lval, "control_common"); const void *ret = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); return ret; } static ClassRef IDRefQualify(const EvalContext *ctx, const char *id) { // HACK: Because call reference names are equivalent to class names, we abuse ClassRef here ClassRef ref = ClassRefParse(id); if (!ClassRefIsQualified(ref)) { const char *ns = EvalContextCurrentNamespace(ctx); if (ns) { ClassRefQualify(&ref, ns); } else { ClassRefQualify(&ref, NamespaceDefault()); } } return ref; } const Bundle *EvalContextResolveBundleExpression(const EvalContext *ctx, const Policy *policy, const char *callee_reference, const char *callee_type) { ClassRef ref = IDRefQualify(ctx, callee_reference); const Bundle *bp = NULL; for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *curr_bp = SeqAt(policy->bundles, i); if ((strcmp(curr_bp->type, callee_type) != 0) || (strcmp(curr_bp->name, ref.name) != 0) || !StringSafeEqual(curr_bp->ns, ref.ns)) { continue; } bp = curr_bp; break; } ClassRefDestroy(ref); return bp; } const Body *EvalContextResolveBodyExpression(const EvalContext *ctx, const Policy *policy, const char *callee_reference, const char *callee_type) { ClassRef ref = IDRefQualify(ctx, callee_reference); const Body *bp = NULL; for (size_t i = 0; i < SeqLength(policy->bodies); i++) { const Body *curr_bp = SeqAt(policy->bodies, i); if ((strcmp(curr_bp->type, callee_type) != 0) || (strcmp(curr_bp->name, ref.name) != 0) || !StringSafeEqual(curr_bp->ns, ref.ns)) { continue; } bp = curr_bp; break; } ClassRefDestroy(ref); return bp; } bool EvalContextPromiseLockCacheContains(const EvalContext *ctx, const char *key) { return StringSetContains(ctx->promise_lock_cache, key); } void EvalContextPromiseLockCachePut(EvalContext *ctx, const char *key) { StringSetAdd(ctx->promise_lock_cache, xstrdup(key)); } bool EvalContextFunctionCacheGet(const EvalContext *ctx, const FnCall *fp, const Rlist *args, Rval *rval_out) { if (!(ctx->eval_options & EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS)) { return false; } size_t hash = RlistHash(args, FnCallHash(fp, 0, INT_MAX), INT_MAX); Rval *rval = RBTreeGet(ctx->function_cache, (void*)hash); if (rval) { if (rval_out) { *rval_out = *rval; } return true; } else { return false; } } void EvalContextFunctionCachePut(EvalContext *ctx, const FnCall *fp, const Rlist *args, const Rval *rval) { if (!(ctx->eval_options & EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS)) { return; } size_t hash = RlistHash(args, FnCallHash(fp, 0, INT_MAX), INT_MAX); Rval *rval_copy = xmalloc(sizeof(Rval)); *rval_copy = RvalCopy(*rval); RBTreePut(ctx->function_cache, (void*)hash, rval_copy); } /* cfPS and associated machinery */ /* * Internal functions temporarily used from logging implementation */ static const char *const NO_STATUS_TYPES[] = { "vars", "classes", "insert_lines", "delete_lines", "replace_patterns", "field_edits", NULL }; static const char *const NO_LOG_TYPES[] = { "vars", "classes", "insert_lines", "delete_lines", "replace_patterns", "field_edits", NULL }; /* * Vars, classes and similar promises which do not affect the system itself (but * just support evalution) do not need to be counted as repaired/failed, as they * may change every iteration and introduce lot of churn in reports without * giving any value. */ static bool IsPromiseValuableForStatus(const Promise *pp) { return pp && (pp->parent_promise_type->name != NULL) && (!IsStrIn(pp->parent_promise_type->name, NO_STATUS_TYPES)); } /* * Vars, classes and subordinate promises (like edit_line) do not need to be * logged, as they exist to support other promises. */ static bool IsPromiseValuableForLogging(const Promise *pp) { return pp && (pp->parent_promise_type->name != NULL) && (!IsStrIn(pp->parent_promise_type->name, NO_LOG_TYPES)); } static void AddAllClasses(EvalContext *ctx, const Rlist *list, unsigned int persistence_ttl, PersistentClassPolicy policy, ContextScope context_scope) { for (const Rlist *rp = list; rp != NULL; rp = rp->next) { char *classname = xstrdup(RlistScalarValue(rp)); if (strcmp(classname, "a_class_global_from_command") == 0 || strcmp(classname, "xxx:a_class_global_from_command") == 0) { Log(LOG_LEVEL_ERR, "Hit '%s'", classname); } CanonifyNameInPlace(classname); if (EvalContextHeapContainsHard(ctx, classname)) { Log(LOG_LEVEL_ERR, "You cannot use reserved hard class '%s' as post-condition class", classname); // TODO: ok.. but should we take any action? continue; maybe? } if (persistence_ttl > 0) { if (context_scope != CONTEXT_SCOPE_NAMESPACE) { Log(LOG_LEVEL_INFO, "Automatically promoting context scope for '%s' to namespace visibility, due to persistence", classname); } Log(LOG_LEVEL_VERBOSE, "Defining persistent promise result class '%s'", classname); EvalContextHeapPersistentSave(ctx, classname, persistence_ttl, policy, ""); EvalContextClassPutSoft(ctx, classname, CONTEXT_SCOPE_NAMESPACE, ""); } else { Log(LOG_LEVEL_VERBOSE, "Defining promise result class '%s'", classname); switch (context_scope) { case CONTEXT_SCOPE_BUNDLE: EvalContextStackFrameAddSoft(ctx, classname, ""); break; case CONTEXT_SCOPE_NONE: case CONTEXT_SCOPE_NAMESPACE: EvalContextClassPutSoft(ctx, classname, CONTEXT_SCOPE_NAMESPACE, ""); break; default: ProgrammingError("AddAllClasses: Unexpected context_scope %d!", context_scope); } } free(classname); } } static void DeleteAllClasses(EvalContext *ctx, const Rlist *list) { for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (CheckParseContext(RlistScalarValue(rp), CF_IDRANGE) != SYNTAX_TYPE_MATCH_OK) { return; // TODO: interesting course of action, but why is the check there in the first place? } if (EvalContextHeapContainsHard(ctx, RlistScalarValue(rp))) { Log(LOG_LEVEL_ERR, "You cannot cancel a reserved hard class '%s' in post-condition classes", RlistScalarValue(rp)); } const char *string = RlistScalarValue(rp); Log(LOG_LEVEL_VERBOSE, "Cancelling class '%s'", string); EvalContextHeapPersistentRemove(string); { ClassRef ref = ClassRefParse(CanonifyName(string)); EvalContextClassRemove(ctx, ref.ns, ref.name); ClassRefDestroy(ref); } EvalContextStackFrameRemoveSoft(ctx, CanonifyName(string)); } } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, TrackTotalCompliance, ARG_UNUSED PromiseResult, status, ARG_UNUSED const Promise *, pp) { } static void SetPromiseOutcomeClasses(EvalContext *ctx, PromiseResult status, DefineClasses dc) { Rlist *add_classes = NULL; Rlist *del_classes = NULL; switch (status) { case PROMISE_RESULT_CHANGE: add_classes = dc.change; del_classes = dc.del_change; break; case PROMISE_RESULT_TIMEOUT: add_classes = dc.timeout; del_classes = dc.del_notkept; break; case PROMISE_RESULT_WARN: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_INTERRUPTED: add_classes = dc.failure; del_classes = dc.del_notkept; break; case PROMISE_RESULT_DENIED: add_classes = dc.denied; del_classes = dc.del_notkept; break; case PROMISE_RESULT_NOOP: add_classes = dc.kept; del_classes = dc.del_kept; break; default: ProgrammingError("Unexpected status '%c' has been passed to SetPromiseOutcomeClasses", status); } AddAllClasses(ctx, add_classes, dc.persist, dc.timer, dc.scope); DeleteAllClasses(ctx, del_classes); } static void UpdatePromiseComplianceStatus(PromiseResult status, const Promise *pp, const char *reason) { if (!IsPromiseValuableForLogging(pp)) { return; } char compliance_status; switch (status) { case PROMISE_RESULT_CHANGE: compliance_status = PROMISE_STATE_REPAIRED; break; case PROMISE_RESULT_WARN: case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_DENIED: case PROMISE_RESULT_INTERRUPTED: compliance_status = PROMISE_STATE_NOTKEPT; break; case PROMISE_RESULT_NOOP: compliance_status = PROMISE_STATE_ANY; break; default: ProgrammingError("Unknown status '%c' has been passed to UpdatePromiseComplianceStatus", status); } NotePromiseCompliance(pp, compliance_status, reason); } static void SummarizeTransaction(EvalContext *ctx, TransactionContext tc, const char *logname) { if (logname && (tc.log_string)) { Buffer *buffer = BufferNew(); ExpandScalar(ctx, NULL, NULL, tc.log_string, buffer); if (strcmp(logname, "udp_syslog") == 0) { RemoteSysLog(tc.log_priority, BufferData(buffer)); } else if (strcmp(logname, "stdout") == 0) { Log(LOG_LEVEL_INFO, "L: %s", BufferData(buffer)); } else { struct stat dsb; // Does the file exist already? if (lstat(logname, &dsb) == -1) { mode_t filemode = 0600; /* Mode for log file creation */ int fd = creat(logname, filemode); if (fd >= 0) { Log(LOG_LEVEL_VERBOSE, "Created log file '%s' with requested permissions %jo", logname, (intmax_t) filemode); close(fd); } } FILE *fout = safe_fopen(logname, "a"); if (fout == NULL) { Log(LOG_LEVEL_ERR, "Unable to open private log '%s'", logname); return; } Log(LOG_LEVEL_VERBOSE, "Logging string '%s' to '%s'", BufferData(buffer), logname); fprintf(fout, "%s\n", BufferData(buffer)); fclose(fout); } BufferDestroy(buffer); tc.log_string = NULL; /* To avoid repetition */ } } static void DoSummarizeTransaction(EvalContext *ctx, PromiseResult status, const Promise *pp, TransactionContext tc) { if (!IsPromiseValuableForLogging(pp)) { return; } char *log_name = NULL; switch (status) { case PROMISE_RESULT_CHANGE: log_name = tc.log_repaired; break; case PROMISE_RESULT_WARN: /* FIXME: nothing? */ return; case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_DENIED: case PROMISE_RESULT_INTERRUPTED: log_name = tc.log_failed; break; case PROMISE_RESULT_NOOP: log_name = tc.log_kept; break; default: ProgrammingError("Unexpected promise result status: %d", status); } SummarizeTransaction(ctx, tc, log_name); } void NotifyDependantPromises(EvalContext *ctx, const Promise *pp, PromiseResult result) { switch (result) { case PROMISE_RESULT_CHANGE: case PROMISE_RESULT_NOOP: { const char *handle = PromiseGetHandle(pp); if (handle) { StringSetAdd(ctx->dependency_handles, xstrdup(handle)); } } break; default: /* This promise is not yet done, don't mark it is as such */ break; } } void ClassAuditLog(EvalContext *ctx, const Promise *pp, Attributes attr, PromiseResult status) { if (IsPromiseValuableForStatus(pp)) { TrackTotalCompliance(status, pp); UpdatePromiseCounters(status); } SetPromiseOutcomeClasses(ctx, status, attr.classes); DoSummarizeTransaction(ctx, status, pp, attr.transaction); } static void LogPromiseContext(const EvalContext *ctx, const Promise *pp) { Writer *w = StringWriter(); WriterWrite(w, "Additional promise info:"); if (PromiseGetHandle(pp)) { WriterWriteF(w, " handle '%s'", PromiseGetHandle(pp)); } { const char *version = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_VERSION); if (version) { WriterWriteF(w, " version '%s'", version); } } if (PromiseGetBundle(pp)->source_path) { WriterWriteF(w, " source path '%s' at line %zu", PromiseGetBundle(pp)->source_path, pp->offset.line); } switch (pp->promisee.type) { case RVAL_TYPE_SCALAR: WriterWriteF(w, " promisee '%s'", RvalScalarValue(pp->promisee)); break; case RVAL_TYPE_LIST: WriterWrite(w, " promisee "); RlistWrite(w, pp->promisee.item); break; default: break; } if (pp->comment) { WriterWriteF(w, " comment '%s'", pp->comment); } Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w)); WriterClose(w); } void cfPS(EvalContext *ctx, LogLevel level, PromiseResult status, const Promise *pp, Attributes attr, const char *fmt, ...) { /* * This stub implementation of cfPS delegates to the new logging backend. * * Due to the fact very little of the code has been converted, this code * does a full initialization and shutdown of logging subsystem for each * cfPS. * * Instead, LoggingInit should be called at the moment EvalContext is * created, LoggingPromiseEnter/LoggingPromiseFinish should be called around * ExpandPromise and LoggingFinish should be called when EvalContext is * going to be destroyed. * * But it requires all calls to cfPS to be eliminated. */ /* FIXME: Ensure that NULL pp is never passed into cfPS */ assert(pp); if (level >= LOG_LEVEL_VERBOSE) { LogPromiseContext(ctx, pp); } va_list ap; va_start(ap, fmt); char *msg = NULL; xvasprintf(&msg, fmt, ap); Log(level, "%s", msg); va_end(ap); /* Now complete the exits status classes and auditing */ ClassAuditLog(ctx, pp, attr, status); UpdatePromiseComplianceStatus(status, pp, msg); free(msg); } void SetChecksumUpdatesDefault(EvalContext *ctx, bool enabled) { ctx->checksum_updates_default = enabled; } bool GetChecksumUpdatesDefault(const EvalContext *ctx) { return ctx->checksum_updates_default; } void EvalContextAddIpAddress(EvalContext *ctx, const char *ip_address) { AppendItem(&ctx->ip_addresses, ip_address, ""); } void EvalContextDeleteIpAddresses(EvalContext *ctx) { DeleteItemList(ctx->ip_addresses); ctx->ip_addresses = NULL; } Item *EvalContextGetIpAddresses(const EvalContext *ctx) { return ctx->ip_addresses; } void EvalContextSetEvalOption(EvalContext *ctx, EvalContextOption option, bool value) { if (value) { ctx->eval_options |= option; } else { ctx->eval_options &= ~option; } } bool EvalContextGetEvalOption(EvalContext *ctx, EvalContextOption option) { return !!(ctx->eval_options & option); } void EvalContextSetLaunchDirectory(EvalContext *ctx, const char *path) { free(ctx->launch_directory); ctx->launch_directory = xstrdup(path); } void EvalContextSetIgnoreLocks(EvalContext *ctx, bool ignore) { ctx->ignore_locks = ignore; } bool EvalContextIsIgnoringLocks(const EvalContext *ctx) { return ctx->ignore_locks; } cfengine-3.6.2/libpromises/crypto.h0000664000175100017510000000354312400110676017041 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CRYPTO_H #define CFENGINE_CRYPTO_H #include #include #include void CryptoInitialize(void); void CryptoDeInitialize(void); const char *CryptoLastErrorString(void); void DebugBinOut(char *buffer, int len, char *com); bool LoadSecretKeys(void); void PolicyHubUpdateKeys(const char *policy_server); int EncryptString(char type, const char *in, char *out, unsigned char *key, int len); int DecryptString(char type, const char *in, char *out, unsigned char *key, int len); RSA *HavePublicKey(const char *username, const char *ipaddress, const char *digest); RSA *HavePublicKeyByIP(const char *username, const char *ipaddress); void SavePublicKey(const char *username, const char *digest, const RSA *key); char *PublicKeyFile(const char *workdir); char *PrivateKeyFile(const char *workdir); LogLevel CryptoGetMissingKeyLogLevel(void); #endif cfengine-3.6.2/libpromises/mod_databases.h0000664000175100017510000000217512243421446020314 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_DATABASES_H #define CFENGINE_MOD_DATABASES_H #include extern const PromiseTypeSyntax CF_DATABASES_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/acl_tools.h0000644000175100017510000000215112316547775017514 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ACL_TOOLS_H #define CFENGINE_ACL_TOOLS_H int CopyACLs(const char *src, const char *dst); #endif // CFENGINE_ACL_TOOLS_H cfengine-3.6.2/libpromises/process_linux.c0000644000175100017510000000744412316547775020437 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include typedef struct { time_t starttime; char state; } ProcessStat; static bool GetProcessStat(pid_t pid, ProcessStat *state) { char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "/proc/%d/stat", (int)pid); int fd; for (;;) { if ((fd = open(filename, O_RDONLY)) != -1) { break; } if (errno == EINTR) { continue; } if (errno == ENOENT || errno == ENOTDIR) { return false; } if (errno == EACCES) { return false; } assert (fd != -1 && "Unable to open /proc//stat"); } char stat[CF_BUFSIZE]; int res = FullRead(fd, stat, sizeof(stat) - 1); /* -1 for the '\0', below */ close(fd); if (res < 0) { return false; } assert(res < CF_BUFSIZE); stat[res] = '\0'; /* read() doesn't '\0'-terminate */ /* stat entry is of form: () * To avoid choking on weird task names, we search for the closing * parenthesis first: */ char *p = memrchr(stat, ')', res); if (p == NULL) { /* Wrong field format! */ return false; } p++; // Skip the parenthesis char proc_state[2]; unsigned long long starttime; if (sscanf(p, "%1s" /* state */ "%*s" /* ppid */ "%*s" /* pgrp */ "%*s" /* session */ "%*s" /* tty_nr */ "%*s" /* tpgid */ "%*s" /* flags */ "%*s" /* minflt */ "%*s" /* cminflt */ "%*s" /* majflt */ "%*s" /* cmajflt */ "%*s" /* utime */ "%*s" /* stime */ "%*s" /* cutime */ "%*s" /* cstime */ "%*s" /* priority */ "%*s" /* nice */ "%*s" /* num_threads */ "%*s" /* itrealvalue */ "%llu" /* starttime */, proc_state, &starttime) != 2) { return false; } state->state = proc_state[0]; state->starttime = (time_t)(starttime / sysconf(_SC_CLK_TCK)); return true; } time_t GetProcessStartTime(pid_t pid) { ProcessStat st; if (GetProcessStat(pid, &st)) { return st.starttime; } else { return PROCESS_START_TIME_UNKNOWN; } } ProcessState GetProcessState(pid_t pid) { ProcessStat st; if (GetProcessStat(pid, &st)) { if (st.state == 'T') { return PROCESS_STATE_STOPPED; } else { return PROCESS_STATE_RUNNING; } } else { return PROCESS_STATE_DOES_NOT_EXIST; } } cfengine-3.6.2/libpromises/mod_methods.c0000644000175100017510000000714012316547775020035 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include static const char *const POLICY_ERROR_METHODS_BUNDLE_ARITY = "Conflicting arity in calling bundle %s, expected %d arguments, %d given"; static const ConstraintSyntax CF_METHOD_BODIES[] = { ConstraintSyntaxNewBool("inherit", "If true this causes the sub-bundle to inherit the private classes of its parent", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBundle("usebundle", "Specify the name of a bundle to run as a parameterized method", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("useresult", CF_IDRANGE, "Specify the name of a local variable to contain any result/return value from the child", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static bool MethodsParseTreeCheck(const Promise *pp, Seq *errors) { bool success = true; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); // ensure: if call and callee are resolved, then they have matching arity if (StringSafeEqual(cp->lval, "usebundle")) { if (cp->rval.type == RVAL_TYPE_FNCALL) { // HACK: exploiting the fact that class-references and call-references are similar FnCall *call = RvalFnCallValue(cp->rval); ClassRef ref = ClassRefParse(call->name); if (!ClassRefIsQualified(ref)) { ClassRefQualify(&ref, PromiseGetNamespace(pp)); } const Bundle *callee = PolicyGetBundle(PolicyFromPromise(pp), ref.ns, "agent", ref.name); if (!callee) { callee = PolicyGetBundle(PolicyFromPromise(pp), ref.ns, "common", ref.name); } ClassRefDestroy(ref); if (callee) { if (RlistLen(call->args) != RlistLen(callee->args)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp, POLICY_ERROR_METHODS_BUNDLE_ARITY, call->name, RlistLen(callee->args), RlistLen(call->args))); success = false; } } } } } return success; } const PromiseTypeSyntax CF_METHOD_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "methods", CF_METHOD_BODIES, &MethodsParseTreeCheck, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/promises.c0000664000175100017510000004152112411001073017343 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include static void DereferenceComment(Promise *pp); Promise *DeRefCopyPromise(EvalContext *ctx, const Promise *pp) { Promise *pcopy; pcopy = xcalloc(1, sizeof(Promise)); if (pp->promiser) { pcopy->promiser = xstrdup(pp->promiser); } if (pp->promisee.item) { pcopy->promisee = RvalCopy(pp->promisee); if (pcopy->promisee.type == RVAL_TYPE_LIST) { Rlist *rval_list = RvalRlistValue(pcopy->promisee); RlistFlatten(ctx, &rval_list); pcopy->promisee.item = rval_list; } } assert(pp->classes); pcopy->classes = xstrdup(pp->classes); /* FIXME: may it happen? */ if ((pp->promisee.item != NULL && pcopy->promisee.item == NULL)) { ProgrammingError("Unable to copy promise"); } pcopy->parent_promise_type = pp->parent_promise_type; pcopy->offset.line = pp->offset.line; pcopy->comment = pp->comment ? xstrdup(pp->comment) : NULL; pcopy->has_subbundles = pp->has_subbundles; pcopy->conlist = SeqNew(10, ConstraintDestroy); pcopy->org_pp = pp->org_pp; pcopy->offset = pp->offset; /* No further type checking should be necessary here, already done by CheckConstraintTypeMatch */ for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); const Policy *policy = PolicyFromPromise(pp); const Body *bp = NULL; const Rlist *args = NULL; const char *body_reference = NULL; /* A body template reference could look like a scalar or fn to the parser w/w () */ switch (cp->rval.type) { case RVAL_TYPE_SCALAR: if (cp->references_body) { body_reference = RvalScalarValue(cp->rval); bp = EvalContextResolveBodyExpression(ctx, policy, body_reference, cp->lval); } args = NULL; break; case RVAL_TYPE_FNCALL: body_reference = RvalFnCallValue(cp->rval)->name; bp = EvalContextResolveBodyExpression(ctx, policy, body_reference, cp->lval); args = RvalFnCallValue(cp->rval)->args; break; default: bp = NULL; args = NULL; break; } /* First case is: we have a body template to expand lval = body(args), .. */ if (bp) { EvalContextStackPushBodyFrame(ctx, pcopy, bp, args); if (strcmp(bp->type, cp->lval) != 0) { Log(LOG_LEVEL_ERR, "Body type mismatch for body reference '%s' in promise " "at line %zu of file '%s', '%s' does not equal '%s'", body_reference, pp->offset.line, PromiseGetBundle(pp)->source_path, bp->type, cp->lval); } /* Keep the referent body type as a boolean for convenience when checking later */ if (IsDefinedClass(ctx, cp->classes)) { Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, (Rval) {xstrdup("true"), RVAL_TYPE_SCALAR }, false); cp_copy->offset = cp->offset; } if (bp->args) { /* There are arguments to insert */ if (!args) { Log(LOG_LEVEL_ERR, "Argument mismatch for body reference '%s' in promise " "at line %zu of file '%s'", body_reference, pp->offset.line, PromiseGetBundle(pp)->source_path); } for (size_t k = 0; k < SeqLength(bp->conlist); k++) { Constraint *scp = SeqAt(bp->conlist, k); if (IsDefinedClass(ctx, scp->classes)) { Rval returnval = ExpandPrivateRval(ctx, NULL, "body", scp->rval.item, scp->rval.type); Constraint *scp_copy = PromiseAppendConstraint(pcopy, scp->lval, returnval, false); scp_copy->offset = scp->offset; } } } else { /* No arguments to deal with or body undeclared */ if (args) { Log(LOG_LEVEL_ERR, "Apparent body '%s' was undeclared or could " "have incorrect args, but used in a promise near " "line %zu of %s (possible unquoted literal value)", RvalScalarValue(cp->rval), pp->offset.line, PromiseGetBundle(pp)->source_path); } else { for (size_t k = 0; k < SeqLength(bp->conlist); k++) { Constraint *scp = SeqAt(bp->conlist, k); if (IsDefinedClass(ctx, scp->classes)) { Rval newrv = RvalCopy(scp->rval); if (newrv.type == RVAL_TYPE_LIST) { Rlist *new_list = RvalRlistValue(newrv); RlistFlatten(ctx, &new_list); newrv.item = new_list; } Constraint *scp_copy = PromiseAppendConstraint(pcopy, scp->lval, newrv, false); scp_copy->offset = scp->offset; } } } } EvalContextStackPopFrame(ctx); } else { const Policy *policy = PolicyFromPromise(pp); if (cp->references_body) { // assume this is a typed bundle (e.g. edit_line) const Bundle *callee = EvalContextResolveBundleExpression(ctx, policy, RvalScalarValue(cp->rval), cp->lval); if (!callee) { // otherwise, assume this is a method-type call callee = EvalContextResolveBundleExpression(ctx, policy, RvalScalarValue(cp->rval), "agent"); if (!callee) { callee = EvalContextResolveBundleExpression(ctx, policy, RvalScalarValue(cp->rval), "common"); } } if (!callee) { Log(LOG_LEVEL_ERR, "Apparent bundle '%s' was undeclared, but " "used in a promise near line %zu of %s " "(possible unquoted literal value)", RvalScalarValue(cp->rval), pp->offset.line, PromiseGetBundle(pp)->source_path); } } if (IsDefinedClass(ctx, cp->classes)) { Rval newrv = RvalCopy(cp->rval); if (newrv.type == RVAL_TYPE_LIST) { Rlist *new_list = RvalRlistValue(newrv); RlistFlatten(ctx, &new_list); newrv.item = new_list; } Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, newrv, false); cp_copy->offset = cp->offset; } } } return pcopy; } /*****************************************************************************/ static bool EvaluateConstraintIteration(EvalContext *ctx, const Constraint *cp, Rval *rval_out) { assert(cp->type == POLICY_ELEMENT_TYPE_PROMISE); const Promise *pp = cp->parent.promise; if (!IsDefinedClass(ctx, cp->classes)) { return false; } if (ExpectedDataType(cp->lval) == CF_DATA_TYPE_BUNDLE) { *rval_out = ExpandBundleReference(ctx, NULL, "this", cp->rval); } else { *rval_out = EvaluateFinalRval(ctx, PromiseGetPolicy(pp), NULL, "this", cp->rval, false, pp); } return true; } Promise *ExpandDeRefPromise(EvalContext *ctx, const Promise *pp, bool *excluded) { assert(pp->promiser); assert(pp->classes); if (excluded) { *excluded = false; } Promise *pcopy = xcalloc(1, sizeof(Promise)); Rval returnval = ExpandPrivateRval(ctx, NULL, "this", pp->promiser, RVAL_TYPE_SCALAR); pcopy->promiser = RvalScalarValue(returnval); if ((strcmp("files", pp->parent_promise_type->name) != 0) && (strcmp("storage", pp->parent_promise_type->name) != 0)) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", pcopy->promiser, CF_DATA_TYPE_STRING, "source=promise"); } if (pp->promisee.item) { pcopy->promisee = EvaluateFinalRval(ctx, PromiseGetPolicy(pp), NULL, "this", pp->promisee, true, pp); } else { pcopy->promisee = (Rval) {NULL, RVAL_TYPE_NOPROMISEE }; } pcopy->classes = xstrdup(pp->classes); pcopy->parent_promise_type = pp->parent_promise_type; pcopy->offset.line = pp->offset.line; pcopy->comment = pp->comment ? xstrdup(pp->comment) : NULL; pcopy->conlist = SeqNew(10, ConstraintDestroy); pcopy->org_pp = pp->org_pp; { // if this is a class promise, check if it is already set, if so, skip if (strcmp("classes", pp->parent_promise_type->name) == 0) { if (IsDefinedClass(ctx, pcopy->promiser)) { Log(LOG_LEVEL_VERBOSE, "Skipping evaluation of classes promise as class '%s' is already set", pcopy->promiser); if (excluded) { *excluded = true; } return pcopy; } } // look for ifvarclass exclusion, to short-circuit evaluation of other constraints const Constraint *ifvarclass = PromiseGetConstraint(pp, "ifvarclass"); if (ifvarclass) { /* This might fail to expand if there are unexpanded variables in function arguments (in which case the function won't be called at all). If final is not a scalar, then expansion has failed (the function would still return true). In that case, assume that we don't know the class, and skip the promise. Note: EvaluateConstraintIteration calls VarClassExcluded via EvalContextPromiseIsActive, trying to avoid function calls in promise bodies that are disabled due to class conditionals or ifvarclass predicates. Changing the logic of VarClassExcluded would possibly break function evaluation. */ Rval final; if (EvaluateConstraintIteration(ctx, ifvarclass, &final)) { Constraint *cp_copy = PromiseAppendConstraint(pcopy, ifvarclass->lval, final, false); cp_copy->offset = ifvarclass->offset; char *excluding_class_expr = NULL; if (final.type != RVAL_TYPE_SCALAR || VarClassExcluded(ctx, pcopy, &excluding_class_expr)) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); Log(LOG_LEVEL_VERBOSE, "Skipping whole next promise (%s), as ifvarclass %s is not relevant", pp->promiser, excluding_class_expr ? excluding_class_expr : pp->classes); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); } else { Log(LOG_LEVEL_VERBOSE, "Skipping next promise '%s', as ifvarclass '%s' is not relevant", pp->promiser, excluding_class_expr ? excluding_class_expr : pp->classes); } if (excluded) { *excluded = true; } return pcopy; } } } } { // look for depends_on exclusion, to short-circuit evaluation of other constraints const Constraint *depends_on = PromiseGetConstraint(pp, "depends_on"); if (depends_on) { Rval final; if (EvaluateConstraintIteration(ctx, depends_on, &final)) { Constraint *cp_copy = PromiseAppendConstraint(pcopy, depends_on->lval, final, false); cp_copy->offset = depends_on->offset; if (MissingDependencies(ctx, pcopy)) { if (excluded) { *excluded = true; } return pcopy; } } } } for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); // special constraints ifvarclass and depends_on are evaluated before the rest of the constraints if (strcmp(cp->lval, "ifvarclass") == 0 || strcmp(cp->lval, "depends_on") == 0) { continue; } Rval final; if (!EvaluateConstraintIteration(ctx, cp, &final)) { continue; } Constraint *cp_copy = PromiseAppendConstraint(pcopy, cp->lval, final, false); cp_copy->offset = cp->offset; if (strcmp(cp->lval, "comment") == 0) { if (final.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "Comments can only be scalar objects, not '%s' in '%s'", RvalTypeToString(final.type), pp->promiser); } else { free(pcopy->comment); pcopy->comment = final.item ? xstrdup(final.item) : NULL; if (pcopy->comment && (strstr(pcopy->comment, "$(this.promiser)") || strstr(pcopy->comment, "${this.promiser}"))) { DereferenceComment(pcopy); } } } } return pcopy; } void PromiseRef(LogLevel level, const Promise *pp) { if (pp == NULL) { return; } if (PromiseGetBundle(pp)->source_path) { Log(level, "Promise belongs to bundle '%s' in file '%s' near line %zu", PromiseGetBundle(pp)->name, PromiseGetBundle(pp)->source_path, pp->offset.line); } else { Log(level, "Promise belongs to bundle '%s' near line %zu", PromiseGetBundle(pp)->name, pp->offset.line); } if (pp->comment) { Log(level, "Comment is '%s'", pp->comment); } switch (pp->promisee.type) { case RVAL_TYPE_SCALAR: Log(level, "This was a promise to '%s'", (char *)(pp->promisee.item)); break; case RVAL_TYPE_LIST: { Writer *w = StringWriter(); RlistWrite(w, pp->promisee.item); char *p = StringWriterClose(w); Log(level, "This was a promise to '%s'", p); free(p); break; } default: break; } } /*******************************************************************/ static void DereferenceComment(Promise *pp) { char pre_buffer[CF_BUFSIZE], post_buffer[CF_BUFSIZE], buffer[CF_BUFSIZE], *sp; int offset = 0; strlcpy(pre_buffer, pp->comment, CF_BUFSIZE); if ((sp = strstr(pre_buffer, "$(this.promiser)")) || (sp = strstr(pre_buffer, "${this.promiser}"))) { *sp = '\0'; offset = sp - pre_buffer + strlen("$(this.promiser)"); strlcpy(post_buffer, pp->comment + offset, CF_BUFSIZE); snprintf(buffer, CF_BUFSIZE, "%s%s%s", pre_buffer, pp->promiser, post_buffer); free(pp->comment); pp->comment = xstrdup(buffer); } } cfengine-3.6.2/libpromises/mod_services.c0000664000175100017510000000533512243421446020204 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax service_method_constraints[] = { ConstraintSyntaxNewString("service_args", "", "Parameters for starting the service as command", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("service_autostart_policy", "none,boot_time,on_demand", "Should the service be started automatically by the OS", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBundle("service_bundle", "A bundle reference with two arguments (service_name,args) used if the service type is generic", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("service_dependence_chain", "ignore,start_parent_services,stop_child_services,all_related", "How to handle dependencies and dependent services", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("service_type", "windows,generic", "Service abstraction type", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax service_method_body = BodySyntaxNew("service_method", service_method_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax services_constraints[] = { ConstraintSyntaxNewOption("service_policy", "start,stop,disable,restart,reload", "Policy for cfengine service status", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("service_dependencies", CF_IDRANGE, "A list of services on which the named service abstraction depends", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("service_method", &service_method_body, "Details of promise body for the service abtraction feature", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_SERVICES_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "services", services_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/cf3parse.y0000664000175100017510000016761312411001073017251 0ustar00a10038a1003800000000000000 %{ /* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include "cf3.defs.h" #include "parser.h" #include "parser_state.h" #include "fncall.h" #include "rlist.h" #include "item_lib.h" #include "policy.h" #include "mod_files.h" #include "string_lib.h" #include "logic_expressions.h" // FIX: remove #include "syntax.h" #include int yylex(void); extern char *yytext; static int RelevantBundle(const char *agent, const char *blocktype); static bool LvalWantsBody(char *stype, char *lval); static SyntaxTypeMatch CheckSelection(const char *type, const char *name, const char *lval, Rval rval); static SyntaxTypeMatch CheckConstraint(const char *type, const char *lval, Rval rval, const PromiseTypeSyntax *ss); static void fatal_yyerror(const char *s); static void ParseErrorColumnOffset(int column_offset, const char *s, ...) FUNC_ATTR_PRINTF(2, 3); static void ParseError(const char *s, ...) FUNC_ATTR_PRINTF(1, 2); static void ParseWarning(unsigned int warning, const char *s, ...) FUNC_ATTR_PRINTF(2, 3); static void ValidateClassLiteral(const char *class_literal); static bool INSTALL_SKIP = false; static size_t CURRENT_BLOCKID_LINE = 0; static size_t CURRENT_PROMISER_LINE = 0; #define YYMALLOC xmalloc #define ParserDebug if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) printf %} %token IDSYNTAX BLOCKID QSTRING CLASS PROMISE_TYPE BUNDLE BODY ASSIGN ARROW NAKEDVAR %token OP CP OB CB %expect 1 %% specification: /* empty */ | blocks /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ blocks: block | blocks block; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ block: bundle | body | error { ParseError("Expected 'bundle' or 'body' keyword, wrong input '%s'", yytext); YYABORT; } bundle: BUNDLE bundletype bundleid arglist bundlebody body: BODY bodytype bodyid arglist bodybody /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bundletype: bundletype_values { ParserDebug("P:bundle:%s\n", P.blocktype); P.block = "bundle"; RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); RlistDestroy(P.currentRlist); P.currentRlist = NULL; if (P.currentstring) { free(P.currentstring); } P.currentstring = NULL; strcpy(P.blockid,""); } bundletype_values: typeid { /* FIXME: We keep it here, because we skip unknown * promise bundles. Ought to be moved to * after-parsing step once we know how to deal with * it */ if (!BundleTypeCheck(P.blocktype)) { ParseError("Unknown bundle type '%s'", P.blocktype); INSTALL_SKIP = true; } } | error { yyclearin; ParseError("Expected bundle type, wrong input '%s'", yytext); INSTALL_SKIP = true; } bundleid: bundleid_values { ParserDebug("\tP:bundle:%s:%s\n", P.blocktype, P.blockid); CURRENT_BLOCKID_LINE = P.line_no; } bundleid_values: symbol | error { yyclearin; ParseError("Expected bundle identifier, wrong input '%s'", yytext); INSTALL_SKIP = true; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bodytype: bodytype_values { ParserDebug("P:body:%s\n", P.blocktype); P.block = "body"; strcpy(P.blockid,""); RlistDestroy(P.currentRlist); P.currentRlist = NULL; if (P.currentstring) { free(P.currentstring); } P.currentstring = NULL; } bodytype_values: typeid { if (!BodySyntaxGet(P.blocktype)) { ParseError("Unknown body type '%s'", P.blocktype); } } | error { yyclearin; ParseError("Expected body type, wrong input '%s'", yytext); } bodyid: bodyid_values { ParserDebug("\tP:body:%s:%s\n", P.blocktype, P.blockid); CURRENT_BLOCKID_LINE = P.line_no; } bodyid_values: symbol | error { yyclearin; ParseError("Expected body identifier, wrong input '%s'", yytext); INSTALL_SKIP = true; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ typeid: IDSYNTAX { strncpy(P.blocktype,P.currentid,CF_MAXVARSIZE); RlistDestroy(P.useargs); P.useargs = NULL; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ symbol: IDSYNTAX { strncpy(P.blockid,P.currentid,CF_MAXVARSIZE); P.offsets.last_block_id = P.offsets.last_id; }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ arglist: /* Empty */ | arglist_begin aitems arglist_end | arglist_begin arglist_end | arglist_begin error { yyclearin; ParseError("Error in bundle parameter list, expected ')', wrong input '%s'", yytext); } arglist_begin: OP { ParserDebug("P:%s:%s:%s arglist begin:%s\n", P.block,P.blocktype,P.blockid, yytext); } arglist_end: CP { ParserDebug("P:%s:%s:%s arglist end:%s\n", P.block,P.blocktype,P.blockid, yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ aitems: aitem | aitems ',' aitem /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ aitem: IDSYNTAX /* recipient of argument is never a literal */ { ParserDebug("P:%s:%s:%s arg id: %s\n", P.block,P.blocktype,P.blockid, P.currentid); RlistAppendScalar(&(P.useargs),P.currentid); } | error { yyclearin; ParseError("Expected identifier, wrong input '%s'", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bundlebody: body_begin { if (RelevantBundle(CF_AGENTTYPES[P.agent_type], P.blocktype)) { INSTALL_SKIP = false; } else if (strcmp(CF_AGENTTYPES[P.agent_type], P.blocktype) != 0) { INSTALL_SKIP = true; } if (!INSTALL_SKIP) { P.currentbundle = PolicyAppendBundle(P.policy, P.current_namespace, P.blockid, P.blocktype, P.useargs, P.filename); P.currentbundle->offset.line = CURRENT_BLOCKID_LINE; P.currentbundle->offset.start = P.offsets.last_block_id; } else { P.currentbundle = NULL; } RlistDestroy(P.useargs); P.useargs = NULL; } bundle_decl CB { INSTALL_SKIP = false; P.offsets.last_id = -1; P.offsets.last_string = -1; P.offsets.last_class_id = -1; if (P.currentbundle) { P.currentbundle->offset.end = P.offsets.current; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ body_begin: OB { ParserDebug("P:%s:%s:%s begin body open\n", P.block,P.blocktype,P.blockid); } | error { ParseError("Expected body open '{', wrong input '%s'", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bundle_decl: /* empty */ | bundle_statements /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bundle_statements: bundle_statement | bundle_statements bundle_statement | error { INSTALL_SKIP = true; ParseError("Expected promise type, got '%s'", yytext); ParserDebug("P:promise_type:error yychar = %d, %c, yyempty = %d\n", yychar, yychar, YYEMPTY); yyclearin; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bundle_statement: promise_type classpromises_decl /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ promise_type: PROMISE_TYPE /* BUNDLE ONLY */ { ParserDebug("\tP:%s:%s:%s promise_type = %s\n", P.block, P.blocktype, P.blockid, P.currenttype); const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(P.blocktype, P.currenttype); if (promise_type_syntax) { switch (promise_type_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated promise type '%s' in bundle type '%s'", promise_type_syntax->promise_type, promise_type_syntax->bundle_type); // Intentional fall case SYNTAX_STATUS_NORMAL: if (strcmp(P.block, "bundle") == 0) { if (!INSTALL_SKIP) { P.currentstype = BundleAppendPromiseType(P.currentbundle,P.currenttype); P.currentstype->offset.line = P.line_no; P.currentstype->offset.start = P.offsets.last_promise_type_id; } else { P.currentstype = NULL; } } break; case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed promise type '%s' in bundle type '%s'", promise_type_syntax->promise_type, promise_type_syntax->bundle_type); INSTALL_SKIP = true; break; } } else { ParseError("Unknown promise type '%s'", P.currenttype); INSTALL_SKIP = true; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ classpromises_decl: /* empty */ | classpromises /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ classpromises: classpromise | classpromises classpromise /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ classpromise: class | promise_decl /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ promise_decl: promise_line ';' | promiser error { /* * Based on yychar display right error message */ ParserDebug("P:promiser:error yychar = %d\n", yychar); if (yychar =='-' || yychar == '>') { ParseError("Expected '->', got '%s'", yytext); } else if (yychar == IDSYNTAX) { ParseError("Expected attribute, got '%s'", yytext); } else if (yychar == ',') { ParseError("Expected attribute, got '%s' (comma after promiser is not allowed since 3.5.0)", yytext); } else { ParseError("Expected ';', got '%s'", yytext); } yyclearin; } promise_line: promisee_statement | promiser_statement /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ promisee_statement: promiser arrow_type rval { if (!INSTALL_SKIP) { if (!P.currentstype) { ParseError("Missing promise type declaration"); } P.currentpromise = PromiseTypeAppendPromise(P.currentstype, P.promiser, RvalCopy(P.rval), P.currentclasses ? P.currentclasses : "any"); P.currentpromise->offset.line = CURRENT_PROMISER_LINE; P.currentpromise->offset.start = P.offsets.last_string; P.currentpromise->offset.context = P.offsets.last_class_id; } else { P.currentpromise = NULL; } } promiser_constraints_decl /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ promiser_statement: promiser { if (!INSTALL_SKIP) { if (!P.currentstype) { ParseError("Missing promise type declaration"); } P.currentpromise = PromiseTypeAppendPromise(P.currentstype, P.promiser, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, P.currentclasses ? P.currentclasses : "any"); P.currentpromise->offset.line = CURRENT_PROMISER_LINE; P.currentpromise->offset.start = P.offsets.last_string; P.currentpromise->offset.context = P.offsets.last_class_id; } else { P.currentpromise = NULL; } } promiser_constraints_decl /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ promiser: QSTRING { if (P.promiser) { free(P.promiser); } P.promiser = P.currentstring; P.currentstring = NULL; CURRENT_PROMISER_LINE = P.line_no; ParserDebug("\tP:%s:%s:%s:%s:%s promiser = %s\n", P.block, P.blocktype, P.blockid, P.currenttype, P.currentclasses ? P.currentclasses : "any", P.promiser); } | error { INSTALL_SKIP = true; ParserDebug("P:promiser:qstring::error yychar = %d\n", yychar); if (yychar == BUNDLE || yychar == BODY || yychar == YYEOF) { ParseError("Expected '}', got '%s'", yytext); /* YYABORT; */ } else { ParseError("Expected promiser string, got '%s'", yytext); } yyclearin; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ promiser_constraints_decl: /* empty */ | constraints_decl | constraints_decl error { /* * Based on next token id display right error message */ ParserDebug("P:constraints_decl:error yychar = %d\n", yychar); if ( yychar == IDSYNTAX ) { ParseError("Check previous line, Expected ',', got '%s'", yytext); } else { ParseError("Check previous line, Expected ';', got '%s'", yytext); } yyclearin; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ constraints_decl: constraints { /* Don't free these */ strcpy(P.currentid,""); RlistDestroy(P.currentRlist); P.currentRlist = NULL; free(P.promiser); if (P.currentstring) { free(P.currentstring); } P.currentstring = NULL; P.promiser = NULL; P.promisee = NULL; /* reset argptrs etc*/ } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ constraints: constraint /* BUNDLE ONLY */ | constraints ',' constraint /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ constraint: constraint_id /* BUNDLE ONLY */ assign_type rval { if (!INSTALL_SKIP) { const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(P.blocktype, P.currenttype); assert(promise_type_syntax); const ConstraintSyntax *constraint_syntax = PromiseTypeSyntaxGetConstraintSyntax(promise_type_syntax, P.lval); if (constraint_syntax) { switch (constraint_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated constraint '%s' in promise type '%s'", constraint_syntax->lval, promise_type_syntax->promise_type); // Intentional fall case SYNTAX_STATUS_NORMAL: { { SyntaxTypeMatch err = CheckConstraint(P.currenttype, P.lval, P.rval, promise_type_syntax); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { yyerror(SyntaxTypeMatchToString(err)); } } if (P.rval.type == RVAL_TYPE_SCALAR && strcmp(P.lval, "ifvarclass") == 0) { ValidateClassLiteral(P.rval.item); } Constraint *cp = PromiseAppendConstraint(P.currentpromise, P.lval, RvalCopy(P.rval), P.references_body); cp->offset.line = P.line_no; cp->offset.start = P.offsets.last_id; cp->offset.end = P.offsets.current; cp->offset.context = P.offsets.last_class_id; P.currentstype->offset.end = P.offsets.current; // Cache whether there are subbundles for later $(this.promiser) logic if (strcmp(P.lval,"usebundle") == 0 || strcmp(P.lval,"edit_line") == 0 || strcmp(P.lval,"edit_xml") == 0 || strcmp(P.lval,"home_bundle") == 0) { P.currentpromise->has_subbundles = true; } } break; case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed constraint '%s' in promise type '%s'", constraint_syntax->lval, promise_type_syntax->promise_type); break; } } else { ParseError("Unknown constraint '%s' in promise type '%s'", P.lval, promise_type_syntax->promise_type); } RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); strcpy(P.lval,"no lval"); RlistDestroy(P.currentRlist); P.currentRlist = NULL; } else { RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ constraint_id: IDSYNTAX /* BUNDLE ONLY */ { ParserDebug("\tP:%s:%s:%s:%s:%s:%s attribute = %s\n", P.block, P.blocktype, P.blockid, P.currenttype, P.currentclasses ? P.currentclasses : "any", P.promiser, P.currentid); const PromiseTypeSyntax *promise_type_syntax = PromiseTypeSyntaxGet(P.blocktype, P.currenttype); if (!promise_type_syntax) { ParseError("Invalid promise type '%s' in bundle '%s' of type '%s'", P.currenttype, P.blockid, P.blocktype); INSTALL_SKIP = true; } else if (!PromiseTypeSyntaxGetConstraintSyntax(promise_type_syntax, P.currentid)) { ParseError("Unknown attribute '%s' for promise type '%s' in bundle with type '%s'", P.currentid, P.currenttype, P.blocktype); INSTALL_SKIP = true; } strncpy(P.lval,P.currentid,CF_MAXVARSIZE); RlistDestroy(P.currentRlist); P.currentRlist = NULL; } | error { ParseError("Expected attribute, got '%s'\n", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bodybody: body_begin { const BodySyntax *body_syntax = BodySyntaxGet(P.blocktype); if (body_syntax) { INSTALL_SKIP = false; switch (body_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated body '%s' of type '%s'", P.blockid, body_syntax->body_type); // intentional fall case SYNTAX_STATUS_NORMAL: P.currentbody = PolicyAppendBody(P.policy, P.current_namespace, P.blockid, P.blocktype, P.useargs, P.filename); P.currentbody->offset.line = CURRENT_BLOCKID_LINE; P.currentbody->offset.start = P.offsets.last_block_id; break; case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed body '%s' of type '%s'", P.blockid, body_syntax->body_type); INSTALL_SKIP = true; break; } } else { ParseError("Invalid body type '%s'", P.blocktype); INSTALL_SKIP = true; } RlistDestroy(P.useargs); P.useargs = NULL; strcpy(P.currentid,""); } bodyattribs CB { P.offsets.last_id = -1; P.offsets.last_string = -1; P.offsets.last_class_id = -1; if (P.currentbody) { P.currentbody->offset.end = P.offsets.current; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bodyattribs: bodyattrib /* BODY ONLY */ | bodyattribs bodyattrib /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bodyattrib: class | selection_line /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ selection_line: selection ';' | selection error { ParseError("Expected ';' check previous statement, got '%s'", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ selection: selection_id /* BODY ONLY */ assign_type rval { if (!INSTALL_SKIP) { const BodySyntax *body_syntax = BodySyntaxGet(P.blocktype); assert(body_syntax); const ConstraintSyntax *constraint_syntax = BodySyntaxGetConstraintSyntax(body_syntax->constraints, P.lval); if (constraint_syntax) { switch (constraint_syntax->status) { case SYNTAX_STATUS_DEPRECATED: ParseWarning(PARSER_WARNING_DEPRECATED, "Deprecated constraint '%s' in body type '%s'", constraint_syntax->lval, body_syntax->body_type); // Intentional fall case SYNTAX_STATUS_NORMAL: { SyntaxTypeMatch err = CheckSelection(P.blocktype, P.blockid, P.lval, P.rval); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { yyerror(SyntaxTypeMatchToString(err)); } if (P.rval.type == RVAL_TYPE_SCALAR && strcmp(P.lval, "ifvarclass") == 0) { ValidateClassLiteral(P.rval.item); } Constraint *cp = NULL; if (P.currentclasses == NULL) { cp = BodyAppendConstraint(P.currentbody, P.lval, RvalCopy(P.rval), "any", P.references_body); } else { cp = BodyAppendConstraint(P.currentbody, P.lval, RvalCopy(P.rval), P.currentclasses, P.references_body); } cp->offset.line = P.line_no; cp->offset.start = P.offsets.last_id; cp->offset.end = P.offsets.current; cp->offset.context = P.offsets.last_class_id; break; } case SYNTAX_STATUS_REMOVED: ParseWarning(PARSER_WARNING_REMOVED, "Removed constraint '%s' in promise type '%s'", constraint_syntax->lval, body_syntax->body_type); break; } } } else { RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } if (strcmp(P.blockid,"control") == 0 && strcmp(P.blocktype,"file") == 0) { if (strcmp(P.lval,"namespace") == 0) { if (P.rval.type != RVAL_TYPE_SCALAR) { yyerror("namespace must be a constant scalar string"); } else { free(P.current_namespace); P.current_namespace = xstrdup(P.rval.item); } } } RvalDestroy(P.rval); P.rval = RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ selection_id: IDSYNTAX { ParserDebug("\tP:%s:%s:%s:%s attribute = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); if (!INSTALL_SKIP) { const BodySyntax *body_syntax = BodySyntaxGet(P.currentbody->type); if (!body_syntax || !BodySyntaxGetConstraintSyntax(body_syntax->constraints, P.currentid)) { ParseError("Unknown selection '%s' for body type '%s'", P.currentid, P.currentbody->type); INSTALL_SKIP = true; } strncpy(P.lval,P.currentid,CF_MAXVARSIZE); } RlistDestroy(P.currentRlist); P.currentRlist = NULL; } | error { ParserDebug("P:selection_id:idsyntax:error yychar = %d\n", yychar); if ( yychar == BUNDLE || yychar == BODY || yychar == YYEOF ) { ParseError("Expected '}', got '%s'", yytext); /* YYABORT; */ } else { ParseError("Expected attribute, got '%s'", yytext); } yyclearin; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ assign_type: ASSIGN { ParserDebug("\tP:=>\n"); } | error { yyclearin; ParseError("Expected '=>', got '%s'", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ arrow_type: ARROW { ParserDebug("\tP:->\n"); } /* else we display the wrong error | error { yyclearin; ParseError("Expected '->', got '%s'", yytext); } */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ class: CLASS { P.offsets.last_class_id = P.offsets.current - strlen(P.currentclasses) - 2; ParserDebug("\tP:%s:%s:%s:%s class = %s\n", P.block, P.blocktype, P.blockid, P.currenttype, yytext); /* class literal includes terminating :: */ /* Warning : AIX does not like yylen */ char *literal = xstrndup(yytext, strlen(yytext) - 2); ValidateClassLiteral(literal); free(literal); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ rval: IDSYNTAX { ParserDebug("\tP:%s:%s:%s:%s id rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentid); RvalDestroy(P.rval); P.rval = (Rval) { xstrdup(P.currentid), RVAL_TYPE_SCALAR }; P.references_body = true; } | BLOCKID { ParserDebug("\tP:%s:%s:%s:%s blockid rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentid); RvalDestroy(P.rval); P.rval = (Rval) { xstrdup(P.currentid), RVAL_TYPE_SCALAR }; P.references_body = true; } | QSTRING { ParserDebug("\tP:%s:%s:%s:%s qstring rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentstring); RvalDestroy(P.rval); P.rval = (Rval) { P.currentstring, RVAL_TYPE_SCALAR }; P.currentstring = NULL; P.references_body = false; if (P.currentpromise) { if (LvalWantsBody(P.currentpromise->parent_promise_type->name, P.lval)) { yyerror("An rvalue is quoted, but we expect an unquoted body identifier"); } } } | NAKEDVAR { ParserDebug("\tP:%s:%s:%s:%s nakedvar rval, %s = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval, P.currentstring); RvalDestroy(P.rval); P.rval = (Rval) { P.currentstring, RVAL_TYPE_SCALAR }; P.currentstring = NULL; P.references_body = false; } | list { ParserDebug("\tP:%s:%s:%s:%s install list = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.lval); if (RlistLen(P.currentRlist) == 0) { RlistAppendScalar(&P.currentRlist, CF_NULL_VALUE); } RvalDestroy(P.rval); P.rval = (Rval) { RlistCopy(P.currentRlist), RVAL_TYPE_LIST }; RlistDestroy(P.currentRlist); P.currentRlist = NULL; P.references_body = false; } | usefunction { RvalDestroy(P.rval); P.rval = (Rval) { P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL }; P.currentfncall[P.arg_nesting+1] = NULL; P.references_body = false; } | error { yyclearin; ParseError("Invalid r-value type '%s'", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ list: OB litems CB /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ litems: /* empty */ | litem | litem ',' litems | litem error { ParserDebug("P:rval:list:error yychar = %d\n", yychar); if ( yychar ==';' ) { ParseError("Expected '}', wrong input '%s'", yytext); } else if ( yychar == ASSIGN ) { ParseError("Check list statement previous line, Expected '}', wrong input '%s'", yytext); } else { ParseError("Expected ',', wrong input '%s'", yytext); } yyclearin; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ litem: IDSYNTAX { ParserDebug("\tP:%s:%s:%s:%s list append; id = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); RlistAppendScalar((Rlist **)&P.currentRlist, P.currentid); } | QSTRING { ParserDebug("\tP:%s:%s:%s:%s list append: qstring = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentstring); RlistAppendScalar((Rlist **)&P.currentRlist,(void *)P.currentstring); free(P.currentstring); P.currentstring = NULL; } | NAKEDVAR { ParserDebug("\tP:%s:%s:%s:%s list append: nakedvar = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentstring); RlistAppendScalar((Rlist **)&P.currentRlist,(void *)P.currentstring); free(P.currentstring); P.currentstring = NULL; } | usefunction { RlistAppend(&P.currentRlist, P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL); FnCallDestroy(P.currentfncall[P.arg_nesting+1]); P.currentfncall[P.arg_nesting+1] = NULL; } | error { yyclearin; ParseError("Invalid input for a list item, got '%s'", yytext); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ functionid: IDSYNTAX { ParserDebug("\tP:%s:%s:%s:%s function id = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); } | BLOCKID { ParserDebug("\tP:%s:%s:%s:%s function blockid = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentid); } | NAKEDVAR { ParserDebug("\tP:%s:%s:%s:%s function nakedvar = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentstring); strncpy(P.currentid,P.currentstring,CF_MAXVARSIZE); // Make a var look like an ID free(P.currentstring); P.currentstring = NULL; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ usefunction: functionid givearglist { ParserDebug("\tP:%s:%s:%s:%s Finished with function, now at level %d\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.arg_nesting); }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ givearglist: OP { if (++P.arg_nesting >= CF_MAX_NESTING) { fatal_yyerror("Nesting of functions is deeper than recommended"); } P.currentfnid[P.arg_nesting] = xstrdup(P.currentid); ParserDebug("\tP:%s:%s:%s begin givearglist for function %s, level %d\n", P.block,P.blocktype,P.blockid, P.currentfnid[P.arg_nesting], P.arg_nesting ); } gaitems CP { ParserDebug("\tP:%s:%s:%s end givearglist for function %s, level %d\n", P.block,P.blocktype,P.blockid, P.currentfnid[P.arg_nesting], P.arg_nesting ); P.currentfncall[P.arg_nesting] = FnCallNew(P.currentfnid[P.arg_nesting], P.giveargs[P.arg_nesting]); P.giveargs[P.arg_nesting] = NULL; strcpy(P.currentid,""); free(P.currentfnid[P.arg_nesting]); P.currentfnid[P.arg_nesting] = NULL; P.arg_nesting--; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ gaitems: /* empty */ | gaitem | gaitems ',' gaitem | gaitem error { ParseError("Expected ',', wrong input '%s'", yytext); yyclearin; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ gaitem: IDSYNTAX { ParserDebug("\tP:%s:%s:%s:%s function %s, id arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentid); /* currently inside a use function */ RlistAppendScalar(&P.giveargs[P.arg_nesting],P.currentid); } | QSTRING { /* currently inside a use function */ ParserDebug("\tP:%s:%s:%s:%s function %s, qstring arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentstring); RlistAppendScalar(&P.giveargs[P.arg_nesting],P.currentstring); free(P.currentstring); P.currentstring = NULL; } | NAKEDVAR { /* currently inside a use function */ ParserDebug("\tP:%s:%s:%s:%s function %s, nakedvar arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentstring); RlistAppendScalar(&P.giveargs[P.arg_nesting],P.currentstring); free(P.currentstring); P.currentstring = NULL; } | usefunction { /* Careful about recursion */ ParserDebug("\tP:%s:%s:%s:%s function %s, nakedvar arg = %s\n", P.block, P.blocktype, P.blockid, P.currentclasses ? P.currentclasses : "any", P.currentfnid[P.arg_nesting], P.currentstring); RlistAppend(&P.giveargs[P.arg_nesting], P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL); RvalDestroy((Rval) { P.currentfncall[P.arg_nesting+1], RVAL_TYPE_FNCALL }); P.currentfncall[P.arg_nesting+1] = NULL; } | error { ParserDebug("P:rval:function:gaitem:error yychar = %d\n", yychar); if (yychar == ';') { ParseError("Expected ')', wrong input '%s'", yytext); } else if (yychar == ASSIGN ) { ParseError("Check function statement previous line, Expected ')', wrong input '%s'", yytext); } else { ParseError("Invalid function argument, wrong input '%s'", yytext); } yyclearin; } %% /*****************************************************************/ static void ParseErrorVColumnOffset(int column_offset, const char *s, va_list ap) { char *errmsg = StringVFormat(s, ap); fprintf(stderr, "%s:%d:%d: error: %s\n", P.filename, P.line_no, P.line_pos + column_offset, errmsg); free(errmsg); /* FIXME: why this might be NULL? */ if (P.current_line) { fprintf(stderr, "%s\n", P.current_line); fprintf(stderr, "%*s\n", P.line_pos + column_offset, "^"); P.error_count++; if (P.error_count > 12) { fprintf(stderr, "Too many errors\n"); exit(EXIT_FAILURE); } } } static void ParseErrorColumnOffset(int column_offset, const char *s, ...) { va_list ap; va_start(ap, s); ParseErrorVColumnOffset(column_offset, s, ap); va_end(ap); } static void ParseErrorV(const char *s, va_list ap) { ParseErrorVColumnOffset(0, s, ap); } static void ParseError(const char *s, ...) { va_list ap; va_start(ap, s); ParseErrorV(s, ap); va_end(ap); } static void ParseWarningV(unsigned int warning, const char *s, va_list ap) { if (((P.warnings | P.warnings_error) & warning) == 0) { return; } char *errmsg = StringVFormat(s, ap); const char *warning_str = ParserWarningToString(warning); fprintf(stderr, "%s:%d:%d: warning: %s [-W%s]\n", P.filename, P.line_no, P.line_pos, errmsg, warning_str); fprintf(stderr, "%s\n", P.current_line); fprintf(stderr, "%*s\n", P.line_pos, "^"); free(errmsg); P.warning_count++; if ((P.warnings_error & warning) != 0) { P.error_count++; } if (P.error_count > 12) { fprintf(stderr, "Too many errors\n"); exit(EXIT_FAILURE); } } static void ParseWarning(unsigned int warning, const char *s, ...) { va_list ap; va_start(ap, s); ParseWarningV(warning, s, ap); va_end(ap); } void yyerror(const char *str) { ParseError("%s", str); } static void fatal_yyerror(const char *s) { char *sp = yytext; /* Skip quotation mark */ if (sp && *sp == '\"' && sp[1]) { sp++; } fprintf(stderr, "%s: %d,%d: Fatal error during parsing: %s, near token \'%.20s\'\n", P.filename, P.line_no, P.line_pos, s, sp ? sp : "NULL"); exit(EXIT_FAILURE); } static int RelevantBundle(const char *agent, const char *blocktype) { if ((strcmp(agent, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0) || (strcmp(CF_COMMONC, blocktype) == 0)) { return true; } /* Here are some additional bundle types handled by cfAgent */ Item *ip = SplitString("edit_line,edit_xml", ','); if (strcmp(agent, CF_AGENTTYPES[AGENT_TYPE_AGENT]) == 0) { if (IsItemIn(ip, blocktype)) { DeleteItemList(ip); return true; } } DeleteItemList(ip); return false; } static bool LvalWantsBody(char *stype, char *lval) { for (int i = 0; i < CF3_MODULES; i++) { const PromiseTypeSyntax *promise_type_syntax = CF_ALL_PROMISE_TYPES[i]; if (!promise_type_syntax) { continue; } for (int j = 0; promise_type_syntax[j].promise_type != NULL; j++) { const ConstraintSyntax *bs = promise_type_syntax[j].constraints; if (!bs) { continue; } if (strcmp(promise_type_syntax[j].promise_type, stype) != 0) { continue; } for (int l = 0; bs[l].lval != NULL; l++) { if (strcmp(bs[l].lval, lval) == 0) { if (bs[l].dtype == CF_DATA_TYPE_BODY) { return true; } else { return false; } } } } } return false; } static SyntaxTypeMatch CheckSelection(const char *type, const char *name, const char *lval, Rval rval) { // Check internal control bodies etc if (strcmp("control", name) == 0) { for (int i = 0; CONTROL_BODIES[i].body_type != NULL; i++) { if (strcmp(type, CONTROL_BODIES[i].body_type) == 0) { const ConstraintSyntax *bs = CONTROL_BODIES[i].constraints; for (int l = 0; bs[l].lval != NULL; l++) { if (strcmp(lval, bs[l].lval) == 0) { if (bs[l].dtype == CF_DATA_TYPE_BODY) { return SYNTAX_TYPE_MATCH_OK; } else if (bs[l].dtype == CF_DATA_TYPE_BUNDLE) { return SYNTAX_TYPE_MATCH_OK; } else { return CheckConstraintTypeMatch(lval, rval, bs[l].dtype, bs[l].range.validation_string, 0); } } } } } } // Now check the functional modules - extra level of indirection for (int i = 0; i < CF3_MODULES; i++) { const PromiseTypeSyntax *promise_type_syntax = CF_ALL_PROMISE_TYPES[i]; if (!promise_type_syntax) { continue; } for (int j = 0; promise_type_syntax[j].promise_type != NULL; j++) { const ConstraintSyntax *bs = bs = promise_type_syntax[j].constraints; if (!bs) { continue; } for (int l = 0; bs[l].lval != NULL; l++) { if (bs[l].dtype == CF_DATA_TYPE_BODY) { const ConstraintSyntax *bs2 = bs[l].range.body_type_syntax->constraints; if (bs2 == NULL || bs2 == (void *) CF_BUNDLE) { continue; } for (int k = 0; bs2[k].dtype != CF_DATA_TYPE_NONE; k++) { /* Either module defined or common */ if (strcmp(promise_type_syntax[j].promise_type, type) == 0 && strcmp(promise_type_syntax[j].promise_type, "*") != 0) { char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "lval %s belongs to promise type '%s': but this is '%s'\n", lval, promise_type_syntax[j].promise_type, type); yyerror(output); return SYNTAX_TYPE_MATCH_OK; } if (strcmp(lval, bs2[k].lval) == 0) { return CheckConstraintTypeMatch(lval, rval, bs2[k].dtype, bs2[k].range.validation_string, 0); } } } } } } char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "Constraint lvalue \"%s\" is not allowed in \'%s\' constraint body", lval, type); yyerror(output); return SYNTAX_TYPE_MATCH_OK; // TODO: OK? } static SyntaxTypeMatch CheckConstraint(const char *type, const char *lval, Rval rval, const PromiseTypeSyntax *promise_type_syntax) { assert(promise_type_syntax); if (promise_type_syntax->promise_type != NULL) /* In a bundle */ { if (strcmp(promise_type_syntax->promise_type, type) == 0) { const ConstraintSyntax *bs = promise_type_syntax->constraints; for (int l = 0; bs[l].lval != NULL; l++) { if (strcmp(lval, bs[l].lval) == 0) { /* If we get here we have found the lval and it is valid for this promise_type */ /* For bodies and bundles definitions can be elsewhere, so they are checked in PolicyCheckRunnable(). */ if (bs[l].dtype != CF_DATA_TYPE_BODY && bs[l].dtype != CF_DATA_TYPE_BUNDLE) { return CheckConstraintTypeMatch(lval, rval, bs[l].dtype, bs[l].range.validation_string, 0); } } } } } return SYNTAX_TYPE_MATCH_OK; } static void ValidateClassLiteral(const char *class_literal) { ParseResult res = ParseExpression(class_literal, 0, strlen(class_literal)); if (!res.result) { ParseErrorColumnOffset(res.position - strlen(class_literal), "Syntax error in context string"); } FreeExpression(res.result); } cfengine-3.6.2/libpromises/dbm_api.h0000644000175100017510000000564612352557236017135 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_DBM_API_H #define CFENGINE_DBM_API_H #include typedef enum { dbid_classes, dbid_variables, dbid_performance, dbid_checksums, // Deprecated dbid_filestats, // Deprecated dbid_changes, dbid_observations, dbid_state, dbid_lastseen, dbid_audit, dbid_locks, dbid_history, dbid_measure, dbid_static, dbid_scalars, dbid_windows_registry, dbid_cache, dbid_license, dbid_value, dbid_agent_execution, dbid_bundles, dbid_max } dbid; typedef struct DBHandle_ DBHandle; typedef struct DBCursor_ DBCursor; typedef DBHandle CF_DB; typedef DBCursor CF_DBC; bool OpenDB(CF_DB **dbp, dbid db); void CloseDB(CF_DB *dbp); bool HasKeyDB(CF_DB *dbp, const char *key, int key_size); int ValueSizeDB(CF_DB *dbp, const char *key, int key_size); bool ReadComplexKeyDB(CF_DB *dbp, const char *key, int key_size, void *dest, int destSz); bool WriteComplexKeyDB(CF_DB *dbp, const char *key, int keySz, const void *src, int srcSz); bool DeleteComplexKeyDB(CF_DB *dbp, const char *key, int size); bool ReadDB(CF_DB *dbp, const char *key, void *dest, int destSz); bool WriteDB(CF_DB *dbp, const char *key, const void *src, int srcSz); bool DeleteDB(CF_DB *dbp, const char *key); /* * Creating cursor locks the whole database, so keep the amount of work here to * minimum. * * Don't use WriteDB/DeleteDB while iterating database, it will result in * deadlock. Use cursor-specific operations instead. They work on the current * key. */ bool NewDBCursor(CF_DB *dbp, CF_DBC **dbcp); bool NextDB(CF_DBC *dbcp, char **key, int *ksize, void **value, int *vsize); bool DBCursorDeleteEntry(CF_DBC *cursor); bool DBCursorWriteEntry(CF_DBC *cursor, const void *value, int value_size); bool DeleteDBCursor(CF_DBC *dbcp); char *DBIdToPath(const char *workdir, dbid id); int UpdateLastSeenMaxReaders(int maxreaders); StringMap *LoadDatabaseToStringMap(dbid database_id); #endif /* NOT CFENGINE_DBM_API_H */ cfengine-3.6.2/libpromises/vars.h0000644000175100017510000000262612316547775016517 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VARS_H #define CFENGINE_VARS_H #include #include size_t ExtractScalarPrefix(Buffer *out, const char *str, size_t len); bool ExtractScalarReference(Buffer *out, const char *str, size_t len, bool extract_inner); bool RlistIsUnresolved(const Rlist *args); bool IsQualifiedVariable(const char *var); bool StringContainsVar(const char *s, const char *v); bool IsCf3VarString(const char *str); #endif cfengine-3.6.2/libpromises/verify_reports.c0000664000175100017510000001207112411001073020562 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static bool PrintFile(const char *filename, size_t max_lines); static void ReportToFile(const char *logfile, const char *message); static void ReportToLog(const char *message); PromiseResult VerifyReportPromise(EvalContext *ctx, const Promise *pp) { CfLock thislock; char unique_name[CF_EXPANDSIZE]; Attributes a = GetReportsAttributes(ctx, pp); // We let AcquireLock worry about making a unique name snprintf(unique_name, CF_EXPANDSIZE - 1, "%s", pp->promiser); thislock = AcquireLock(ctx, unique_name, VUQNAME, CFSTARTTIME, a.transaction, pp, false); // Handle return values before locks, as we always do this if (a.report.result) { // User-unwritable value last-result contains the useresult if (strlen(a.report.result) > 0) { snprintf(unique_name, CF_BUFSIZE, "last-result[%s]", a.report.result); } else { snprintf(unique_name, CF_BUFSIZE, "last-result"); } VarRef *ref = VarRefParseFromBundle(unique_name, PromiseGetBundle(pp)); EvalContextVariablePut(ctx, ref, pp->promiser, CF_DATA_TYPE_STRING, "source=bundle"); VarRefDestroy(ref); if (thislock.lock) { YieldCurrentLock(thislock); } return PROMISE_RESULT_NOOP; } if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } PromiseBanner(pp); if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_WARN, pp, a, "Need to repair reports promise: %s", pp->promiser); YieldCurrentLock(thislock); return PROMISE_RESULT_WARN; } if (a.report.to_file) { ReportToFile(a.report.to_file, pp->promiser); } else { ReportToLog(pp->promiser); } PromiseResult result = PROMISE_RESULT_NOOP; if (a.report.haveprintfile) { if (!PrintFile(a.report.filename, a.report.numlines)) { result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } YieldCurrentLock(thislock); ClassAuditLog(ctx, pp, a, result); return result; } static void ReportToLog(const char *message) { int report_size = strlen(message) + 4; char report_message[report_size]; xsnprintf(report_message, report_size, "R: %s", message); fprintf(stdout, "%s\n", report_message); LogToSystemLog(report_message, LOG_LEVEL_NOTICE); } static void ReportToFile(const char *logfile, const char *message) { FILE *fp = safe_fopen(logfile, "a"); if (!fp) { Log(LOG_LEVEL_ERR, "Could not open log file '%s', message '%s'. (fopen: %s)", logfile, message, GetErrorStr()); } else { fprintf(fp, "%s\n", message); fclose(fp); } } static bool PrintFile(const char *filename, size_t max_lines) { if (!filename) { Log(LOG_LEVEL_VERBOSE, "Printfile promise was incomplete, with no filename."); return false; } FILE *fp = safe_fopen(filename, "r"); if (!fp) { Log(LOG_LEVEL_ERR, "Printing of file '%s' was not possible. (fopen: %s)", filename, GetErrorStr()); return false; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (size_t i = 0; i < max_lines; i++) { if (CfReadLine(&line, &line_size, fp) == -1) { if (ferror(fp)) { Log(LOG_LEVEL_ERR, "Failed to read line from stream, (getline: %s)", GetErrorStr()); free(line); return false; } else { break; } } ReportToLog(line); } fclose(fp); free(line); return true; } cfengine-3.6.2/libpromises/assoc.h0000664000175100017510000000241412243421446016632 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ASSOC_H #define CFENGINE_ASSOC_H #include /* variable reference linkage , with metatype*/ typedef struct { char *lval; Rval rval; DataType dtype; } CfAssoc; CfAssoc *NewAssoc(const char *lval, Rval rval, DataType dt); void DeleteAssoc(CfAssoc *ap); #endif cfengine-3.6.2/libpromises/Makefile.in0000664000175100017510000012211312412324464017415 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @NT_FALSE@am__append_1 = \ @NT_FALSE@ process_unix.c \ @NT_FALSE@ pipes_unix.c @LINUX_TRUE@@NT_FALSE@am__append_2 = \ @LINUX_TRUE@@NT_FALSE@ process_linux.c @AIX_TRUE@@NT_FALSE@am__append_3 = \ @AIX_TRUE@@NT_FALSE@ process_aix.c @NT_FALSE@@SOLARIS_TRUE@am__append_4 = \ @NT_FALSE@@SOLARIS_TRUE@ process_solaris.c \ @NT_FALSE@@SOLARIS_TRUE@ solaris_ifaddrs.c solaris_ifaddrs.h @AIX_FALSE@@LINUX_FALSE@@NT_FALSE@@SOLARIS_FALSE@am__append_5 = \ @AIX_FALSE@@LINUX_FALSE@@NT_FALSE@@SOLARIS_FALSE@ process_unix_stub.c subdir = libpromises DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am cf3parse.h \ cf3parse.c cf3lex.c $(top_srcdir)/depcomp $(top_srcdir)/ylwrap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(projlibdir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(projlib_LTLIBRARIES) libpromises_la_DEPENDENCIES = ../libutils/libutils.la \ ../libcfnet/libcfnet.la ../libenv/libenv.la am__libpromises_la_SOURCES_DIST = cf3parse.y cf3parse.h cf3lex.l \ acl_tools.h acl_tools_posix.c actuator.c actuator.h addr_lib.c \ addr_lib.h assoc.c assoc.h audit.c audit.h attributes.c \ attributes.h bootstrap.c bootstrap.h cf3.defs.h cf3.extern.h \ cf3globals.c chflags.c chflags.h class.c class.h constants.c \ conversion.c conversion.h crypto.c crypto.h dbm_api.c \ dbm_api.h dbm_priv.h dbm_migration.c dbm_migration.h \ dbm_migration_lastseen.c dbm_migration_bundles.c dbm_lmdb.c \ dbm_quick.c dbm_tokyocab.c enterprise_extension.c \ enterprise_extension.h enterprise_stubs.c eval_context.c \ eval_context.h evalfunction.c evalfunction.h exec_tools.c \ exec_tools.h expand.c expand.h extensions.c extensions.h \ files_copy.c files_copy.h files_hashes.c files_hashes.h \ files_interfaces.c files_interfaces.h files_lib.c files_lib.h \ files_names.c files_names.h fncall.c fncall.h generic_agent.c \ generic_agent.h granules.c granules.h instrumentation.c \ instrumentation.h item_lib.c item_lib.h iteration.c \ iteration.h keyring.c keyring.h known_dirs.c known_dirs.h \ lastseen.c lastseen.h loading.c loading.h locks.c locks.h \ logic_expressions.c logic_expressions.h matching.c matching.h \ math_eval.c math_eval.h mod_access.c mod_access.h mod_common.c \ mod_common.h mod_databases.c mod_databases.h mod_environ.c \ mod_environ.h mod_exec.c mod_exec.h mod_files.c mod_files.h \ mod_measurement.c mod_measurement.h mod_methods.c \ mod_methods.h mod_outputs.c mod_outputs.h mod_packages.c \ mod_packages.h mod_process.c mod_process.h mod_report.c \ mod_report.h mod_services.c mod_services.h mod_storage.c \ mod_storage.h mod_knowledge.c mod_knowledge.h mod_users.c \ mod_users.h modes.c mutex.c mutex.h ornaments.c ornaments.h \ policy.c policy.h parser.c parser.h parser_state.h patches.c \ pipes.h pipes.c processes_select.c processes_select.h \ process_lib.h process_unix_priv.h promises.c promises.h \ prototypes3.h rlist.c rlist.h scope.c scope.h shared_lib.c \ shared_lib.h signals.c signals.h sort.c sort.h storage_tools.c \ string_expressions.c string_expressions.h syntax.c syntax.h \ syslog_client.c syslog_client.h systype.c systype.h timeout.c \ timeout.h unix.c unix.h var_expressions.c var_expressions.h \ vars.c vars.h variable.c variable.h verify_classes.c \ verify_classes.h verify_reports.c verify_vars.c verify_vars.h \ cf-windows-functions.h bootstrap.inc process_unix.c \ pipes_unix.c process_linux.c process_aix.c process_solaris.c \ solaris_ifaddrs.c solaris_ifaddrs.h process_unix_stub.c @NT_FALSE@am__objects_1 = process_unix.lo pipes_unix.lo @LINUX_TRUE@@NT_FALSE@am__objects_2 = process_linux.lo @AIX_TRUE@@NT_FALSE@am__objects_3 = process_aix.lo @NT_FALSE@@SOLARIS_TRUE@am__objects_4 = process_solaris.lo \ @NT_FALSE@@SOLARIS_TRUE@ solaris_ifaddrs.lo @AIX_FALSE@@LINUX_FALSE@@NT_FALSE@@SOLARIS_FALSE@am__objects_5 = process_unix_stub.lo am_libpromises_la_OBJECTS = cf3parse.lo cf3lex.lo acl_tools_posix.lo \ actuator.lo addr_lib.lo assoc.lo audit.lo attributes.lo \ bootstrap.lo cf3globals.lo chflags.lo class.lo constants.lo \ conversion.lo crypto.lo dbm_api.lo dbm_migration.lo \ dbm_migration_lastseen.lo dbm_migration_bundles.lo dbm_lmdb.lo \ dbm_quick.lo dbm_tokyocab.lo enterprise_extension.lo \ enterprise_stubs.lo eval_context.lo evalfunction.lo \ exec_tools.lo expand.lo extensions.lo files_copy.lo \ files_hashes.lo files_interfaces.lo files_lib.lo \ files_names.lo fncall.lo generic_agent.lo granules.lo \ instrumentation.lo item_lib.lo iteration.lo keyring.lo \ known_dirs.lo lastseen.lo loading.lo locks.lo \ logic_expressions.lo matching.lo math_eval.lo mod_access.lo \ mod_common.lo mod_databases.lo mod_environ.lo mod_exec.lo \ mod_files.lo mod_measurement.lo mod_methods.lo mod_outputs.lo \ mod_packages.lo mod_process.lo mod_report.lo mod_services.lo \ mod_storage.lo mod_knowledge.lo mod_users.lo modes.lo mutex.lo \ ornaments.lo policy.lo parser.lo patches.lo pipes.lo \ processes_select.lo promises.lo rlist.lo scope.lo \ shared_lib.lo signals.lo sort.lo storage_tools.lo \ string_expressions.lo syntax.lo syslog_client.lo systype.lo \ timeout.lo unix.lo var_expressions.lo vars.lo variable.lo \ verify_classes.lo verify_reports.lo verify_vars.lo \ $(am__objects_1) $(am__objects_2) $(am__objects_3) \ $(am__objects_4) $(am__objects_5) libpromises_la_OBJECTS = $(am_libpromises_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = @BUILTIN_EXTENSIONS_FALSE@am_libpromises_la_rpath = -rpath \ @BUILTIN_EXTENSIONS_FALSE@ $(projlibdir) @BUILTIN_EXTENSIONS_TRUE@am_libpromises_la_rpath = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = @MAINTAINER_MODE_FALSE@am__skiplex = test -f $@ || LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS) AM_V_LEX = $(am__v_LEX_@AM_V@) am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) am__v_LEX_0 = @echo " LEX " $@; am__v_LEX_1 = YLWRAP = $(top_srcdir)/ylwrap @MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ || am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ -e s/c++$$/h++/ -e s/c$$/h/ YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS) AM_V_YACC = $(am__v_YACC_@AM_V@) am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@) am__v_YACC_0 = @echo " YACC " $@; am__v_YACC_1 = SOURCES = $(libpromises_la_SOURCES) DIST_SOURCES = $(am__libpromises_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = $(LMDB_LIBS) $(TOKYOCABINET_LIBS) $(QDBM_LIBS) \ $(PCRE_LIBS) $(OPENSSL_LIBS) $(SQLITE3_LIBS) $(LIBACL_LIBS) LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ @BUILTIN_EXTENSIONS_FALSE@projlib_LTLIBRARIES = libpromises.la @BUILTIN_EXTENSIONS_FALSE@AM_LDFLAGS = -version-info 3:6:0 \ @BUILTIN_EXTENSIONS_FALSE@ -no-undefined $(LMDB_LDFLAGS) \ @BUILTIN_EXTENSIONS_FALSE@ $(TOKYOCABINET_LDFLAGS) \ @BUILTIN_EXTENSIONS_FALSE@ $(QDBM_LDFLAGS) $(PCRE_LDFLAGS) \ @BUILTIN_EXTENSIONS_FALSE@ $(OPENSSL_LDFLAGS) \ @BUILTIN_EXTENSIONS_FALSE@ $(SQLITE3_LDFLAGS) $(LIBACL_LDFLAGS) @BUILTIN_EXTENSIONS_TRUE@AM_LDFLAGS = $(LMDB_LDFLAGS) \ @BUILTIN_EXTENSIONS_TRUE@ $(TOKYOCABINET_LDFLAGS) \ @BUILTIN_EXTENSIONS_TRUE@ $(QDBM_LDFLAGS) $(PCRE_LDFLAGS) \ @BUILTIN_EXTENSIONS_TRUE@ $(OPENSSL_LDFLAGS) $(SQLITE3_LDFLAGS) \ @BUILTIN_EXTENSIONS_TRUE@ $(LIBACL_LDFLAGS) @BUILTIN_EXTENSIONS_TRUE@noinst_LTLIBRARIES = libpromises.la EXTRA_DIST = extensions_template.c extensions_template.h enterprise_extension.sed math.pc AM_CPPFLAGS = \ -I$(srcdir)/../libutils -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv $(ENTERPRISE_CPPFLAGS) \ $(LMDB_CPPFLAGS) $(TOKYOCABINET_CPPFLAGS) $(QDBM_CPPFLAGS) \ $(PCRE_CPPFLAGS) $(OPENSSL_CPPFLAGS) $(SQLITE3_CPPFLAGS) $(LIBACL_CPPFLAGS) AM_CFLAGS = $(ENTERPRISE_CFLAGS) \ $(LMDB_CFLAGS) $(TOKYOCABINET_CFLAGS) $(QDBM_CFLAGS) \ $(PCRE_CFLAGS) $(OPENSSL_CFLAGS) $(SQLITE3_CFLAGS) $(LIBACL_CFLAGS) AM_YFLAGS = -d libpromises_la_LIBADD = ../libutils/libutils.la ../libcfnet/libcfnet.la \ ../libenv/libenv.la $(ENTERPRISE_LDADD) libpromises_la_SOURCES = cf3parse.y cf3parse.h cf3lex.l acl_tools.h \ acl_tools_posix.c actuator.c actuator.h addr_lib.c addr_lib.h \ assoc.c assoc.h audit.c audit.h attributes.c attributes.h \ bootstrap.c bootstrap.h cf3.defs.h cf3.extern.h cf3globals.c \ chflags.c chflags.h class.c class.h constants.c conversion.c \ conversion.h crypto.c crypto.h dbm_api.c dbm_api.h dbm_priv.h \ dbm_migration.c dbm_migration.h dbm_migration_lastseen.c \ dbm_migration_bundles.c dbm_lmdb.c dbm_quick.c dbm_tokyocab.c \ enterprise_extension.c enterprise_extension.h \ enterprise_stubs.c eval_context.c eval_context.h \ evalfunction.c evalfunction.h exec_tools.c exec_tools.h \ expand.c expand.h extensions.c extensions.h files_copy.c \ files_copy.h files_hashes.c files_hashes.h files_interfaces.c \ files_interfaces.h files_lib.c files_lib.h files_names.c \ files_names.h fncall.c fncall.h generic_agent.c \ generic_agent.h granules.c granules.h instrumentation.c \ instrumentation.h item_lib.c item_lib.h iteration.c \ iteration.h keyring.c keyring.h known_dirs.c known_dirs.h \ lastseen.c lastseen.h loading.c loading.h locks.c locks.h \ logic_expressions.c logic_expressions.h matching.c matching.h \ math_eval.c math_eval.h mod_access.c mod_access.h mod_common.c \ mod_common.h mod_databases.c mod_databases.h mod_environ.c \ mod_environ.h mod_exec.c mod_exec.h mod_files.c mod_files.h \ mod_measurement.c mod_measurement.h mod_methods.c \ mod_methods.h mod_outputs.c mod_outputs.h mod_packages.c \ mod_packages.h mod_process.c mod_process.h mod_report.c \ mod_report.h mod_services.c mod_services.h mod_storage.c \ mod_storage.h mod_knowledge.c mod_knowledge.h mod_users.c \ mod_users.h modes.c mutex.c mutex.h ornaments.c ornaments.h \ policy.c policy.h parser.c parser.h parser_state.h patches.c \ pipes.h pipes.c processes_select.c processes_select.h \ process_lib.h process_unix_priv.h promises.c promises.h \ prototypes3.h rlist.c rlist.h scope.c scope.h shared_lib.c \ shared_lib.h signals.c signals.h sort.c sort.h storage_tools.c \ string_expressions.c string_expressions.h syntax.c syntax.h \ syslog_client.c syslog_client.h systype.c systype.h timeout.c \ timeout.h unix.c unix.h var_expressions.c var_expressions.h \ vars.c vars.h variable.c variable.h verify_classes.c \ verify_classes.h verify_reports.c verify_vars.c verify_vars.h \ cf-windows-functions.h bootstrap.inc $(am__append_1) \ $(am__append_2) $(am__append_3) $(am__append_4) \ $(am__append_5) BUILT_SOURCES = cf3lex.c cf3parse.h cf3parse.c \ enterprise_extension.c \ enterprise_extension.h ENTERPRISE_EXTENSION_GENERATE = $(SED) -f $(srcdir)/enterprise_extension.sed $< > $@ ENTERPRISE_EXTENSION_MAKE = @if test -z "$(V)"; then echo " SED " $@; else echo "$(ENTERPRISE_EXTENSION_GENERATE)"; fi; $(ENTERPRISE_EXTENSION_GENERATE) CLEANFILES = *.gcno *.gcda $(BUILT_SOURCES) # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .l .lo .o .obj .y $(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) --foreign libpromises/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libpromises/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } install-projlibLTLIBRARIES: $(projlib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(projlib_LTLIBRARIES)'; test -n "$(projlibdir)" || 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)$(projlibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(projlibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(projlibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(projlibdir)"; \ } uninstall-projlibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(projlib_LTLIBRARIES)'; test -n "$(projlibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(projlibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(projlibdir)/$$f"; \ done clean-projlibLTLIBRARIES: -test -z "$(projlib_LTLIBRARIES)" || rm -f $(projlib_LTLIBRARIES) @list='$(projlib_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}; \ } cf3parse.h: cf3parse.c @if test ! -f $@; then rm -f cf3parse.c; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) cf3parse.c; else :; fi libpromises.la: $(libpromises_la_OBJECTS) $(libpromises_la_DEPENDENCIES) $(EXTRA_libpromises_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libpromises_la_rpath) $(libpromises_la_OBJECTS) $(libpromises_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl_tools_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actuator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addr_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assoc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attributes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bootstrap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf3globals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf3lex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf3parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chflags.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/class.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_lmdb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_migration.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_migration_bundles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_migration_lastseen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_quick.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbm_tokyocab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enterprise_extension.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enterprise_stubs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval_context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evalfunction.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec_tools.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expand.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extensions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_copy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_hashes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_interfaces.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_names.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fncall.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic_agent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/granules.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrumentation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/item_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iteration.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyring.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/known_dirs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lastseen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loading.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/locks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logic_expressions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matching.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/math_eval.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_access.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_databases.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_environ.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_exec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_files.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_knowledge.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_measurement.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_methods.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_outputs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_packages.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_process.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_report.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_services.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mod_users.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mutex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ornaments.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patches.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipes_unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_aix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_solaris.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process_unix_stub.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processes_select.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/promises.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scope.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shared_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/solaris_ifaddrs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage_tools.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_expressions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syntax.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/systype.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var_expressions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/variable.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vars.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_classes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_reports.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_vars.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< .l.c: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .y.c: $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(projlibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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." -rm -f cf3lex.c -rm -f cf3parse.c -rm -f cf3parse.h -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ clean-projlibLTLIBRARIES 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-projlibLTLIBRARIES 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: uninstall-projlibLTLIBRARIES .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-projlibLTLIBRARIES \ cscopelist-am ctags ctags-am 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-projlibLTLIBRARIES 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 tags-am uninstall \ uninstall-am uninstall-projlibLTLIBRARIES enterprise_extension.c: extensions_template.c enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) enterprise_extension.h: extensions_template.h enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) bootstrap.inc: perl ./text2cstring.pl failsafe.cf > bootstrap.inc # 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: cfengine-3.6.2/libpromises/mod_outputs.h0000664000175100017510000000216712243421446020111 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_OUTPUTS_H #define CFENGINE_MOD_OUTPUTS_H #include extern const PromiseTypeSyntax CF_OUTPUTS_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/actuator.h0000644000175100017510000000241612316547775017363 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ACTUATOR_H #define CFENGINE_ACTUATOR_H #include typedef PromiseResult PromiseActuator(EvalContext *ctx, const Promise *pp, void *param); PromiseResult PromiseResultUpdate(PromiseResult prior, PromiseResult evidence); bool PromiseResultIsOK(PromiseResult result); #endif cfengine-3.6.2/libpromises/rlist.h0000644000175100017510000000674212332665147016674 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_RLIST_H #define CFENGINE_RLIST_H #include #include #include struct Rlist_ { Rval val; Rlist *next; }; RvalType DataTypeToRvalType(DataType datatype); char *RvalScalarValue(Rval rval); FnCall *RvalFnCallValue(Rval rval); Rlist *RvalRlistValue(Rval rval); JsonElement *RvalContainerValue(Rval rval); const char *RvalTypeToString(RvalType type); Rval RvalNew(const void *item, RvalType type); Rval RvalCopy(Rval rval); void RvalDestroy(Rval rval); JsonElement *RvalToJson(Rval rval); char *RvalToString(Rval rval); void RvalWrite(Writer *writer, Rval rval); void RvalWriteParts(Writer *writer, const void* item, RvalType type); unsigned RvalHash(Rval rval, unsigned seed, unsigned max); Rlist *RlistCopy(const Rlist *list); unsigned RlistHash(const Rlist *list, unsigned seed, unsigned max); void RlistDestroy(Rlist *list); void RlistDestroyEntry(Rlist **liststart, Rlist *entry); char *RlistScalarValue(const Rlist *rlist); FnCall *RlistFnCallValue(const Rlist *rlist); Rlist *RlistRlistValue(const Rlist *rlist); Rlist *RlistParseShown(const char *string); Rlist *RlistParseString(const char *string); Rlist *RlistKeyIn(Rlist *list, const char *key); int RlistLen(const Rlist *start); bool RlistMatchesRegexRlist(const Rlist *list, const Rlist *search); bool RlistMatchesRegex(const Rlist *list, const char *str); bool RlistIsInListOfRegex(const Rlist *list, const char *str); bool RlistIsNullList(const Rlist *list); Rlist *RlistAppendRval(Rlist **start, Rval rval); Rlist *RlistPrependScalarIdemp(Rlist **start, const char *scalar); Rlist *RlistAppendScalarIdemp(Rlist **start, const char *scalar); Rlist *RlistAppendScalar(Rlist **start, const char *scalar); Rlist *RlistPrepend(Rlist **start, const void *item, RvalType type); Rlist *RlistAppend(Rlist **start, const void *item, RvalType type); Rlist *RlistFromSplitString(const char *string, char sep); Rlist *RlistFromSplitRegex(const char *string, const char *regex, size_t max_entries, bool allow_blanks); Rlist *RlistFromRegexSplitNoOverflow(const char *string, const char *regex, int max); void RlistWrite(Writer *writer, const Rlist *list); Rlist *RlistLast(Rlist *start); void RlistFilter(Rlist **list, bool (*KeepPredicate)(void *item, void *predicate_data), void *predicate_user_data, void (*DestroyItem)(void *item)); void RlistReverse(Rlist **list); /** * @brief Flattens an Rlist by expanding naked scalar list-variable members. Flattening is only one-level deep. */ void RlistFlatten(EvalContext *ctx, Rlist **list); #endif cfengine-3.6.2/libpromises/verify_vars.c0000664000175100017510000005305112411001073020042 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include /* CompileRegex,StringMatchFullWithPrecompiledRegex */ #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { bool should_converge; bool ok_redefine; bool drop_undefined; Constraint *cp_save; // e.g. string => "foo" } ConvergeVariableOptions; static ConvergeVariableOptions CollectConvergeVariableOptions(EvalContext *ctx, const Promise *pp, bool allow_redefine); static bool Epimenides(EvalContext *ctx, const char *ns, const char *scope, const char *var, Rval rval, int level); static int CompareRval(const void *rval1_item, RvalType rval1_type, const void *rval2_item, RvalType rval2_type); static bool IsValidVariableName(const char *var_name) { /* TODO: remove at some point (global, leaked), but for now * this offers an attractive speedup. */ static pcre *rx = NULL; if (!rx) { rx = CompileRegex("[a-zA-Z0-9_\200-\377.]+(\\[.+\\])*"); /* Known leak, see TODO. */ } return StringMatchFullWithPrecompiledRegex(rx, var_name); } PromiseResult VerifyVarPromise(EvalContext *ctx, const Promise *pp, bool allow_duplicates) { ConvergeVariableOptions opts = CollectConvergeVariableOptions(ctx, pp, allow_duplicates); if (!opts.should_converge) { return PROMISE_RESULT_NOOP; } Attributes a = { {0} }; // More consideration needs to be given to using these //a.transaction = GetTransactionConstraints(pp); a.classes = GetClassDefinitionConstraints(ctx, pp); VarRef *ref = VarRefParseFromBundle(pp->promiser, PromiseGetBundle(pp)); if (strcmp("meta", pp->parent_promise_type->name) == 0) { VarRefSetMeta(ref, true); } DataType existing_value_type = CF_DATA_TYPE_NONE; const void *const existing_value = IsExpandable(pp->promiser) ? NULL : EvalContextVariableGet(ctx, ref, &existing_value_type); PromiseResult result = PROMISE_RESULT_NOOP; Rval rval = opts.cp_save->rval; if (rval.item != NULL) { DataType data_type = DataTypeFromString(opts.cp_save->lval); if (opts.cp_save->rval.type == RVAL_TYPE_FNCALL) { FnCall *fp = RvalFnCallValue(rval); const FnCallType *fn = FnCallTypeGet(fp->name); if (!fn) { assert(false && "Canary: should have been caught before this point"); FatalError(ctx, "While setting variable '%s' in bundle '%s', unknown function '%s'", pp->promiser, PromiseGetBundle(pp)->name, fp->name); } if (fn->dtype != DataTypeFromString(opts.cp_save->lval)) { FatalError(ctx, "While setting variable '%s' in bundle '%s', variable declared type '%s' but function '%s' returns type '%s'", pp->promiser, PromiseGetBundle(pp)->name, opts.cp_save->lval, fp->name, DataTypeToString(fn->dtype)); } if (existing_value_type != CF_DATA_TYPE_NONE) { // Already did this VarRefDestroy(ref); return PROMISE_RESULT_NOOP; } FnCallResult res = FnCallEvaluate(ctx, PromiseGetPolicy(pp), fp, pp); if (res.status == FNCALL_FAILURE) { /* We do not assign variables to failed fn calls */ RvalDestroy(res.rval); VarRefDestroy(ref); return PROMISE_RESULT_NOOP; } else { rval = res.rval; } } else { Buffer *conv = BufferNew(); bool malformed = false, misprint = false; if (strcmp(opts.cp_save->lval, "int") == 0) { long int asint = IntFromString(opts.cp_save->rval.item); if (asint == CF_NOINT) { malformed = true; } else if (0 > BufferPrintf(conv, "%ld", asint)) { misprint = true; } else { rval = RvalNew(BufferData(conv), opts.cp_save->rval.type); } } else if (strcmp(opts.cp_save->lval, "real") == 0) { double real_value; if (!DoubleFromString(opts.cp_save->rval.item, &real_value)) { malformed = true; } else if (0 > BufferPrintf(conv, "%lf", real_value)) { misprint = true; } else { rval = RvalNew(BufferData(conv), opts.cp_save->rval.type); } } else { rval = RvalCopy(opts.cp_save->rval); } BufferDestroy(conv); if (malformed) { /* Arises when opts->cp_save->rval.item isn't yet expanded. */ /* Has already been logged by *FromString */ VarRefDestroy(ref); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else if (misprint) { /* Even though no problems with memory allocation can * get here, there might be other problems. */ UnexpectedError("Problems writing to buffer"); VarRefDestroy(ref); return PROMISE_RESULT_NOOP; } else if (rval.type == RVAL_TYPE_LIST) { Rlist *rval_list = RvalRlistValue(rval); RlistFlatten(ctx, &rval_list); rval.item = rval_list; } } if (Epimenides(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, pp->promiser, rval, 0)) { Log(LOG_LEVEL_ERR, "Variable '%s' contains itself indirectly - an unkeepable promise", pp->promiser); exit(EXIT_FAILURE); } else { /* See if the variable needs recursively expanding again */ Rval returnval = EvaluateFinalRval(ctx, PromiseGetPolicy(pp), ref->ns, ref->scope, rval, true, pp); RvalDestroy(rval); // freed before function exit rval = returnval; } if (existing_value_type != CF_DATA_TYPE_NONE) { if (!opts.ok_redefine) /* only on second iteration, else we ignore broken promises */ { if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON && !CompareRval(existing_value, DataTypeToRvalType(existing_value_type), rval.item, rval.type)) { switch (rval.type) { case RVAL_TYPE_SCALAR: Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant scalar '%s', was '%s' now '%s'", pp->promiser, (const char *)existing_value, RvalScalarValue(rval)); PromiseRef(LOG_LEVEL_VERBOSE, pp); break; case RVAL_TYPE_LIST: { Log(LOG_LEVEL_VERBOSE, "Redefinition of a constant list '%s'", pp->promiser); Writer *w = StringWriter(); RlistWrite(w, existing_value); char *oldstr = StringWriterClose(w); Log(LOG_LEVEL_VERBOSE, "Old value '%s'", oldstr); free(oldstr); w = StringWriter(); RlistWrite(w, rval.item); char *newstr = StringWriterClose(w); Log(LOG_LEVEL_VERBOSE, " New value '%s'", newstr); free(newstr); PromiseRef(LOG_LEVEL_VERBOSE, pp); } break; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: break; } } RvalDestroy(rval); VarRefDestroy(ref); return result; } } if (IsCf3VarString(pp->promiser)) { // Unexpanded variables, we don't do anything with RvalDestroy(rval); VarRefDestroy(ref); return result; } if (!IsValidVariableName(pp->promiser)) { Log(LOG_LEVEL_ERR, "Variable identifier contains illegal characters"); PromiseRef(LOG_LEVEL_ERR, pp); RvalDestroy(rval); VarRefDestroy(ref); return result; } if (rval.type == RVAL_TYPE_LIST) { if (opts.drop_undefined) { Rlist *stripped = RvalRlistValue(rval); Rlist *entry = stripped; while (entry) { Rlist *delete_me = NULL; if (IsNakedVar(RlistScalarValue(entry), '@')) { delete_me = entry; } entry = entry->next; RlistDestroyEntry(&stripped, delete_me); } rval.item = stripped; } for (const Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: break; default: // Cannot assign variable because value is a list containing a non-scalar item VarRefDestroy(ref); RvalDestroy(rval); return result; } } } if (ref->num_indices > 0) { if (data_type == CF_DATA_TYPE_CONTAINER) { char *lval_str = VarRefToString(ref, true); Log(LOG_LEVEL_ERR, "Cannot assign a container to an indexed variable name '%s'. Should be assigned to '%s' instead", lval_str, ref->lval); free(lval_str); VarRefDestroy(ref); RvalDestroy(rval); return result; } else { DataType existing_type = CF_DATA_TYPE_NONE; VarRef *base_ref = VarRefCopyIndexless(ref); if (EvalContextVariableGet(ctx, ref, &existing_type) && existing_type == CF_DATA_TYPE_CONTAINER) { char *lval_str = VarRefToString(ref, true); char *base_ref_str = VarRefToString(base_ref, true); Log(LOG_LEVEL_ERR, "Cannot assign value to indexed variable name '%s', because a container is already assigned to the base name '%s'", lval_str, base_ref_str); free(lval_str); free(base_ref_str); VarRefDestroy(base_ref); VarRefDestroy(ref); RvalDestroy(rval); return result; } VarRefDestroy(base_ref); } } DataType required_datatype = DataTypeFromString(opts.cp_save->lval); if (rval.type != DataTypeToRvalType(required_datatype)) { char *ref_str = VarRefToString(ref, true); char *value_str = RvalToString(rval); Log(LOG_LEVEL_ERR, "Variable '%s' expected a variable of type '%s', but was given incompatible value '%s'", ref_str, DataTypeToString(required_datatype), value_str); PromiseRef(LOG_LEVEL_ERR, pp); free(ref_str); free(value_str); VarRefDestroy(ref); RvalDestroy(rval); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } if (!EvalContextVariablePut(ctx, ref, rval.item, required_datatype, "source=promise")) { Log(LOG_LEVEL_VERBOSE, "Unable to converge %s.%s value (possibly empty or infinite regression)", ref->scope, pp->promiser); PromiseRef(LOG_LEVEL_VERBOSE, pp); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { Rlist *promise_meta = PromiseGetConstraintAsList(ctx, "meta", pp); if (promise_meta) { StringSet *class_meta = EvalContextVariableTags(ctx, ref); Buffer *print; for (const Rlist *rp = promise_meta; rp; rp = rp->next) { StringSetAdd(class_meta, xstrdup(RlistScalarValue(rp))); print = StringSetToBuffer(class_meta, ','); Log(LOG_LEVEL_DEBUG, "Added tag %s to class %s, tags now [%s]", RlistScalarValue(rp), pp->promiser, BufferData(print)); BufferDestroy(print); } } } } else { Log(LOG_LEVEL_ERR, "Variable %s has no promised value", pp->promiser); Log(LOG_LEVEL_ERR, "Rule from %s at/before line %zu", PromiseGetBundle(pp)->source_path, opts.cp_save->offset.line); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } /* * FIXME: Variable promise are exempt from normal evaluation logic still, so * they are not pushed to evaluation stack before being evaluated. Due to * this reason, we cannot call cfPS here to set classes, as it will error * out with ProgrammingError. * * In order to support 'classes' body for variables as well, we call * ClassAuditLog explicitly. */ ClassAuditLog(ctx, pp, a, result); VarRefDestroy(ref); RvalDestroy(rval); return result; } // FIX: this function is a mixture of Equal/Compare (boolean/diff). // somebody is bound to misuse this at some point static int CompareRlist(const Rlist *list1, const Rlist *list2) { const Rlist *rp1, *rp2; for (rp1 = list1, rp2 = list2; rp1 != NULL && rp2 != NULL; rp1 = rp1->next, rp2 = rp2->next) { if (rp1->val.item && rp2->val.item) { const Rlist *rc1, *rc2; if (rp1->val.type == RVAL_TYPE_FNCALL || rp2->val.type == RVAL_TYPE_FNCALL) { return -1; // inconclusive } rc1 = rp1; rc2 = rp2; // Check for list nesting with { fncall(), "x" ... } if (rp1->val.type == RVAL_TYPE_LIST) { rc1 = rp1->val.item; } if (rp2->val.type == RVAL_TYPE_LIST) { rc2 = rp2->val.item; } if (IsCf3VarString(rc1->val.item) || IsCf3VarString(rp2->val.item)) { return -1; // inconclusive } if (strcmp(rc1->val.item, rc2->val.item) != 0) { return false; } } else { return false; } } return true; } static int CompareRval(const void *rval1_item, RvalType rval1_type, const void *rval2_item, RvalType rval2_type) { if (rval1_type != rval2_type) { return -1; } switch (rval1_type) { case RVAL_TYPE_SCALAR: if (IsCf3VarString(rval1_item) || IsCf3VarString(rval2_item)) { return -1; // inconclusive } if (strcmp(rval1_item, rval2_item) != 0) { return false; } break; case RVAL_TYPE_LIST: return CompareRlist(rval1_item, rval2_item); case RVAL_TYPE_FNCALL: return -1; default: return -1; } return true; } static bool Epimenides(EvalContext *ctx, const char *ns, const char *scope, const char *var, Rval rval, int level) { switch (rval.type) { case RVAL_TYPE_SCALAR: if (StringContainsVar(RvalScalarValue(rval), var)) { Log(LOG_LEVEL_ERR, "Scalar variable '%s' contains itself (non-convergent) '%s'", var, RvalScalarValue(rval)); return true; } if (IsCf3VarString(RvalScalarValue(rval))) { Buffer *exp = BufferNew(); ExpandScalar(ctx, ns, scope, RvalScalarValue(rval), exp); if (strcmp(BufferData(exp), RvalScalarValue(rval)) == 0) { BufferDestroy(exp); return false; } if (level > 3) { BufferDestroy(exp); return false; } if (Epimenides(ctx, ns, scope, var, (Rval) { BufferGet(exp), RVAL_TYPE_SCALAR}, level + 1)) { BufferDestroy(exp); return true; } BufferDestroy(exp); } break; case RVAL_TYPE_LIST: for (const Rlist *rp = RvalRlistValue(rval); rp != NULL; rp = rp->next) { if (Epimenides(ctx, ns, scope, var, rp->val, level)) { return true; } } break; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: return false; } return false; } /** * @brief Collects variable constraints controlling how the promise should be converged */ static ConvergeVariableOptions CollectConvergeVariableOptions(EvalContext *ctx, const Promise *pp, bool allow_redefine) { ConvergeVariableOptions opts = { 0 }; opts.should_converge = false; opts.drop_undefined = false; opts.ok_redefine = allow_redefine; opts.cp_save = NULL; if (!IsDefinedClass(ctx, pp->classes)) { return opts; } int num_values = 0; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, "comment") == 0) { continue; } if (cp->rval.item == NULL) { continue; } if (strcmp(cp->lval, "ifvarclass") == 0) { switch (cp->rval.type) { case RVAL_TYPE_SCALAR: if (!IsDefinedClass(ctx, cp->rval.item)) { return opts; } break; case RVAL_TYPE_FNCALL: { bool excluded = false; /* eval it: e.g. ifvarclass => not("a_class") */ Rval res = FnCallEvaluate(ctx, PromiseGetPolicy(pp), cp->rval.item, pp).rval; /* Don't continue unless function was evaluated properly */ if (res.type != RVAL_TYPE_SCALAR) { RvalDestroy(res); return opts; } excluded = !IsDefinedClass(ctx, res.item); RvalDestroy(res); if (excluded) { return opts; } } break; default: Log(LOG_LEVEL_ERR, "Invalid ifvarclass type '%c': should be string or function", cp->rval.type); continue; } continue; } if (strcmp(cp->lval, "policy") == 0) { if (strcmp(cp->rval.item, "ifdefined") == 0) { opts.drop_undefined = true; opts.ok_redefine = false; } else if (strcmp(cp->rval.item, "constant") == 0) { opts.ok_redefine = false; } else { opts.ok_redefine |= true; } opts.ok_redefine &= allow_redefine; } else if (DataTypeFromString(cp->lval) != CF_DATA_TYPE_NONE) { num_values++; opts.cp_save = cp; } } if (opts.cp_save == NULL) { Log(LOG_LEVEL_WARNING, "Variable body for '%s' seems incomplete", pp->promiser); PromiseRef(LOG_LEVEL_INFO, pp); return opts; } if (num_values > 2) { Log(LOG_LEVEL_ERR, "Variable '%s' breaks its own promise with multiple values (code %d)", pp->promiser, num_values); PromiseRef(LOG_LEVEL_ERR, pp); return opts; } opts.should_converge = true; return opts; } cfengine-3.6.2/libpromises/mod_outputs.c0000664000175100017510000000322712243421446020102 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax CF_OUTPUTS_BODIES[] = { ConstraintSyntaxNewOption("output_level", "verbose,debug,inform", "Output level to observe for the named promise or bundle (meta-promise). Default value: verbose", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("promiser_type", "promise,bundle", "Output level to observe for the named promise or bundle (meta-promise). Default value: promise", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_OUTPUTS_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "outputs", CF_OUTPUTS_BODIES, NULL, SYNTAX_STATUS_REMOVED), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/pipes.c0000664000175100017510000000257612243421446016646 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include bool PipeTypeIsOk(const char *type) { if (type[0] != 'r' && type[0] != 'w') { return false; } else if (type[1] != 't') { if (type[1] == '\0') { return true; } else { return false; } } else if (type[2] == '\0') { return true; } else { return false; } } cfengine-3.6.2/libpromises/bootstrap.c0000664000175100017510000002067012400110676017531 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include // PrintVersionBanner #include #include #include #include #include #include /* Bootstrapping is a tricky sequence of fragile events. We need to map shakey/IP and identify policy hub IP in a special order to bootstrap the license and agents. During commercial bootstrap: - InitGA (generic-agent) loads the public key - The verifylicense function sets the policy hub but fails to verify license yet as there is no key/IP binding - Policy server gets set in workdir/state/am_policy_hub - The agents gets run and start this all over again, but this time the am_policy_hub is defined and caches the key/IP binding - Now the license has a binding, resolves the policy hub's key and succeeds */ /*****************************************************************************/ #if defined(__CYGWIN__) || defined(__ANDROID__) bool BootstrapAllowed(void) { return true; } #elif !defined(__MINGW32__) bool BootstrapAllowed(void) { return IsPrivileged(); } #endif /*****************************************************************************/ static char *AmPolicyHubFilename(const char *workdir) { return StringFormat("%s%cstate%cam_policy_hub", workdir, FILE_SEPARATOR, FILE_SEPARATOR); } bool WriteAmPolicyHubFile(const char *workdir, bool am_policy_hub) { char *filename = AmPolicyHubFilename(workdir); if (am_policy_hub) { if (!GetAmPolicyHub(workdir)) { if (creat(filename, 0600) == -1) { Log(LOG_LEVEL_ERR, "Error writing marker file '%s'", filename); free(filename); return false; } } } else { if (GetAmPolicyHub(workdir)) { if (unlink(filename) != 0) { Log(LOG_LEVEL_ERR, "Error removing marker file '%s'", filename); free(filename); return false; } } } free(filename); return true; } /* NULL is an acceptable value for new_policy_server. Could happen when an * already bootstrapped server re-parses its policies, and the * policy_server.dat file has been removed. Then this function will be called * with NULL as new_policy_server, and cf-serverd will keep running even * without a policy server set. */ void SetPolicyServer(EvalContext *ctx, const char *new_policy_server) { if (new_policy_server) { xsnprintf(POLICY_SERVER, CF_MAX_IP_LEN, "%s", new_policy_server); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "policy_hub", new_policy_server, CF_DATA_TYPE_STRING, "source=bootstrap"); } else { strcpy(POLICY_SERVER, ""); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "policy_hub"); } } /* Set "sys.last_policy_update" variable. */ void UpdateLastPolicyUpdateTime(EvalContext *ctx) { // Get the timestamp on policy update struct stat sb; { char cf_promises_validated_filename[CF_MAXVARSIZE]; snprintf(cf_promises_validated_filename, CF_MAXVARSIZE, "%s/cf_promises_validated", GetMasterDir()); MapName(cf_promises_validated_filename); if ((stat(cf_promises_validated_filename, &sb)) != 0) { return; } } char timebuf[26]; cf_strtimestamp_local(sb.st_mtime, timebuf); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "last_policy_update", timebuf, CF_DATA_TYPE_STRING, "source=agent"); } static char *PolicyServerFilename(const char *workdir) { return StringFormat("%s%cpolicy_server.dat", workdir, FILE_SEPARATOR); } char *ReadPolicyServerFile(const char *workdir) { char contents[CF_MAX_IP_LEN] = ""; char *filename = PolicyServerFilename(workdir); FILE *fp = fopen(filename, "r"); free(filename); if (fp) { if (fscanf(fp, "%63s", contents) != 1) { fclose(fp); return NULL; } fclose(fp); return xstrdup(contents); } else { return NULL; } } bool WritePolicyServerFile(const char *workdir, const char *new_policy_server) { char *filename = PolicyServerFilename(workdir); FILE *file = fopen(filename, "w"); if (!file) { Log(LOG_LEVEL_ERR, "Unable to write policy server file '%s' (fopen: %s)", filename, GetErrorStr()); free(filename); return false; } fprintf(file, "%s", new_policy_server); fclose(file); free(filename); return true; } bool RemovePolicyServerFile(const char *workdir) { char *filename = PolicyServerFilename(workdir); if (unlink(filename) != 0) { Log(LOG_LEVEL_ERR, "Unable to remove file '%s'. (unlink: %s)", filename, GetErrorStr()); free(filename); return false; } return true; } bool GetAmPolicyHub(const char *workdir) { char path[CF_BUFSIZE] = { 0 }; snprintf(path, sizeof(path), "%s/state/am_policy_hub", workdir); MapName(path); struct stat sb; return stat(path, &sb) == 0; } bool RemoveAllExistingPolicyInInputs(const char *inputs_path) { Log(LOG_LEVEL_INFO, "Removing all files in '%s'", inputs_path); struct stat sb; if (stat(inputs_path, &sb) == -1) { if (errno == ENOENT) { return true; } else { Log(LOG_LEVEL_ERR, "Could not stat inputs directory at '%s'. (stat: %s)", inputs_path, GetErrorStr()); return false; } } if (!S_ISDIR(sb.st_mode)) { Log(LOG_LEVEL_ERR, "Inputs path exists at '%s', but it is not a directory", inputs_path); return false; } return DeleteDirectoryTree(inputs_path); } bool MasterfileExists(const char *masterdir) { char filename[CF_BUFSIZE] = { 0 }; snprintf(filename, sizeof(filename), "%s/promises.cf", masterdir); MapName(filename); struct stat sb; if (stat(filename, &sb) == -1) { if (errno == ENOENT) { return false; } else { Log(LOG_LEVEL_ERR, "Could not stat file '%s'. (stat: %s)", filename, GetErrorStr()); return false; } } if (!S_ISREG(sb.st_mode)) { Log(LOG_LEVEL_ERR, "Path exists at '%s', but it is not a regular file", filename); return false; } return true; } /********************************************************************/ bool WriteBuiltinFailsafePolicyToPath(const char *filename) { // The bootstrap.inc file is generated by "make bootstrap-inc" const char * bootstrap_content = #include "bootstrap.inc" ; Log(LOG_LEVEL_INFO, "Writing built-in failsafe policy to '%s'", filename); FILE *fout = fopen(filename, "w"); if (!fout) { Log(LOG_LEVEL_ERR, "Unable to write failsafe to '%s' (fopen: %s)", filename, GetErrorStr()); return false; } fputs(bootstrap_content, fout); fclose(fout); if (chmod(filename, S_IRUSR | S_IWUSR) == -1) { Log(LOG_LEVEL_ERR, "Failed setting permissions on generated failsafe file '%s'", filename); return false; } return true; } bool WriteBuiltinFailsafePolicy(const char *inputdir) { char failsafe_path[CF_BUFSIZE]; snprintf(failsafe_path, CF_BUFSIZE - 1, "%s/failsafe.cf", inputdir); MapName(failsafe_path); return WriteBuiltinFailsafePolicyToPath(failsafe_path); } cfengine-3.6.2/libpromises/math_eval.h0000664000175100017510000000227412243421446017466 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MATH_EVAL_H #define CFENGINE_MATH_EVAL_H #include double EvaluateMathInfix(EvalContext *ctx, const char *input, char *failure); double EvaluateMathFunction(const char *f, double p); #endif cfengine-3.6.2/libpromises/process_unix_stub.c0000664000175100017510000000305212243421446021272 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include time_t GetProcessStartTime(ARG_UNUSED pid_t pid) { Log(LOG_LEVEL_VERBOSE, "No platform-specific code for obtaining process start time. - " "Falling back to no PID double-checking on kill()"); return PROCESS_START_TIME_UNKNOWN; } ProcessState GetProcessState(ARG_UNUSED pid_t pid) { Log(LOG_LEVEL_VERBOSE, "No platform-specific code for obtaining process state. - " "Falling back to no PID double-checking on kill()"); return PROCESS_STATE_RUNNING; } cfengine-3.6.2/libpromises/granules.h0000664000175100017510000000254312243421446017345 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_GRANULES_H #define CFENGINE_GRANULES_H #include char *GenTimeKey(time_t now); const char *ShiftSlotToString(int shift_slot); int GetTimeSlot(time_t here_and_now); int GetShiftSlot(time_t here_and_now); time_t GetShiftSlotStart(time_t t); time_t MeasurementSlotStart(time_t t); time_t MeasurementSlotTime(size_t slot, size_t num_slots, time_t now); #endif cfengine-3.6.2/libpromises/cf3lex.l0000664000175100017510000002626012400110676016712 0ustar00a10038a1003800000000000000%{ /* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /*******************************************************************/ /* */ /* LEXER for cfengine 3 */ /* */ /*******************************************************************/ #include #include #include #include /* yyinput/input are generated and unused */ #if defined(__GNUC__) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION >= 40200 # pragma GCC diagnostic ignored "-Wunused-function" # endif #endif #undef malloc #undef realloc #define malloc xmalloc #define realloc xrealloc #define ParserDebug if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) printf static int DeEscapeQuotedString(const char *from, char *to); int yywrap(void) { return 1; } static void yyuseraction() { P.offsets.current += yyleng; } #define YY_USER_ACTION yyuseraction(); // Do not use lex - flex only %} space [ \t]+ newline ([\n]|[\xd][\xa]) line ^.*$ comment #[^\n]* promises bundle body body nakedvar [$@][(][a-zA-Z0-9_\[\]\200-\377.:]+[)]|[$@][{][a-zA-Z0-9_\[\]\200-\377.:]+[}]|[$@][(][a-zA-Z0-9_\200-\377.:]+[\[][a-zA-Z0-9_$(){}\200-\377.:]+[\]]+[)]|[$@][{][a-zA-Z0-9_\200-\377.:]+[\[][a-zA-Z0-9_$(){}\200-\377.:]+[\]]+[}] id [a-zA-Z0-9_\200-\377]+ symbol [a-zA-Z0-9_\200-\377]+[:][a-zA-Z0-9_\200-\377]+ assign => arrow -> op [(] cp [)] ob [{] cb [}] /* * Three types of quoted strings: * * - string in double quotes, starts with double quote, runs until another * double quote, \" masks the double quote. * - string in single quotes, starts with single quote, runs until another * single quote, \' masks the single quote. * - string in backquotes, starts with backquote, runs until another backquote. * * The same rule formatted for the better readability: * * := \" \" | \' \' | ` ` * = * * = \\ | [^"\\] * = * * = \\ | [^'\\] * = * * = [^`] * = . | \n * */ qstring \"((\\(.|\n))|[^"\\])*\"|\'((\\(.|\n))|[^'\\])*\'|`[^`]*` class [.|&!()a-zA-Z0-9_\200-\377:]+:: promise_type [a-zA-Z_]+: %% {line} { free(P.current_line); P.current_line = xstrdup(yytext); ParserDebug("L:line %s\n", P.current_line); REJECT; } {newline} { P.line_no++; P.line_pos = 0; } {promises} { /* Note this has to come before "id" since it is a subset of id */ if (P.currentclasses != NULL) { free(P.currentclasses); P.currentclasses = NULL; } P.line_pos += yyleng; ParserDebug("\tL:bundle %d\n", P.line_pos); return BUNDLE; } {body} { /* Note this has to come before "id" since it is a subset of id */ if (P.currentclasses != NULL) { free(P.currentclasses); P.currentclasses = NULL; } P.line_pos += yyleng; ParserDebug("\tL:body %d\n", P.line_pos); return BODY; } {id} { P.offsets.last_id = P.offsets.current - yyleng; P.line_pos += yyleng; ParserDebug("\tL:id %s %d\n", yytext, P.line_pos); if (yyleng > CF_MAXVARSIZE-1) { yyerror("identifier too long"); } strncpy(P.currentid, yytext, CF_MAXVARSIZE); return IDSYNTAX; } {symbol} { P.offsets.last_id = P.offsets.current - yyleng; P.line_pos += yyleng; ParserDebug("\tL:symbol %s %d\n", yytext, P.line_pos); if (yyleng > CF_MAXVARSIZE-1) { yyerror("qualified identifier too long"); } strncpy(P.currentid, yytext, CF_MAXVARSIZE); return IDSYNTAX; } {assign} { P.line_pos += yyleng; ParserDebug("\tL:assign %d\n", P.line_pos); return ASSIGN; } {arrow} { P.line_pos += yyleng; ParserDebug("\tL:arrow %d\n", P.line_pos); return ARROW; } {class} { char *tmp = NULL; P.line_pos += yyleng; ParserDebug("\tL:class %s %d\n", yytext, P.line_pos); tmp = xstrdup(yytext); tmp[yyleng-2] = '\0'; if (P.currentclasses != NULL) { free(P.currentclasses); } P.currentclasses = xstrdup(tmp); free(tmp); return CLASS; } {promise_type} { char *tmp = NULL; P.line_pos += yyleng; ParserDebug("\tL:promise_type %s %d\n", yytext, P.line_pos); P.offsets.last_promise_type_id = P.offsets.current - yyleng; tmp = xstrdup(yytext); tmp[yyleng - 1] = '\0'; strncpy(P.currenttype, tmp, CF_MAXVARSIZE); if (P.currentclasses != NULL) { free(P.currentclasses); P.currentclasses = NULL; } free(tmp); return PROMISE_TYPE; } {qstring} { char *tmp = NULL; int less = 0; P.offsets.last_string = P.offsets.current - yyleng; P.line_pos += yyleng; ParserDebug("\tL:qstring %s %d\n", yytext, P.line_pos); for (char *c = yytext; *c; ++c) { if (*c == '\n') { P.line_no++; } } tmp = xmalloc(yyleng + 1); if ((less = DeEscapeQuotedString(yytext,tmp)) > 0) { yyless(less); P.offsets.current -= less; } if (P.currentstring) { free(P.currentstring); } P.currentstring = xstrdup(tmp); free(tmp); return QSTRING; } {nakedvar} { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); if (P.currentstring) { free(P.currentstring); } P.currentstring = xstrdup(yytext); return NAKEDVAR; } {op} { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return OP; } {cp} { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return CP; } {ob} { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return OB; } {cb} { P.line_pos += yyleng; ParserDebug("\tL: %s %d\n", yytext, P.line_pos); return CB; } {space}+ { P.line_pos += yyleng; } {comment} { } . { P.line_pos++; return yytext[0]; } %% static int DeEscapeQuotedString(const char *from, char *to) { char *cp; const char *sp; char start = *from; int len = strlen(from); if (len == 0) { return 0; } for (sp = from + 1, cp = to; (sp - from) < len; sp++, cp++) { if ((*sp == start)) { *(cp) = '\0'; if (*(sp + 1) != '\0') { return (2 + (sp - from)); } return 0; } if (*sp == '\\') { switch (*(sp + 1)) { case '\n': sp += 2; break; case ' ': break; case '\\': case '\"': case '\'': sp++; break; } } *cp = *sp; } yyerror("Runaway string"); *(cp) = '\0'; return 0; } /* EOF */ cfengine-3.6.2/libpromises/mod_process.h0000664000175100017510000000216712243421446020044 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_PROCESS_H #define CFENGINE_MOD_PROCESS_H #include extern const PromiseTypeSyntax CF_PROCESS_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/parser.h0000644000175100017510000000353112316547775017034 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PARSER_H #define CFENGINE_PARSER_H #include #define PARSER_WARNING_DEPRECATED (1 << 0) #define PARSER_WARNING_REMOVED (1 << 1) #define PARSER_WARNING_ALL 0xfffffff /** * @return warning code, or -1 if not a valid warning */ int ParserWarningFromString(const char *warning_str); const char *ParserWarningToString(unsigned int warning); /** * @brief Parse a CFEngine file to create a Policy DOM * @param agent_type Which agent is parsing the file. The parser will ignore elements not pertitent to its type * @param path Path of file to parse * @param warnings Bitfield of which warnings should be recorded * @param warnings_error Bitfield of which warnings should be counted as errors * @return */ Policy *ParserParseFile(AgentType agent_type, const char *path, unsigned int warnings, unsigned int warnings_error); #endif cfengine-3.6.2/libpromises/cf-windows-functions.h0000644000175100017510000000665012316547775021633 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_WINDOWS_FUNCTIONS_H #define CFENGINE_WINDOWS_FUNCTIONS_H #include #ifdef __MINGW32__ /* win_api.c */ int NovaWin_chmod(const char *path, mode_t mode); /* win_file.c */ FILE *NovaWin_FileHandleToStream(HANDLE fHandle, char *mode); int NovaWin_rename(const char *oldpath, const char *newpath); int NovaWin_FileExists(const char *fileName); int NovaWin_IsDir(char *fileName); int NovaWin_TakeFileOwnership(char *path); int NovaWin_SetFileOwnership(char *path, SID *sid); off_t NovaWin_GetDiskUsage(char *file, CfSize type); /* win_log.c */ void OpenLog(int facility); void CloseLog(void); void LogToSystemLog(const char *msg, LogLevel level); /* win_proc.c */ int NovaWin_IsProcessRunning(pid_t pid); int NovaWin_RunCmd(const char *comm, ShellType shell, int inheritHandles, char *startDir, STARTUPINFO *si, HANDLE *procHandle); int NovaWin_GetCurrentProcessOwner(SID *sid, int sidSz); int NovaWin_SetTokenPrivilege(HANDLE token, char *privilegeName, int enablePriv); /* win_ps.c */ int NovaWin_GetProcessSnapshot(Item **procdata); int GatherProcessUsers(Item **userList, int *userListSz, int *numRootProcs, int *numOtherProcs); /* win_service_exec.c */ void NovaWin_StartExecService(void); /* win_sysinfo.c */ int NovaWin_GetWinDir(char *winDir, int winDirSz); int NovaWin_GetSysDir(char *sysDir, int sysDirSz); int NovaWin_GetProgDir(char *progDir, int progDirSz); int NovaWin_GetEnv(char *varName, char *varContents, int varContentsSz); const char *GetDefaultWorkDir(void); const char *GetDefaultLogDir(void); const char *GetDefaultPidDir(void); const char *GetDefaultMasterDir(void); const char *GetDefaultInputDir(void); /* win_user.c */ int NovaWin_UserNameToSid(char *userName, SID *sid, DWORD sidSz, int shouldExist); int NovaWin_GroupNameToSid(char *groupName, SID *sid, DWORD sidSz, int shouldExist); int NovaWin_NameToSid(char *name, SID *sid, DWORD sidSz); int NovaWin_SidToName(SID *sid, char *name, int nameSz); int NovaWin_StringToSid(char *stringSid, SID *sid, int sidSz); FnCallResult FnCallUserExists(EvalContext *ctx, FnCall *fp, Rlist *finalargs); FnCallResult FnCallGroupExists(EvalContext *ctx, FnCall *fp, Rlist *finalargs); /* win_wmi.c */ int NovaWin_PackageListInstalledFromAPI(EvalContext *ctx, PackageItem ** pkgList, Attributes a, Promise *pp); /* win_execd_pipe.c */ bool IsReadReady(int fd, int timeout_sec); /* win_common.c */ void InitializeWindows(void); #endif /* __MINGW32__ */ #endif // CFENGINE_WINDOWS_FUNCTIONS_H cfengine-3.6.2/libpromises/variable.c0000664000175100017510000001475112411001073017274 0ustar00a10038a1003800000000000000#include #include #include #include #include struct VariableTable_ { RBTree *vars; }; struct VariableTableIterator_ { VarRef *ref; RBTreeIterator *iter; }; void VariableDestroy(Variable *var) { if (var) { VarRefDestroy(var->ref); RvalDestroy(var->rval); StringSetDestroy(var->tags); // Nothing to do for ->promise free(var); } } VariableTable *VariableTableNew(void) { VariableTable *table = xmalloc(sizeof(VariableTable)); table->vars = RBTreeNew(NULL, NULL, NULL, NULL, NULL, (RBTreeValueDestroyFn*)VariableDestroy); return table; } void VariableTableDestroy(VariableTable *table) { if (table) { RBTreeDestroy(table->vars); free(table); } } Variable *VariableTableGet(const VariableTable *table, const VarRef *ref) { return RBTreeGet(table->vars, (void *)ref->hash); } bool VariableTableRemove(VariableTable *table, const VarRef *ref) { return RBTreeRemove(table->vars, (void *)ref->hash); } static Variable *VariableNew(VarRef *ref, Rval rval, DataType type, StringSet *tags, const Promise *promise) { Variable *var = xmalloc(sizeof(Variable)); var->ref = ref; var->rval = rval; var->type = type; var->tags = tags; var->promise = promise; return var; } bool VariableTablePut(VariableTable *table, const VarRef *ref, const Rval *rval, DataType type, const char *tags, const Promise *promise) { assert(VarRefIsQualified(ref)); bool result; Variable *var = VariableTableGet(table, ref); if (var == NULL) { var = VariableNew(VarRefCopy(ref), RvalCopy(*rval), type, StringSetFromString(tags, ','), promise); result = RBTreePut(table->vars, (void *)var->ref->hash, var); } else // if (!RvalsEqual(var->rval *rval) // TODO: implement-me ! { RvalDestroy(var->rval); var->rval = RvalCopy(*rval); var->type = type; var->promise = promise; result = true; } return result; } bool VariableTableClear(VariableTable *table, const char *ns, const char *scope, const char *lval) { if (!ns && !scope && !lval) { bool has_vars = RBTreeSize(table->vars) > 0; RBTreeClear(table->vars); return has_vars; } RBTree *remove_set = RBTreeNew(NULL, NULL, NULL, NULL, NULL, NULL); { VariableTableIterator *iter = VariableTableIteratorNew(table, ns, scope, lval); for (Variable *v = VariableTableIteratorNext(iter); v; v = VariableTableIteratorNext(iter)) { RBTreePut(remove_set, (void *)v->ref->hash, v); } VariableTableIteratorDestroy(iter); } size_t remove_count = RBTreeSize(remove_set); if (remove_count == 0) { RBTreeDestroy(remove_set); return false; } size_t removed = 0; { RBTreeIterator *iter = RBTreeIteratorNew(remove_set); void *ref_key = NULL; Variable *var = NULL; while (RBTreeIteratorNext(iter, &ref_key, (void **)&var)) { if (VariableTableRemove(table, var->ref)) { removed++; } } RBTreeIteratorDestroy(iter); } RBTreeDestroy(remove_set); assert(removed == remove_count); return true; } size_t VariableTableCount(const VariableTable *table, const char *ns, const char *scope, const char *lval) { if (!ns && !scope && !lval) { return RBTreeSize(table->vars); } VariableTableIterator *iter = VariableTableIteratorNew(table, ns, scope, lval); size_t count = 0; while (VariableTableIteratorNext(iter)) { count++; } VariableTableIteratorDestroy(iter); return count; } VariableTableIterator *VariableTableIteratorNewFromVarRef(const VariableTable *table, const VarRef *ref) { VariableTableIterator *iter = xmalloc(sizeof(VariableTableIterator)); iter->ref = VarRefCopy(ref); iter->iter = RBTreeIteratorNew(table->vars); return iter; } VariableTableIterator *VariableTableIteratorNew(const VariableTable *table, const char *ns, const char *scope, const char *lval) { VarRef ref = { 0 }; ref.ns = (char *)ns; ref.scope = (char *)scope; ref.lval = (char *)lval; return VariableTableIteratorNewFromVarRef(table, &ref); } Variable *VariableTableIteratorNext(VariableTableIterator *iter) { void *key_ref = NULL; Variable *var = NULL; while (RBTreeIteratorNext(iter->iter, &key_ref, (void **)&var)) { const char *key_ns = var->ref->ns ? var->ref->ns : "default"; if (iter->ref->ns && strcmp(key_ns, iter->ref->ns) != 0) { continue; } if (iter->ref->scope && strcmp(var->ref->scope, iter->ref->scope) != 0) { continue; } if (iter->ref->lval && strcmp(var->ref->lval, iter->ref->lval) != 0) { continue; } if (iter->ref->num_indices > 0) { if (iter->ref->num_indices > var->ref->num_indices) { continue; } bool match = true; for (size_t i = 0; i < iter->ref->num_indices; i++) { if (strcmp(var->ref->indices[i], iter->ref->indices[i]) != 0) { match = false; break; } } if (!match) { continue; } } return var; } return NULL; } void VariableTableIteratorDestroy(VariableTableIterator *iter) { if (iter) { VarRefDestroy(iter->ref); RBTreeIteratorDestroy(iter->iter); free(iter); } } VariableTable *VariableTableCopyLocalized(const VariableTable *table, const char *ns, const char *scope) { VariableTable *localized_copy = VariableTableNew(); VariableTableIterator *iter = VariableTableIteratorNew(table, ns, scope, NULL); Variable *foreign_var = NULL; while ((foreign_var = VariableTableIteratorNext(iter))) { Variable *localized_var = VariableNew(VarRefCopyLocalized(foreign_var->ref), RvalCopy(foreign_var->rval), foreign_var->type, NULL, foreign_var->promise); RBTreePut(localized_copy->vars, (void *)localized_var->ref->hash, localized_var); } VariableTableIteratorDestroy(iter); return localized_copy; } cfengine-3.6.2/libpromises/Makefile.am0000664000175100017510000001260012411001073017366 0ustar00a10038a1003800000000000000if !BUILTIN_EXTENSIONS projlib_LTLIBRARIES = libpromises.la AM_LDFLAGS = -version-info 3:6:0 -no-undefined else noinst_LTLIBRARIES = libpromises.la AM_LDFLAGS = endif AM_LDFLAGS += $(LMDB_LDFLAGS) $(TOKYOCABINET_LDFLAGS) $(QDBM_LDFLAGS) \ $(PCRE_LDFLAGS) $(OPENSSL_LDFLAGS) $(SQLITE3_LDFLAGS) $(LIBACL_LDFLAGS) EXTRA_DIST = extensions_template.c extensions_template.h enterprise_extension.sed math.pc AM_CPPFLAGS = \ -I$(srcdir)/../libutils -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv $(ENTERPRISE_CPPFLAGS) \ $(LMDB_CPPFLAGS) $(TOKYOCABINET_CPPFLAGS) $(QDBM_CPPFLAGS) \ $(PCRE_CPPFLAGS) $(OPENSSL_CPPFLAGS) $(SQLITE3_CPPFLAGS) $(LIBACL_CPPFLAGS) AM_CFLAGS = $(ENTERPRISE_CFLAGS) \ $(LMDB_CFLAGS) $(TOKYOCABINET_CFLAGS) $(QDBM_CFLAGS) \ $(PCRE_CFLAGS) $(OPENSSL_CFLAGS) $(SQLITE3_CFLAGS) $(LIBACL_CFLAGS) AM_YFLAGS = -d LIBS = $(LMDB_LIBS) $(TOKYOCABINET_LIBS) $(QDBM_LIBS) \ $(PCRE_LIBS) $(OPENSSL_LIBS) $(SQLITE3_LIBS) $(LIBACL_LIBS) libpromises_la_LIBADD = ../libutils/libutils.la ../libcfnet/libcfnet.la \ ../libenv/libenv.la $(ENTERPRISE_LDADD) libpromises_la_SOURCES = \ cf3parse.y cf3parse.h \ cf3lex.l \ acl_tools.h acl_tools_posix.c \ actuator.c actuator.h \ addr_lib.c addr_lib.h \ assoc.c assoc.h \ audit.c audit.h \ attributes.c attributes.h \ bootstrap.c bootstrap.h \ cf3.defs.h \ cf3.extern.h \ cf3globals.c \ chflags.c chflags.h \ class.c class.h \ constants.c \ conversion.c conversion.h \ crypto.c crypto.h \ dbm_api.c dbm_api.h dbm_priv.h \ dbm_migration.c dbm_migration.h \ dbm_migration_lastseen.c \ dbm_migration_bundles.c \ dbm_lmdb.c \ dbm_quick.c \ dbm_tokyocab.c \ enterprise_extension.c enterprise_extension.h \ enterprise_stubs.c \ eval_context.c eval_context.h \ evalfunction.c evalfunction.h \ exec_tools.c exec_tools.h \ expand.c expand.h \ extensions.c extensions.h \ files_copy.c files_copy.h \ files_hashes.c files_hashes.h \ files_interfaces.c files_interfaces.h \ files_lib.c files_lib.h \ files_names.c files_names.h \ fncall.c fncall.h \ generic_agent.c generic_agent.h \ granules.c granules.h \ instrumentation.c instrumentation.h \ item_lib.c item_lib.h \ iteration.c iteration.h \ keyring.c keyring.h\ known_dirs.c known_dirs.h \ lastseen.c lastseen.h \ loading.c loading.h \ locks.c locks.h \ logic_expressions.c logic_expressions.h \ matching.c matching.h \ math_eval.c math_eval.h \ mod_access.c mod_access.h \ mod_common.c mod_common.h \ mod_databases.c mod_databases.h \ mod_environ.c mod_environ.h \ mod_exec.c mod_exec.h \ mod_files.c mod_files.h \ mod_measurement.c mod_measurement.h \ mod_methods.c mod_methods.h \ mod_outputs.c mod_outputs.h \ mod_packages.c mod_packages.h \ mod_process.c mod_process.h \ mod_report.c mod_report.h \ mod_services.c mod_services.h \ mod_storage.c mod_storage.h \ mod_knowledge.c mod_knowledge.h \ mod_users.c mod_users.h \ modes.c \ mutex.c mutex.h \ ornaments.c ornaments.h \ policy.c policy.h \ parser.c parser.h \ parser_state.h \ patches.c \ pipes.h pipes.c \ processes_select.c processes_select.h \ process_lib.h process_unix_priv.h \ promises.c promises.h \ prototypes3.h \ rlist.c rlist.h \ scope.c scope.h \ shared_lib.c shared_lib.h \ signals.c signals.h \ sort.c sort.h \ storage_tools.c \ string_expressions.c string_expressions.h \ syntax.c syntax.h \ syslog_client.c syslog_client.h \ systype.c systype.h \ timeout.c timeout.h \ unix.c unix.h \ var_expressions.c var_expressions.h \ vars.c vars.h \ variable.c variable.h \ verify_classes.c verify_classes.h \ verify_reports.c \ verify_vars.c verify_vars.h \ cf-windows-functions.h \ bootstrap.inc if !NT libpromises_la_SOURCES += \ process_unix.c \ pipes_unix.c if LINUX libpromises_la_SOURCES += \ process_linux.c endif if AIX libpromises_la_SOURCES += \ process_aix.c endif if SOLARIS libpromises_la_SOURCES += \ process_solaris.c \ solaris_ifaddrs.c solaris_ifaddrs.h endif if !LINUX if !AIX if !SOLARIS libpromises_la_SOURCES += \ process_unix_stub.c endif endif endif endif # !NT BUILT_SOURCES = cf3lex.c cf3parse.h cf3parse.c \ enterprise_extension.c \ enterprise_extension.h ENTERPRISE_EXTENSION_GENERATE = $(SED) -f $(srcdir)/enterprise_extension.sed $< > $@ ENTERPRISE_EXTENSION_MAKE = @if test -z "$(V)"; then echo " SED " $@; else echo "$(ENTERPRISE_EXTENSION_GENERATE)"; fi; $(ENTERPRISE_EXTENSION_GENERATE) enterprise_extension.c: extensions_template.c enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) enterprise_extension.h: extensions_template.h enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) CLEANFILES = *.gcno *.gcda $(BUILT_SOURCES) # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej bootstrap.inc: perl ./text2cstring.pl failsafe.cf > bootstrap.inc cfengine-3.6.2/libpromises/mod_environ.c0000664000175100017510000000726012411001073020023 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax environment_resources_constraints[] = { ConstraintSyntaxNewInt("env_cpus", CF_VALRANGE, "Number of virtual CPUs in the environment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("env_memory", CF_VALRANGE, "Amount of primary storage (RAM) in the virtual environment (KB)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("env_disk", CF_VALRANGE, "Amount of secondary storage (DISK) in the virtual environment (MB)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("env_baseline", CF_ABSPATHRANGE, "The path to an image with which to baseline the virtual environment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("env_spec", CF_ANYSTRING, "A string containing a technology specific set of promises for the virtual instance", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax environment_resources_body = BodySyntaxNew("environment_resources", environment_resources_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax environment_interface_constraints[] = { ConstraintSyntaxNewStringList("env_addresses", "", "The IP addresses of the environment's network interfaces", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("env_name", "", "The hostname of the virtual environment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("env_network", "", "The hostname of the virtual network", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax environment_interface_body = BodySyntaxNew("environment_interface", environment_interface_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax CF_ENVIRON_BODIES[] = { ConstraintSyntaxNewString("environment_host", "[a-zA-Z0-9_]+", "A class indicating which physical node will execute this guest machine", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("environment_interface", &environment_interface_body, "Virtual environment outward identity and location", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("environment_resources", &environment_resources_body, "Virtual environment resource description", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("environment_state", "create,delete,running,suspended,down", "The desired dynamical state of the specified environment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("environment_type", "xen,kvm,esx,vbox,test,xen_net,kvm_net,esx_net,test_net,zone,ec2,eucalyptus", "Virtual environment type", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_ENVIRONMENT_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "guest_environments", CF_ENVIRON_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/instrumentation.c0000664000175100017510000001027112411001073020743 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include static void NotePerformance(char *eventname, time_t t, double value); /* Alter this code at your peril. Berkeley DB is very sensitive to errors. */ /***************************************************************/ struct timespec BeginMeasure() { struct timespec start; if (clock_gettime(CLOCK_REALTIME, &start) == -1) { Log(LOG_LEVEL_VERBOSE, "Clock gettime failure. (clock_gettime: %s)", GetErrorStr()); } return start; } /***************************************************************/ void EndMeasurePromise(struct timespec start, const Promise *pp) { char id[CF_BUFSIZE], *mid = NULL; mid = PromiseGetConstraintAsRval(pp, "measurement_class", RVAL_TYPE_SCALAR); if (mid) { snprintf(id, CF_BUFSIZE, "%s:%s:%.100s", mid, pp->parent_promise_type->name, pp->promiser); if (Chop(id, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } EndMeasure(id, start); } } /***************************************************************/ void EndMeasure(char *eventname, struct timespec start) { struct timespec stop; if (clock_gettime(CLOCK_REALTIME, &stop) == -1) { Log(LOG_LEVEL_VERBOSE, "Clock gettime failure. (clock_gettime: %s)", GetErrorStr()); } else { double dt = (stop.tv_sec - start.tv_sec) + (stop.tv_nsec - start.tv_nsec) / (double) CF_BILLION; NotePerformance(eventname, start.tv_sec, dt); } } /***************************************************************/ int EndMeasureValueMs(struct timespec start) { struct timespec stop; if (clock_gettime(CLOCK_REALTIME, &stop) == -1) { Log(LOG_LEVEL_VERBOSE, "Clock gettime failure. (clock_gettime: %s)", GetErrorStr()); } else { double dt = ((stop.tv_sec - start.tv_sec) * 1e3 + /* 1 s = 1e3 ms */ (stop.tv_nsec - start.tv_nsec) / 1e6); /* 1e6 ns = 1 ms */ return (int)dt; } return -1; } /***************************************************************/ static void NotePerformance(char *eventname, time_t t, double value) { CF_DB *dbp; Event e, newe; double lastseen; int lsea = SECONDS_PER_WEEK; time_t now = time(NULL); if (!OpenDB(&dbp, dbid_performance)) { return; } if (ReadDB(dbp, eventname, &e, sizeof(e))) { lastseen = now - e.t; newe.t = t; newe.Q = QAverage(e.Q, value, 0.3); /* Have to kickstart variance computation, assume 1% to start */ if (newe.Q.var <= 0.0009) { newe.Q.var = newe.Q.expect / 100.0; } } else { lastseen = 0.0; newe.t = t; newe.Q.q = value; newe.Q.dq = 0; newe.Q.expect = value; newe.Q.var = 0.001; } if (lastseen > (double) lsea) { Log(LOG_LEVEL_DEBUG, "Performance record '%s' expired", eventname); DeleteDB(dbp, eventname); } else { WriteDB(dbp, eventname, &newe, sizeof(newe)); } CloseDB(dbp); } cfengine-3.6.2/libpromises/cf3globals.c0000664000175100017510000001167012411001073017523 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include /*****************************************************************************/ /* flags */ /*****************************************************************************/ int SHOWREPORTS = false; /* GLOBAL_A */ /*****************************************************************************/ /* operational state */ /*****************************************************************************/ bool FIPS_MODE = false; /* GLOBAL_P */ struct utsname VSYSNAME; /* GLOBAL_E, initialized later */ int CFA_MAXTHREADS = 10; /* GLOBAL_P */ int CF_PERSISTENCE = 10; /* GLOBAL_P */ AgentType THIS_AGENT_TYPE; /* GLOBAL_C, initialized later */ Item *PROCESSTABLE = NULL; /* GLOBAL_X */ /*****************************************************************************/ /* Internal data structures */ /*****************************************************************************/ int LASTSEENEXPIREAFTER = SECONDS_PER_WEEK; /* GLOBAL_P */ char POLICY_SERVER[CF_MAX_IP_LEN] = ""; /* GLOBAL_X */ /*****************************************************************************/ /* Compatability infrastructure */ /*****************************************************************************/ bool DONTDO = false; /* GLOBAL_A */ char VFQNAME[CF_MAXVARSIZE] = ""; /* GLOBAL_E GLOBAL_P */ char VUQNAME[CF_MAXVARSIZE] = ""; /* GLOBAL_E */ char VDOMAIN[CF_MAXVARSIZE] = ""; /* GLOBAL_E GLOBAL_P */ char CFWORKDIR[CF_BUFSIZE] = ""; /* GLOBAL_C */ /* Default value for copytype attribute. Loaded by cf-agent from body control */ const char *DEFAULT_COPYTYPE = NULL; /* GLOBAL_P */ /* Keys for the agent. Loaded by GAInitialize (and hence every time policy is reloaded). Used in network protocol and leaked to language. */ RSA *PRIVKEY = NULL, *PUBKEY = NULL; /* GLOBAL_X */ /* First IP address discovered by DetectEnvironment (hence reloaded every policy change). Used somewhere in cf-execd, superficially in old-style protocol handshake and sporadically in other situations. */ char VIPADDRESS[CF_MAX_IP_LEN] = ""; /* GLOBAL_E */ /* Edition-time constant (MD5 for community, something else for Enterprise) Used as a default hash everywhere (not only in network protocol) */ HashMethod CF_DEFAULT_DIGEST; /* GLOBAL_C, initialized later */ int CF_DEFAULT_DIGEST_LEN; /* GLOBAL_C, initialized later */ /* Holds the "now" time captured at the moment of policy load (and in response to cf-runagent command to cf-serverd?!). Utilized everywhere "now" start time is needed */ time_t CFSTARTTIME; /* GLOBAL_E, initialized later */ /* Set in cf-agent/cf-runagent (from control body). Used as a timeout for socket operations in network code. */ time_t CONNTIMEOUT = 30; /* seconds */ /* GLOBAL_A GLOBAL_P */ /* Internal detail of timeout operations. Due to historical reasons is defined here, not in libpromises/timeout.c */ pid_t ALARM_PID = -1; /* GLOBAL_X */ /* Set in cf-agent (from control body). Used as a default value for maxfilesize attribute in policy */ int EDITFILESIZE = 10000; /* GLOBAL_P */ /* Set in cf-agent (from control body) and GenericAgentInitialize. Used as a default value for ifelapsed attribute in policy. */ int VIFELAPSED = 1; /* GLOBAL_P */ /* Set in cf-agent (from control body) and GenericAgentInitialize. Used as a default value for expireafter attribute in policy. */ int VEXPIREAFTER = 120; /* GLOBAL_P */ /* Set in cf-agent/cf-serverd (from control body). Utilized in server/client code to bind sockets. */ char BINDINTERFACE[CF_MAXVARSIZE]; /* GLOBAL_P */ /* Set in cf-*.c:CheckOpts and GenericAgentConfigParseArguments. Utilized in generic_agent.c for - cf_promises_validated filename - GenericAgentCheckPolicy - GenericAgentLoadPolicy (ReadPolicyValidatedFile) */ bool MINUSF = false; /* GLOBAL_A */ cfengine-3.6.2/libpromises/mod_files.c0000644000175100017510000007163612352022221017455 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include static const ConstraintSyntax location_constraints[] = { ConstraintSyntaxNewOption("before_after", "before,after", "Menu option, point cursor before of after matched line. Default value: after", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("first_last", "first,last", "Menu option, choose first or last occurrence of match in file. Default value: last", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("select_line_matching", CF_ANYSTRING, "Regular expression for matching file line location", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax location_body = BodySyntaxNew("location", location_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax edit_field_constraints[] = { ConstraintSyntaxNewBool("allow_blank_fields", "true/false allow blank fields in a line (do not purge). Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("extend_fields", "true/false add new fields at end of line if necessary to complete edit. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("field_operation", "prepend,append,alphanum,delete,set", "Menu option policy for editing subfields. Default value: none", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("field_separator", CF_ANYSTRING, "The regular expression used to separate fields in a line. Default value: none", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("field_value", CF_ANYSTRING, "Set field value to a fixed value", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("select_field", "0,99999999", "Integer index of the field required 0..n (default starts from 1)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("start_fields_from_zero", "If set, the default field numbering starts from 0", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("value_separator", CF_CHARRANGE, "Character separator for subfields inside the selected field. Default value: none", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax edit_field_body = BodySyntaxNew("edit_field", edit_field_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax replace_with_constraints[] = { ConstraintSyntaxNewOption("occurrences", "all,first", "Menu option to replace all occurrences or just first (NB the latter is non-convergent). Default value: all", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("replace_value", CF_ANYSTRING, "Value used to replace regular expression matches in search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax replace_with_body = BodySyntaxNew("replace_with", replace_with_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax select_region_constraints[] = { ConstraintSyntaxNewBool("include_start_delimiter", "Whether to include the section delimiter. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("include_end_delimiter", "Whether to include the section delimiter. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("select_start", CF_ANYSTRING, "Regular expression matching start of edit region", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("select_end", CF_ANYSTRING, "Regular expression matches end of edit region from start", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax select_region_body = BodySyntaxNew("select_region", select_region_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax delete_select_constraints[] = { ConstraintSyntaxNewStringList("delete_if_startwith_from_list", CF_ANYSTRING, "Delete line if it starts with a string in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("delete_if_not_startwith_from_list", CF_ANYSTRING, "Delete line if it DOES NOT start with a string in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("delete_if_match_from_list", CF_ANYSTRING, "Delete line if it fully matches a regex in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("delete_if_not_match_from_list", CF_ANYSTRING,"Delete line if it DOES NOT fully match a regex in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("delete_if_contains_from_list", CF_ANYSTRING, "Delete line if a regex in the list match a line fragment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("delete_if_not_contains_from_list", CF_ANYSTRING,"Delete line if a regex in the list DOES NOT match a line fragment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax delete_select_body = BodySyntaxNew("delete_select", delete_select_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax insert_select_constraints[] = { ConstraintSyntaxNewStringList("insert_if_startwith_from_list", CF_ANYSTRING, "Insert line if it starts with a string in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("insert_if_not_startwith_from_list", CF_ANYSTRING,"Insert line if it DOES NOT start with a string in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("insert_if_match_from_list", CF_ANYSTRING, "Insert line if it fully matches a regex in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("insert_if_not_match_from_list", CF_ANYSTRING,"Insert line if it DOES NOT fully match a regex in the list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("insert_if_contains_from_list", CF_ANYSTRING,"Insert line if a regex in the list match a line fragment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("insert_if_not_contains_from_list", CF_ANYSTRING, "Insert line if a regex in the list DOES NOT match a line fragment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax insert_select_body = BodySyntaxNew("insert_select", insert_select_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax CF_INSERTLINES_BODIES[] = { ConstraintSyntaxNewBool("expand_scalars", "Expand any unexpanded variables. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("insert_type", "literal,string,file,file_preserve_block,preserve_block,preserve_all_lines", "Type of object the promiser string refers to. Default value: literal", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("insert_select", &insert_select_body, "Insert only if lines pass filter criteria", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("location", &location_body, "Specify where in a file an insertion will be made", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOptionList("whitespace_policy", "ignore_leading,ignore_trailing,ignore_embedded,exact_match", "Criteria for matching and recognizing existing lines", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_DELETELINES_BODIES[] = { ConstraintSyntaxNewBody("delete_select", &delete_select_body, "Delete only if lines pass filter criteria", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("not_matching", "true/false negate match criterion. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_COLUMN_BODIES[] = { ConstraintSyntaxNewBody("edit_field", &edit_field_body, "Edit line-based file as matrix of fields", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_REPLACE_BODIES[] = { ConstraintSyntaxNewBody("replace_with", &replace_with_body, "Search-replace pattern", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CF_COMMON_EDITBODIES[] = { ConstraintSyntaxNewBody("select_region", &select_region_body, "Limit edits to a demarked region of the file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static bool AclCheck(const Body *body, Seq *errors) { bool success = true; if (BodyHasConstraint(body, "acl_directory_inherit") && BodyHasConstraint(body, "acl_default")) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An acl body cannot have both acl_directory_inherit and acl_default. Please use acl_default only")); success = false; } if (BodyHasConstraint(body, "specify_inherit_aces") && BodyHasConstraint(body, "specify_default_aces")) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An acl body cannot have both specify_inherit_aces and specify_default_aces. Please use specify_default_aces only")); success = false; } return success; } static const ConstraintSyntax acl_constraints[] = { ConstraintSyntaxNewStringList("aces", "((user|group):[^:]+:[-=+,rwx()dtTabBpcoD]*(:(allow|deny))?)|((all|mask):[-=+,rwx()]*(:(allow|deny))?)", "Native settings for access control entry", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("acl_directory_inherit", "nochange,parent,specify,clear", "Access control list type for the affected file system", SYNTAX_STATUS_DEPRECATED), ConstraintSyntaxNewOption("acl_default", "nochange,access,specify,clear", "How to apply default (inheritable) access control list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("acl_method", "append,overwrite", "Editing method for access control list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("acl_type", "generic,posix,ntfs", "Access control list type for the affected file system", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("specify_inherit_aces", "((user|group):[^:]+:[-=+,rwx()dtTabBpcoD]*(:(allow|deny))?)|((all|mask):[-=+,rwx()]*(:(allow|deny))?)", "Native settings for access control entry", SYNTAX_STATUS_DEPRECATED), ConstraintSyntaxNewStringList("specify_default_aces", "((user|group):[^:]+:[-=+,rwx()dtTabBpcoD]*(:(allow|deny))?)|((all|mask):[-=+,rwx()]*(:(allow|deny))?)", "Native settings for access control entry", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("acl_inherit", CF_BOOL ",nochange", "Whether the object inherits its ACL from the parent (Windows only)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax acl_body = BodySyntaxNew("acl", acl_constraints, &AclCheck, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax changes_constraints[] = { ConstraintSyntaxNewOption("hash", "md5,sha1,sha224,sha256,sha384,sha512,best", "Hash files for change detection", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("report_changes", "all,stats,content,none", "Specify criteria for change warnings", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("update_hashes", "Update hash values immediately after change warning", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("report_diffs","Generate reports summarizing the major differences between individual text files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax changes_body = BodySyntaxNew("changes", changes_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax depth_search_constraints[] = { ConstraintSyntaxNewInt("depth", CF_VALRANGE, "Maximum depth level for search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("exclude_dirs", ".*", "List of regexes of directory names NOT to include in depth search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("include_basedir", "true/false include the start/root dir of the search results", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("include_dirs", ".*", "List of regexes of directory names to include in depth search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("rmdeadlinks", "true/false remove links that point to nowhere. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("traverse_links", "true/false traverse symbolic links to directories. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("xdev", "true/false exclude directories that are on different devices. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax depth_search_body = BodySyntaxNew("depth_search", depth_search_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax edit_defaults_constraints[] = { ConstraintSyntaxNewOption("edit_backup", "true,false,timestamp,rotate", "Menu option for backup policy on edit changes. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("empty_file_before_editing", "Baseline memory model of file to zero/empty before commencing promised edits. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("inherit", "If true this causes the sub-bundle to inherit the private classes of its parent", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("max_file_size", CF_VALRANGE, "Do not edit files bigger than this number of bytes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("recognize_join", "Join together lines that end with a backslash, up to 4kB limit. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("rotate", "0,99", "How many backups to store if 'rotate' edit_backup strategy is selected. Default value: 1", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax edit_defaults_body = BodySyntaxNew("edit_defaults", edit_defaults_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax delete_constraints[] = { ConstraintSyntaxNewOption("dirlinks", "delete,tidy,keep", "Menu option policy for dealing with symbolic links to directories during deletion", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("rmdirs", "true/false whether to delete empty directories during recursive deletion", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax delete_body = BodySyntaxNew("delete", delete_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax rename_constraints[] = { ConstraintSyntaxNewBool("disable", "true/false automatically rename and remove permissions. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("disable_mode", CF_MODERANGE, "The permissions to set when a file is disabled", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("disable_suffix", "", "The suffix to add to files when disabling (.cfdisabled)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("newname", "", "The desired name for the current file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("rotate", "0,99", "Maximum number of file rotations to keep", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax rename_body = BodySyntaxNew("rename", rename_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax perms_constraints[] = { ConstraintSyntaxNewStringList("bsdflags", CF_BSDFLAGRANGE, "List of menu options for bsd file system flags to set", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("groups", CF_USERRANGE, "List of acceptable groups of group ids, first is change target", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("mode", CF_MODERANGE, "File permissions (like posix chmod)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("owners", CF_USERRANGE, "List of acceptable owners or user ids, first is change target", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("rxdirs", "true/false add execute flag for directories if read flag is set", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax perms_body = BodySyntaxNew("perms", perms_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax file_select_constraints[] = { ConstraintSyntaxNewStringList("leaf_name", "", "List of regexes that match an acceptable name", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("path_name", CF_ABSPATHRANGE, "List of pathnames to match acceptable target", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("search_mode", CF_MODERANGE, "A list of mode masks for acceptable file permissions", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("search_size", "0,inf", "Integer range of file sizes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("search_owners", "", "List of acceptable user names or ids for the file, or regexes to match", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("search_groups", "", "List of acceptable group names or ids for the file, or regexes to match", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("search_bsdflags", CF_BSDFLAGRANGE, "String of flags for bsd file system flags expected set", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("ctime", CF_TIMERANGE, "Range of change times (ctime) for acceptable files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("mtime", CF_TIMERANGE, "Range of modification times (mtime) for acceptable files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("atime", CF_TIMERANGE, "Range of access times (atime) for acceptable files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("exec_regex", CF_ANYSTRING, "Matches file if this regular expression matches any full line returned by the command", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("exec_program", CF_ABSPATHRANGE, "Execute this command on each file and match if the exit status is zero", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOptionList("file_types", "plain,reg,symlink,dir,socket,fifo,door,char,block", "List of acceptable file types from menu choices", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("issymlinkto", "", "List of regular expressions to match file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("file_result", "[!*(leaf_name|path_name|file_types|mode|size|owner|group|atime|ctime|mtime|issymlinkto|exec_regex|exec_program|bsdflags)[|&.]*]*", "Logical expression combining classes defined by file search criteria", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax file_select_body = BodySyntaxNew("file_select", file_select_constraints, NULL, SYNTAX_STATUS_NORMAL); /* Copy and link are really the same body and should have non-overlapping patterns so that they are XOR but it's okay that some names overlap (like source) as there is no ambiguity in XOR */ static const ConstraintSyntax link_from_constraints[] = { ConstraintSyntaxNewStringList("copy_patterns", "", "A set of patterns that should be copied and synchronized instead of linked", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("link_children", "true/false whether to link all directory's children to source originals. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("link_type", CF_LINKRANGE, "The type of link used to alias the file. Default value: symlink", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("source", CF_PATHRANGE, "The source file to which the link should point", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("when_linking_children", "override_file,if_no_such_file", "Policy for overriding existing files when linking directories of children", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("when_no_source", "force,delete,nop", "Behaviour when the source file to link to does not exist. Default value: nop", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax link_from_body = BodySyntaxNew("link_from", link_from_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax copy_from_constraints[] = { /* We use CF_PATHRANGE due to collision with LINKTO_BODY and a bug lurking in * a verification stage -- this attribute gets picked instead of another * 'source' */ ConstraintSyntaxNewString("source", CF_PATHRANGE, "Reference source file from which to copy", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("servers", "[A-Za-z0-9_.:\\-\\[\\]]+", "List of servers in order of preference from which to copy", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("collapse_destination_dir", "true/false Place files in subdirectories into the root destination directory during copy", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("compare", "atime,mtime,ctime,digest,hash,exists,binary", "Menu option policy for comparing source and image file attributes. Default: mtime or ctime differs", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("copy_backup", "true,false,timestamp", "Menu option policy for file backup/version control. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("encrypt", "true/false use encrypted data stream to connect to remote host. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("check_root", "true/false check permissions on the root directory when depth_search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("copylink_patterns", "", "List of patterns matching files that should be copied instead of linked", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntRange("copy_size", "0,inf", "Integer range of file sizes that may be copied", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("findertype", "MacOSX", "Menu option for default finder type on MacOSX", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("linkcopy_patterns", "", "List of patterns matching files that should be replaced with symbolic links", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("link_type", CF_LINKRANGE, "Menu option for type of links to use when copying. Default value: symlink", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("force_update", "true/false force copy update always. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("force_ipv4", "true/false force use of ipv4 on ipv6 enabled network. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("portnumber", "", "Port number or service name to connect to on server host", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("preserve", "true/false whether to preserve file permissions on copied file. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("purge", "true/false purge files on client that do not match files on server when a depth_search is used. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("stealth", "true/false whether to preserve time stamps on copied file. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("timeout", "1,3600", "Connection timeout, seconds", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("trustkey", "true/false trust public keys from remote server if previously unknown. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("type_check", "true/false compare file types before copying and require match", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("verify", "true/false verify transferred file by hashing after copy (resource penalty). Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("protocol_version", "0,undefined,1,classic,2,latest", "CFEngine protocol version to use when connecting to the server. Default: undefined", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax copy_from_body = BodySyntaxNew("copy_from", copy_from_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax CF_FILES_BODIES[] = { ConstraintSyntaxNewBody("acl", &acl_body, "Criteria for access control lists on file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("changes", &changes_body, "Criteria for change management", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("copy_from", ©_from_body, "Criteria for copying file from a source", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("create", "true/false whether to create non-existing file. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("delete", &delete_body, "Criteria for deleting files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("depth_search", &depth_search_body, "Criteria for file depth searches", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("edit_defaults", &edit_defaults_body, "Default promise details for file edits", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBundle("edit_line", "Line editing model for file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("edit_template", CF_ABSPATHRANGE, "The name of a special CFEngine template file to expand", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBundle("edit_xml", "XML editing model for file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("file_select", &file_select_body, "Choose which files select in a search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("link_from", &link_from_body, "Criteria for linking file from a source", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("move_obstructions", "true/false whether to move obstructions to file-object creation. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("pathtype", "literal,regex,guess", "Menu option for interpreting promiser file object", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("perms", &perms_body, "Criteria for setting permissions on a file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("rename", &rename_body, "Criteria for renaming files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("repository", CF_ABSPATHRANGE, "Name of a repository for versioning", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("touch", "true/false whether to touch time stamps on file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("transformer", CF_ABSPATHRANGE, "Command (with full path) used to transform current file (no shell wrapper used)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("template_method", "cfengine,mustache", "", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContainer("template_data", "", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; // edit_xml body syntax const ConstraintSyntax CF_COMMON_XMLBODIES[] = { ConstraintSyntaxNewString("build_xpath", "", "Build an XPath within the XML file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("select_xpath", "", "Select the XPath node in the XML file to edit", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_INSERTTAGS_BODIES[] = { ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_DELETETAGS_BODIES[] = { ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_INSERTATTRIBUTES_BODIES[] = { ConstraintSyntaxNewString("attribute_value", "", "Value of the attribute to be inserted into the XPath node of the XML file", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const ConstraintSyntax CF_DELETEATTRIBUTES_BODIES[] = { ConstraintSyntaxNewNull() }; // Master Syntax for Files const PromiseTypeSyntax CF_FILES_PROMISE_TYPES[] = { /* Body lists belonging to "files:" type in Agent */ PromiseTypeSyntaxNew("agent", "files", CF_FILES_BODIES, NULL, SYNTAX_STATUS_NORMAL), /* Body lists belonging to th edit_line sub-bundle of files: */ PromiseTypeSyntaxNew("edit_line", "*", CF_COMMON_EDITBODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_line", "delete_lines", CF_DELETELINES_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_line", "insert_lines", CF_INSERTLINES_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_line", "field_edits", CF_COLUMN_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_line", "replace_patterns", CF_REPLACE_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "*", CF_COMMON_XMLBODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "build_xpath", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "delete_tree", CF_DELETETAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "insert_tree", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "delete_attribute", CF_DELETEATTRIBUTES_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "set_attribute", CF_INSERTATTRIBUTES_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "delete_text", CF_DELETETAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "set_text", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("edit_xml", "insert_text", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/string_expressions.c0000664000175100017510000001650412243421446021472 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include /* */ static StringParseResult ParseQname(const char *expr, int start, int end) { StringParseResult lhs, rhs; StringExpression *ret, *subret, *dot; lhs = ParseStringExpression(expr, start, end); if (!lhs.result) { return lhs; } if (lhs.position == end || expr[lhs.position] != '.') { return lhs; } rhs = ParseStringExpression(expr, lhs.position + 1, end); if (!rhs.result) { FreeStringExpression(lhs.result); return rhs; } dot = xcalloc(1, sizeof(StringExpression)); dot->op = LITERAL; dot->val.literal.literal = xstrdup("."); subret = xcalloc(1, sizeof(StringExpression)); subret->op = CONCAT; subret->val.concat.lhs = dot; subret->val.concat.rhs = rhs.result; ret = xcalloc(1, sizeof(StringExpression)); ret->op = CONCAT; ret->val.concat.lhs = lhs.result; ret->val.concat.rhs = subret; return (StringParseResult) {ret, rhs.position}; } /* */ static StringParseResult ParseVarRef(const char *expr, int start, int end) { if (start + 1 < end && (expr[start] == '$' || expr[start] == '@')) { if (expr[start + 1] == '(' || expr[start + 1] == '{') { char closing_bracket = expr[start + 1] == '(' ? ')' : '}'; StringParseResult res = ParseQname(expr, start + 2, end); if (res.result) { if (res.position < end && expr[res.position] == closing_bracket) { StringExpression *ret = xcalloc(1, sizeof(StringExpression)); ret->op = VARREF; ret->val.varref.name = res.result; if (expr[start] == '$') { ret->val.varref.type = VAR_REF_TYPE_SCALAR; } else if (expr[start] == '@') { ret->val.varref.type = VAR_REF_TYPE_LIST; } else { ProgrammingError("Unrecognized var ref type"); } return (StringParseResult) {ret, res.position + 1}; } else { FreeStringExpression(res.result); return (StringParseResult) {NULL, res.position}; } } else { return res; } } else { return (StringParseResult) {NULL, start + 1}; } } else { return (StringParseResult) {NULL, start}; } } /* */ static bool ValidTokenCharacter(char c) { if (c >= 'a' && c <= 'z') { return true; } if (c >= 'A' && c <= 'Z') { return true; } if (c >= '0' && c <= '9') { return true; } if (c == '_' || c == '[' || c == ']' || c == ':') { return true; } return false; } static StringParseResult ParseToken(const char *expr, int start, int end) { int endlit = start; while (endlit < end && ValidTokenCharacter(expr[endlit])) { endlit++; } if (endlit > start) { StringExpression *ret = xcalloc(1, sizeof(StringExpression)); ret->op = LITERAL; ret->val.literal.literal = xstrndup(expr + start, endlit - start); return (StringParseResult) {ret, endlit}; } else { return (StringParseResult) {NULL, endlit}; } } /* */ static StringParseResult ParseTerm(const char *expr, int start, int end) { StringParseResult res = ParseToken(expr, start, end); if (res.result) { return res; } else { return ParseVarRef(expr, start, end); } } /* */ StringParseResult ParseStringExpression(const char *expr, int start, int end) { StringParseResult lhs = ParseTerm(expr, start, end); if (lhs.result) { StringParseResult rhs = ParseStringExpression(expr, lhs.position, end); if (rhs.result) { StringExpression *ret = xcalloc(1, sizeof(StringExpression)); ret->op = CONCAT; ret->val.concat.lhs = lhs.result; ret->val.concat.rhs = rhs.result; return (StringParseResult) {ret, rhs.position}; } else { return lhs; } } else { return lhs; } } /* Evaluation */ static char *EvalConcat(const StringExpression *expr, VarRefEvaluator evalfn, void *param) { char *lhs, *rhs, *res; lhs = EvalStringExpression(expr->val.concat.lhs, evalfn, param); if (!lhs) { return NULL; } rhs = EvalStringExpression(expr->val.concat.rhs, evalfn, param); if (!rhs) { free(lhs); return NULL; } xasprintf(&res, "%s%s", lhs, rhs); free(lhs); free(rhs); return res; } static char *EvalVarRef(const StringExpression *expr, VarRefEvaluator evalfn, void *param) { char *name, *eval; name = EvalStringExpression(expr->val.varref.name, evalfn, param); if (!name) { return NULL; } eval = (*evalfn) (name, expr->val.varref.type, param); free(name); return eval; } char *EvalStringExpression(const StringExpression *expr, VarRefEvaluator evalfn, void *param) { switch (expr->op) { case CONCAT: return EvalConcat(expr, evalfn, param); case LITERAL: return xstrdup(expr->val.literal.literal); case VARREF: return EvalVarRef(expr, evalfn, param); default: ProgrammingError("Unknown type of string expression" "encountered during evaluation: %d", expr->op); } } /* Freeing results */ void FreeStringExpression(StringExpression *expr) { if (!expr) { return; } switch (expr->op) { case CONCAT: FreeStringExpression(expr->val.concat.lhs); FreeStringExpression(expr->val.concat.rhs); break; case LITERAL: free(expr->val.literal.literal); break; case VARREF: FreeStringExpression(expr->val.varref.name); break; default: ProgrammingError("Unknown type of string expression encountered: %d", expr->op); } free(expr); } cfengine-3.6.2/libpromises/exec_tools.c0000664000175100017510000001314512400110676017657 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include // CloseLog /********************************************************************/ bool GetExecOutput(const char *command, char *buffer, ShellType shell) /* Buffer initially contains whole exec string */ { int offset = 0; FILE *pp; if (shell == SHELL_TYPE_USE) { pp = cf_popen_sh(command, "rt"); } else if (shell == SHELL_TYPE_POWERSHELL) { #ifdef __MINGW32__ pp = cf_popen_powershell(command, "rt"); #else // !__MINGW32__ Log(LOG_LEVEL_ERR, "Powershell is only supported on Windows"); return false; #endif // __MINGW32__ } else { pp = cf_popen(command, "rt", true); } if (pp == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", command, GetErrorStr()); return false; } memset(buffer, 0, CF_EXPANDSIZE); size_t line_size = CF_EXPANDSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Unable to read output of command '%s'. (fread: %s)", command, GetErrorStr()); cf_pclose(pp); free(line); return false; } else { break; } } if (strlen(line) + offset > CF_EXPANDSIZE - 10) { Log(LOG_LEVEL_ERR, "Buffer exceeded %d bytes in exec '%s'", CF_EXPANDSIZE, command); break; } snprintf(buffer + offset, CF_EXPANDSIZE - offset, "%s\n", line); offset += strlen(line) + 1; } if (offset > 0) { if (Chop(buffer, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } } Log(LOG_LEVEL_DEBUG, "GetExecOutput got '%s'", buffer); cf_pclose(pp); free(line); return true; } /**********************************************************************/ void ActAsDaemon() { int fd; #ifdef HAVE_SETSID setsid(); #endif CloseNetwork(); CloseLog(); fflush(NULL); fd = open(NULLFILE, O_RDWR, 0); if (fd != -1) { if (dup2(fd, STDIN_FILENO) == -1) { Log(LOG_LEVEL_ERR, "Could not dup. (dup2: %s)", GetErrorStr()); } if (dup2(fd, STDOUT_FILENO) == -1) { Log(LOG_LEVEL_ERR, "Could not dup. (dup2: %s)", GetErrorStr()); } dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) { close(fd); } } if (chdir("/")) { UnexpectedError("Failed to chdir into '/'"); } } /**********************************************************************/ #define INITIAL_ARGS 8 char **ArgSplitCommand(const char *comm) { const char *s = comm; int argc = 0; int argslen = INITIAL_ARGS; char **args = xmalloc(argslen * sizeof(char *)); while (*s != '\0') { const char *end; char *arg; if (isspace((int)*s)) /* Skip whitespace */ { s++; continue; } switch (*s) { case '"': /* Look for matching quote */ case '\'': case '`': { char delim = *s++; /* Skip first delimeter */ end = strchr(s, delim); break; } default: /* Look for whitespace */ end = strpbrk(s, " \f\n\r\t\v"); break; } if (end == NULL) /* Delimeter was not found, remaining string is the argument */ { arg = xstrdup(s); s += strlen(arg); } else { arg = xstrndup(s, end - s); s = end; if ((*s == '"') || (*s == '\'') || (*s == '`')) /* Skip second delimeter */ s++; } /* Argument */ if (argc == argslen) { argslen *= 2; args = xrealloc(args, argslen * sizeof(char *)); } args[argc++] = arg; } /* Trailing NULL */ if (argc == argslen) { argslen += 1; args = xrealloc(args, argslen * sizeof(char *)); } args[argc++] = NULL; return args; } /**********************************************************************/ void ArgFree(char **args) { char **arg = args; for (; *arg; ++arg) { free(*arg); } free(args); } cfengine-3.6.2/libpromises/dbm_migration_bundles.c0000644000175100017510000000464112316547775022065 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include static bool BundlesMigrationVersion0(DBHandle *db) { bool errors = false; DBCursor *cursor; if (!NewDBCursor(db, &cursor)) { return false; } char *key; void *value; int ksize, vsize; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { if (ksize == 0) { Log(LOG_LEVEL_INFO, "BundlesMigrationVersion0: Database structure error -- zero-length key."); continue; } if (strchr(key, '.')) // is qualified name? { continue; } char *fqname = StringConcatenate(3, "default", ".", key); if (!WriteDB(db, fqname, value, vsize)) { Log(LOG_LEVEL_INFO, "Unable to write version 1 bundle entry for '%s'", key); errors = true; continue; } if (!DBCursorDeleteEntry(cursor)) { Log(LOG_LEVEL_INFO, "Unable to delete version 0 bundle entry for '%s'", key); errors = true; } } if (DeleteDBCursor(cursor) == false) { Log(LOG_LEVEL_ERR, "BundlesMigrationVersion0: Unable to close cursor"); errors = true; } if ((!errors) && (!WriteDB(db, "version", "1", sizeof("1")))) { errors = true; } return !errors; } const DBMigrationFunction dbm_migration_plan_bundles[] = { BundlesMigrationVersion0, NULL }; cfengine-3.6.2/libpromises/signals.h0000644000175100017510000000246012316547775017200 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SIGNALS_H #define CFENGINE_SIGNALS_H #include // check whether the running daemon should terminate after having received a signal. bool IsPendingTermination(void); void MakeSignalPipe(void); int GetSignalPipe(void); void HandleSignalsForDaemon(int signum); void HandleSignalsForAgent(int signum); #endif cfengine-3.6.2/libpromises/syntax.c0000664000175100017510000011216412411001073017032 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include /* IsStrIn */ #include /* StringMatchFull */ #include #include #include #include static SyntaxTypeMatch CheckParseString(const char *lv, const char *s, const char *range); static SyntaxTypeMatch CheckParseInt(const char *lv, const char *s, const char *range); static SyntaxTypeMatch CheckParseReal(const char *lv, const char *s, const char *range); static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range); static SyntaxTypeMatch CheckParseIntRange(const char *lval, const char *s, const char *range); static SyntaxTypeMatch CheckParseOpts(const char *s, const char *range); static SyntaxTypeMatch CheckFnCallType(const char *s, DataType dtype); /*********************************************************/ static const PromiseTypeSyntax *PromiseTypeSyntaxGetStrict(const char *bundle_type, const char *promise_type) { for (int module_index = 0; module_index < CF3_MODULES; module_index++) { for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++) { const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index]; if (strcmp(bundle_type, promise_type_syntax->bundle_type) == 0 && strcmp(promise_type, promise_type_syntax->promise_type) == 0) { return promise_type_syntax; } } } return NULL; } const PromiseTypeSyntax *PromiseTypeSyntaxGet(const char *bundle_type, const char *promise_type) { const PromiseTypeSyntax *pts = PromiseTypeSyntaxGetStrict(bundle_type, promise_type); if (!pts) { pts = PromiseTypeSyntaxGetStrict("*", promise_type); } return pts; } static const ConstraintSyntax *GetCommonConstraint(const char *lval) { for (int i = 0; CF_COMMON_PROMISE_TYPES[i].promise_type; i++) { const PromiseTypeSyntax promise_type_syntax = CF_COMMON_PROMISE_TYPES[i]; for (int j = 0; promise_type_syntax.constraints[j].lval; j++) { if (strcmp(promise_type_syntax.constraints[j].lval, lval) == 0) { return &promise_type_syntax.constraints[j]; } } } return NULL; } const ConstraintSyntax *BodySyntaxGetConstraintSyntax(const ConstraintSyntax *body_syntax, const char *lval) { for (int j = 0; body_syntax[j].lval; j++) { if (strcmp(body_syntax[j].lval, lval) == 0) { return &body_syntax[j]; } } return NULL; } const ConstraintSyntax *PromiseTypeSyntaxGetConstraintSyntax(const PromiseTypeSyntax *promise_type_syntax, const char *lval) { for (int i = 0; promise_type_syntax->constraints[i].lval; i++) { if (strcmp(promise_type_syntax->constraints[i].lval, lval) == 0) { return &promise_type_syntax->constraints[i]; } } const ConstraintSyntax *constraint_syntax = NULL; if (strcmp("edit_line", promise_type_syntax->bundle_type) == 0) { constraint_syntax = BodySyntaxGetConstraintSyntax(CF_COMMON_EDITBODIES, lval); if (constraint_syntax) { return constraint_syntax; } } else if (strcmp("edit_xml", promise_type_syntax->bundle_type) == 0) { constraint_syntax = BodySyntaxGetConstraintSyntax(CF_COMMON_XMLBODIES, lval); if (constraint_syntax) { return constraint_syntax; } } return GetCommonConstraint(lval); } const BodySyntax *BodySyntaxGet(const char *body_type) { for (int i = 0; i < CF3_MODULES; i++) { const PromiseTypeSyntax *promise_type_syntax = CF_ALL_PROMISE_TYPES[i]; for (int k = 0; promise_type_syntax[k].bundle_type != NULL; k++) { for (int z = 0; promise_type_syntax[k].constraints[z].lval != NULL; z++) { const ConstraintSyntax constraint_syntax = promise_type_syntax[k].constraints[z]; if (constraint_syntax.dtype == CF_DATA_TYPE_BODY && strcmp(body_type, constraint_syntax.lval) == 0) { return constraint_syntax.range.body_type_syntax; } } } } for (int i = 0; CONTROL_BODIES[i].body_type != NULL; i++) { const BodySyntax body_syntax = CONTROL_BODIES[i]; if (strcmp(body_type, body_syntax.body_type) == 0) { return &CONTROL_BODIES[i]; } } return NULL; } const char *SyntaxStatusToString(SyntaxStatus status) { static const char *const status_strings[] = { [SYNTAX_STATUS_DEPRECATED] = "deprecated", [SYNTAX_STATUS_NORMAL] = "normal", [SYNTAX_STATUS_REMOVED] = "removed" }; return status_strings[status]; } /****************************************************************************/ DataType ExpectedDataType(const char *lvalname) { int i, j, k, l; const ConstraintSyntax *bs, *bs2; const PromiseTypeSyntax *ss; for (i = 0; i < CF3_MODULES; i++) { if ((ss = CF_ALL_PROMISE_TYPES[i]) == NULL) { continue; } for (j = 0; ss[j].promise_type != NULL; j++) { if ((bs = ss[j].constraints) == NULL) { continue; } for (k = 0; bs[k].lval != NULL; k++) { if (strcmp(lvalname, bs[k].lval) == 0) { return bs[k].dtype; } } for (k = 0; bs[k].lval != NULL; k++) { if (bs[k].dtype == CF_DATA_TYPE_BODY) { bs2 = bs[k].range.body_type_syntax->constraints; if (bs2 == NULL || bs2 == (void *) CF_BUNDLE) { continue; } for (l = 0; bs2[l].dtype != CF_DATA_TYPE_NONE; l++) { if (strcmp(lvalname, bs2[l].lval) == 0) { return bs2[l].dtype; } } } } } } return CF_DATA_TYPE_NONE; } /****************************************************************************/ /* Level 1 */ /****************************************************************************/ const char *SyntaxTypeMatchToString(SyntaxTypeMatch result) { assert(result < SYNTAX_TYPE_MATCH_MAX); static const char *const msgs[SYNTAX_TYPE_MATCH_MAX] = { [SYNTAX_TYPE_MATCH_OK] = "OK", [SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED] = "Cannot check unexpanded value", [SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED] = "Real range specification should not be enclosed in brackets - just 'a,b'", [SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS] = "Range format specifier should be of form 'a,b'' but got multiple items", [SYNTAX_TYPE_MATCH_ERROR_GOT_SCALAR] = "Attempted to give a scalar to a non-scalar type", [SYNTAX_TYPE_MATCH_ERROR_GOT_LIST] = "Attempted to give a list to a non-list type", [SYNTAX_TYPE_MATCH_ERROR_GOT_NULL] = "Attempted to give a value of type null", [SYNTAX_TYPE_MATCH_ERROR_STRING_UNIX_PERMISSION] = "Error parsing Unix permission string", [SYNTAX_TYPE_MATCH_ERROR_SCALAR_OUT_OF_RANGE] = "Scalar value is out of range", [SYNTAX_TYPE_MATCH_ERROR_EMPTY_SCALAR_OUT_OF_RANGE] = "Empty scalar value is out of range", [SYNTAX_TYPE_MATCH_ERROR_INT_PARSE] = "Cannot parse value as integer", [SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE] = "Integer is out of range", [SYNTAX_TYPE_MATCH_ERROR_REAL_INF] = "Keyword 'inf' has an integer value, cannot be used as real", [SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE] = "Real value is out of range", [SYNTAX_TYPE_MATCH_ERROR_OPTS_OUT_OF_RANGE] = "Selection is out of bounds", [SYNTAX_TYPE_MATCH_ERROR_FNCALL_RETURN_TYPE] = "Function does not return the required type", [SYNTAX_TYPE_MATCH_ERROR_FNCALL_UNKNOWN] = "Unknown function", [SYNTAX_TYPE_MATCH_ERROR_CONTEXT_OUT_OF_RANGE] = "Context string is invalid/out of range" }; return msgs[result]; } SyntaxTypeMatch CheckConstraintTypeMatch(const char *lval, Rval rval, DataType dt, const char *range, int level) { Rlist *rp; Item *checklist; /* Get type of lval */ switch (rval.type) { case RVAL_TYPE_SCALAR: switch (dt) { case CF_DATA_TYPE_STRING_LIST: case CF_DATA_TYPE_INT_LIST: case CF_DATA_TYPE_REAL_LIST: case CF_DATA_TYPE_CONTEXT_LIST: case CF_DATA_TYPE_OPTION_LIST: if (level == 0) { return SYNTAX_TYPE_MATCH_ERROR_GOT_SCALAR; } break; default: /* Only lists are incompatible with scalars */ break; } break; case RVAL_TYPE_LIST: switch (dt) { case CF_DATA_TYPE_STRING_LIST: case CF_DATA_TYPE_INT_LIST: case CF_DATA_TYPE_REAL_LIST: case CF_DATA_TYPE_CONTEXT_LIST: case CF_DATA_TYPE_OPTION_LIST: break; default: return SYNTAX_TYPE_MATCH_ERROR_GOT_LIST; } for (rp = (Rlist *) rval.item; rp != NULL; rp = rp->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(lval, rp->val, dt, range, 1); switch (err) { case SYNTAX_TYPE_MATCH_OK: case SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED: break; default: return err; } } return SYNTAX_TYPE_MATCH_OK; case RVAL_TYPE_FNCALL: /* Fn-like objects are assumed to be parameterized bundles in these... */ checklist = SplitString("bundlesequence,edit_line,edit_xml,usebundle,service_bundle,home_bundle", ','); if (!IsItemIn(checklist, lval)) { SyntaxTypeMatch err = CheckFnCallType(RvalFnCallValue(rval)->name, dt); DeleteItemList(checklist); return err; } DeleteItemList(checklist); return SYNTAX_TYPE_MATCH_OK; case RVAL_TYPE_CONTAINER: break; case RVAL_TYPE_NOPROMISEE: return SYNTAX_TYPE_MATCH_ERROR_GOT_NULL; } /* If we get here, we have a literal scalar type */ switch (dt) { case CF_DATA_TYPE_STRING: case CF_DATA_TYPE_STRING_LIST: return CheckParseString(lval, (const char *) rval.item, range); case CF_DATA_TYPE_INT: case CF_DATA_TYPE_INT_LIST: return CheckParseInt(lval, (const char *) rval.item, range); case CF_DATA_TYPE_REAL: case CF_DATA_TYPE_REAL_LIST: return CheckParseReal(lval, (const char *) rval.item, range); case CF_DATA_TYPE_BODY: case CF_DATA_TYPE_BUNDLE: case CF_DATA_TYPE_CONTAINER: break; case CF_DATA_TYPE_OPTION: case CF_DATA_TYPE_OPTION_LIST: return CheckParseOpts(RvalScalarValue(rval), range); case CF_DATA_TYPE_CONTEXT: case CF_DATA_TYPE_CONTEXT_LIST: return CheckParseContext((const char *) rval.item, range); case CF_DATA_TYPE_INT_RANGE: return CheckParseIntRange(lval, (const char *) rval.item, range); case CF_DATA_TYPE_REAL_RANGE: return CheckParseRealRange(lval, (char *) rval.item, range); default: ProgrammingError("Unknown (unhandled) datatype for lval = %s (CheckConstraintTypeMatch)", lval); break; } return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ DataType StringDataType(EvalContext *ctx, const char *string) { int islist = false; DataType dtype = CF_DATA_TYPE_NONE; /*------------------------------------------------------- What happens if we embed vars in a literal string "$(list)withending" - a list? "$(list1)$(list2)" - not a simple list Disallow these manual concatenations as ambiguous. Demand this syntax to work around vars: "listvar" slist => EmbellishList("prefix$(list)suffix"); ---------------------------------------------------------*/ size_t len = strlen(string); if (*string == '$') { Buffer *inner_value = BufferNew(); if (ExtractScalarReference(inner_value, string, len, true)) { if (!IsExpandable(BufferData(inner_value))) { VarRef *ref = VarRefParse(BufferData(inner_value)); if (EvalContextVariableGet(ctx, ref, &dtype)) { if (DataTypeToRvalType(dtype) == RVAL_TYPE_LIST) { if (!islist) { islist = true; } else { islist = false; } } } VarRefDestroy(ref); } if (BufferSize(inner_value) == strlen(string)) { BufferDestroy(inner_value); return dtype; } else { BufferDestroy(inner_value); return CF_DATA_TYPE_STRING; } } BufferDestroy(inner_value); } return CF_DATA_TYPE_STRING; } /****************************************************************************/ /* Level 1 */ /****************************************************************************/ static SyntaxTypeMatch CheckParseString(const char *lval, const char *s, const char *range) { if (s == NULL) { return SYNTAX_TYPE_MATCH_OK; } if (strlen(range) == 0) { return SYNTAX_TYPE_MATCH_OK; } if (IsNakedVar(s, '@') || IsNakedVar(s, '$')) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } /* Deal with complex strings as special cases */ if (strcmp(lval, "mode") == 0 || strcmp(lval, "search_mode") == 0) { mode_t plus, minus; if (!ParseModeString(s, &plus, &minus)) { return SYNTAX_TYPE_MATCH_ERROR_STRING_UNIX_PERMISSION; } } /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(range, s) || StringMatchFull(range, s)) { return SYNTAX_TYPE_MATCH_OK; } if (IsCf3VarString(s)) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } else if ('\0' == s[0]) { return SYNTAX_TYPE_MATCH_ERROR_EMPTY_SCALAR_OUT_OF_RANGE; } else { return SYNTAX_TYPE_MATCH_ERROR_SCALAR_OUT_OF_RANGE; } return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ SyntaxTypeMatch CheckParseContext(const char *context, const char *range) { if (strlen(range) == 0) { return SYNTAX_TYPE_MATCH_OK; } /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(range, context) || StringMatchFull(range, context)) { return SYNTAX_TYPE_MATCH_OK; } return SYNTAX_TYPE_MATCH_ERROR_CONTEXT_OUT_OF_RANGE; } /****************************************************************************/ static SyntaxTypeMatch CheckParseInt(const char *lval, const char *s, const char *range) { Item *split; int n; long long max = CF_LOWINIT, min = CF_HIGHINIT; // Numeric types are registered by range separated by comma str "min,max" split = SplitString(range, ','); if ((n = ListLen(split)) != 2) { ProgrammingError("INTERN: format specifier for int rvalues is not ok for lval %s - got %d items", lval, n); } sscanf(split->name, "%lld", &min); if (strcmp(split->next->name, "inf") == 0) { max = CF_INFINITY; } else { sscanf(split->next->name, "%lld", &max); } DeleteItemList(split); if (min == CF_HIGHINIT || max == CF_LOWINIT) { ProgrammingError("INTERN: could not parse format specifier for int rvalues for lval %s", lval); } if (IsCf3VarString(s)) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } long val = IntFromString(s); if (val == CF_NOINT) { return SYNTAX_TYPE_MATCH_ERROR_INT_PARSE; } if (val > max || val < min) { return SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE; } return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ static SyntaxTypeMatch CheckParseIntRange(const char *lval, const char *s, const char *range) { Item *split, *ip, *rangep; int n; long long max = CF_LOWINIT, min = CF_HIGHINIT; // Numeric types are registered by range separated by comma str "min,max" if (*s == '[' || *s == '(') { return SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED; } split = SplitString(range, ','); if ((n = ListLen(split)) != 2) { ProgrammingError("Format specifier %s for irange rvalues is not ok for lval %s - got %d items", range, lval, n); } sscanf(split->name, "%lld", &min); if (strcmp(split->next->name, "inf") == 0) { max = CF_INFINITY; } else { sscanf(split->next->name, "%lld", &max); } DeleteItemList(split); if (min == CF_HIGHINIT || max == CF_LOWINIT) { ProgrammingError("Could not parse irange format specifier for int rvalues for lval %s", lval); } if (IsCf3VarString(s)) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } rangep = SplitString(s, ','); if ((n = ListLen(rangep)) != 2) { return SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS; } for (ip = rangep; ip != NULL; ip = ip->next) { long val = IntFromString(ip->name); if (val > max || val < min) { return SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE; } } DeleteItemList(rangep); return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ static SyntaxTypeMatch CheckParseReal(const char *lval, const char *s, const char *range) { Item *split; double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val; int n; if (strcmp(s, "inf") == 0) { return SYNTAX_TYPE_MATCH_ERROR_REAL_INF; } if (IsCf3VarString(s)) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } /* Numeric types are registered by range separated by comma str "min,max" */ split = SplitString(range, ','); if ((n = ListLen(split)) != 2) { ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n); } sscanf(split->name, "%lf", &min); sscanf(split->next->name, "%lf", &max); DeleteItemList(split); if (min == CF_HIGHINIT || max == CF_LOWINIT) { ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval); } if (!DoubleFromString(s, &val)) { return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE; } if (val > max || val < min) { return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE; } return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range) { Item *split, *rangep, *ip; double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val; int n; if (*s == '[' || *s == '(') { return SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED; } if (strcmp(s, "inf") == 0) { return SYNTAX_TYPE_MATCH_ERROR_REAL_INF; } if (IsCf3VarString(s)) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } /* Numeric types are registered by range separated by comma str "min,max" */ split = SplitString(range, ','); if ((n = ListLen(split)) != 2) { ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n); } sscanf(split->name, "%lf", &min); sscanf(split->next->name, "%lf", &max); DeleteItemList(split); if (min == CF_HIGHINIT || max == CF_LOWINIT) { ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval); } rangep = SplitString(s, ','); if ((n = ListLen(rangep)) != 2) { return SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS; } for (ip = rangep; ip != NULL; ip = ip->next) { if (!DoubleFromString(ip->name, &val)) { return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE; } if (val > max || val < min) { return SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE; } } DeleteItemList(rangep); return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ static SyntaxTypeMatch CheckParseOpts(const char *s, const char *range) { Item *split; /* List/menu types are separated by comma str "a,b,c,..." */ if (IsNakedVar(s, '@') || IsNakedVar(s, '$')) { return SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED; } split = SplitString(range, ','); if (!IsItemIn(split, s)) { DeleteItemList(split); return SYNTAX_TYPE_MATCH_ERROR_OPTS_OUT_OF_RANGE; } DeleteItemList(split); return SYNTAX_TYPE_MATCH_OK; } /****************************************************************************/ int CheckParseVariableName(const char *name) { const char *reserved[] = { "promiser", "handle", "promise_filename", "promise_dirname", "promise_linenumber", "this", NULL }; char scopeid[CF_MAXVARSIZE], vlval[CF_MAXVARSIZE]; int count = 0, level = 0; if (IsStrIn(name, reserved)) { return false; } scopeid[0] = '\0'; if (strchr(name, '.')) { for (const char *sp = name; *sp != '\0'; sp++) { switch (*sp) { case '.': if (++count > 1 && level != 1) { return false; } break; case '[': level++; break; case ']': level--; break; default: break; } if (level > 1) { yyerror("Too many levels of [] reserved for array use"); return false; } } if (count == 1) { sscanf(name, "%[^.].%s", scopeid, vlval); if (strlen(scopeid) == 0 || strlen(vlval) == 0) { return false; } } } return true; } /****************************************************************************/ static SyntaxTypeMatch CheckFnCallType(const char *s, DataType dtype) { DataType dt; const FnCallType *fn; fn = FnCallTypeGet(s); if (fn) { dt = fn->dtype; if (dtype != dt) { /* Ok to allow fn calls of correct element-type in lists */ if (dt == CF_DATA_TYPE_STRING && dtype == CF_DATA_TYPE_STRING_LIST) { return SYNTAX_TYPE_MATCH_OK; } if (dt == CF_DATA_TYPE_INT && dtype == CF_DATA_TYPE_INT_LIST) { return SYNTAX_TYPE_MATCH_OK; } if (dt == CF_DATA_TYPE_REAL && dtype == CF_DATA_TYPE_REAL_LIST) { return SYNTAX_TYPE_MATCH_OK; } if (dt == CF_DATA_TYPE_OPTION && dtype == CF_DATA_TYPE_OPTION_LIST) { return SYNTAX_TYPE_MATCH_OK; } if (dt == CF_DATA_TYPE_CONTEXT && dtype == CF_DATA_TYPE_CONTEXT_LIST) { return SYNTAX_TYPE_MATCH_OK; } return SYNTAX_TYPE_MATCH_ERROR_FNCALL_RETURN_TYPE; } else { return SYNTAX_TYPE_MATCH_OK; } } else { return SYNTAX_TYPE_MATCH_ERROR_FNCALL_UNKNOWN; } } /****************************************************************************/ static JsonElement *ConstraintSyntaxToJson(const ConstraintSyntax *constraint_syntax) { JsonElement *json_constraint = JsonObjectCreate(5); JsonObjectAppendString(json_constraint, "attribute", constraint_syntax->lval); JsonObjectAppendString(json_constraint, "status", SyntaxStatusToString(constraint_syntax->status)); JsonObjectAppendString(json_constraint, "type", DataTypeToString(constraint_syntax->dtype)); if (constraint_syntax->dtype != CF_DATA_TYPE_BODY && constraint_syntax->dtype != CF_DATA_TYPE_BUNDLE) { JsonObjectAppendString(json_constraint, "range", constraint_syntax->range.validation_string); } return json_constraint; } static JsonElement *BodySyntaxToJson(const BodySyntax *body_syntax) { JsonElement *json_body = JsonObjectCreate(2); JsonObjectAppendString(json_body, "status", SyntaxStatusToString(body_syntax->status)); { JsonElement *attributes = JsonObjectCreate(50); for (int i = 0; body_syntax->constraints[i].lval; i++) { const ConstraintSyntax *constraint_syntax = &body_syntax->constraints[i]; if (constraint_syntax->status != SYNTAX_STATUS_REMOVED) { JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax); JsonObjectAppendString(json_constraint, "visibility", "body"); JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint); } } JsonObjectAppendObject(json_body, "attributes", attributes); } return json_body; } static JsonElement *JsonBundleTypeNew(void) { JsonElement *json_bundle_type = JsonObjectCreate(2); JsonObjectAppendString(json_bundle_type, "status", SyntaxStatusToString(SYNTAX_STATUS_NORMAL)); JsonObjectAppendArray(json_bundle_type, "promiseTypes", JsonArrayCreate(50)); return json_bundle_type; } static JsonElement *BundleTypesToJson(void) { JsonElement *bundle_types = JsonObjectCreate(50); Seq *common_promise_types = SeqNew(50, free); for (int module_index = 0; module_index < CF3_MODULES; module_index++) { for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++) { const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index]; // skip global constraints if (strcmp("*", promise_type_syntax->promise_type) == 0) { continue; } // collect common promise types to be appended at the end if (strcmp("*", promise_type_syntax->bundle_type) == 0) { SeqAppend(common_promise_types, xstrdup(promise_type_syntax->promise_type)); continue; } if (promise_type_syntax->status == SYNTAX_STATUS_REMOVED) { continue; } JsonElement *bundle_type = JsonObjectGet(bundle_types, promise_type_syntax->bundle_type); if (!bundle_type) { bundle_type = JsonBundleTypeNew(); JsonObjectAppendObject(bundle_types, promise_type_syntax->bundle_type, bundle_type); } assert(bundle_type); JsonElement *promise_types = JsonObjectGet(bundle_type, "promiseTypes"); assert(promise_types); JsonArrayAppendString(promise_types, promise_type_syntax->promise_type); } } // Append the common bundle, which has only common promise types, but is not declared in syntax { JsonElement *bundle_type = JsonBundleTypeNew(); JsonObjectAppendObject(bundle_types, "common", bundle_type); } JsonIterator it = JsonIteratorInit(bundle_types); const char *bundle_type = NULL; while ((bundle_type = JsonIteratorNextKey(&it))) { JsonElement *promise_types = JsonObjectGetAsArray(JsonObjectGetAsObject(bundle_types, bundle_type), "promiseTypes"); for (int i = 0; i < SeqLength(common_promise_types); i++) { const char *common_promise_type = SeqAt(common_promise_types, i); JsonArrayAppendString(promise_types, common_promise_type); } } SeqDestroy(common_promise_types); return bundle_types; } static JsonElement *JsonPromiseTypeNew(SyntaxStatus status) { JsonElement *promise_type = JsonObjectCreate(2); JsonObjectAppendString(promise_type, "status", SyntaxStatusToString(status)); JsonObjectAppendObject(promise_type, "attributes", JsonObjectCreate(50)); return promise_type; } static JsonElement *PromiseTypesToJson(void) { JsonElement *promise_types = JsonObjectCreate(50); const PromiseTypeSyntax *global_promise_type = PromiseTypeSyntaxGet("*", "*"); for (int module_index = 0; module_index < CF3_MODULES; module_index++) { for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++) { const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index]; // skip global and bundle-local common constraints if (strcmp("*", promise_type_syntax->promise_type) == 0) { continue; } if (promise_type_syntax->status == SYNTAX_STATUS_REMOVED) { continue; } JsonElement *promise_type = JsonObjectGet(promise_types, promise_type_syntax->promise_type); if (!promise_type) { promise_type = JsonPromiseTypeNew(promise_type_syntax->status); JsonObjectAppendObject(promise_types, promise_type_syntax->promise_type, promise_type); } assert(promise_type); JsonElement *attributes = JsonObjectGet(promise_type, "attributes"); assert(attributes); for (int i = 0; promise_type_syntax->constraints[i].lval; i++) { const ConstraintSyntax *constraint_syntax = &promise_type_syntax->constraints[i]; JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax); JsonObjectAppendString(json_constraint, "visibility", "promiseType"); JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint); } // append bundle common constraints const PromiseTypeSyntax *bundle_promise_type = PromiseTypeSyntaxGet(promise_type_syntax->bundle_type, "*"); if (strcmp("*", bundle_promise_type->bundle_type) != 0) { for (int i = 0; bundle_promise_type->constraints[i].lval; i++) { const ConstraintSyntax *constraint_syntax = &bundle_promise_type->constraints[i]; JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax); JsonObjectAppendString(json_constraint, "visibility", "bundle"); JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint); } } // append global common constraints for (int i = 0; global_promise_type->constraints[i].lval; i++) { const ConstraintSyntax *constraint_syntax = &global_promise_type->constraints[i]; JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax); JsonObjectAppendString(json_constraint, "visibility", "global"); JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint); } } } return promise_types; } static JsonElement *BodyTypesToJson(void) { JsonElement *body_types = JsonObjectCreate(50); for (int module_index = 0; module_index < CF3_MODULES; module_index++) { for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++) { const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index]; for (int constraint_index = 0; promise_type_syntax->constraints[constraint_index].lval; constraint_index++) { const ConstraintSyntax *constraint_syntax = &promise_type_syntax->constraints[constraint_index]; if (constraint_syntax->dtype != CF_DATA_TYPE_BODY) { continue; } if (constraint_syntax->status == SYNTAX_STATUS_REMOVED) { continue; } const BodySyntax *body_syntax = constraint_syntax->range.body_type_syntax; JsonElement *body_type = JsonObjectGet(body_types, body_syntax->body_type); if (!body_type) { JsonElement *body_type = BodySyntaxToJson(body_syntax); JsonObjectAppendObject(body_types, body_syntax->body_type, body_type); } } } } for (int i = 0; CONTROL_BODIES[i].body_type; i++) { const BodySyntax *body_syntax = &CONTROL_BODIES[i]; if (body_syntax->status == SYNTAX_STATUS_REMOVED) { continue; } JsonElement *body_type = JsonObjectGet(body_types, body_syntax->body_type); if (!body_type) { JsonElement *body_type = BodySyntaxToJson(body_syntax); JsonObjectAppendObject(body_types, body_syntax->body_type, body_type); } } return body_types; } static const char *FnCallCategoryToString(FnCallCategory category) { static const char *const category_str[] = { [FNCALL_CATEGORY_COMM] = "communication", [FNCALL_CATEGORY_DATA] = "data", [FNCALL_CATEGORY_FILES] = "files", [FNCALL_CATEGORY_IO] = "io", [FNCALL_CATEGORY_SYSTEM] = "system", [FNCALL_CATEGORY_UTILS] = "utils" }; return category_str[category]; } static JsonElement *FnCallTypeToJson(const FnCallType *fn_syntax) { JsonElement *json_fn = JsonObjectCreate(10); JsonObjectAppendString(json_fn, "status", SyntaxStatusToString(fn_syntax->status)); JsonObjectAppendString(json_fn, "returnType", DataTypeToString(fn_syntax->dtype)); { JsonElement *params = JsonArrayCreate(10); for (int i = 0; fn_syntax->args[i].pattern; i++) { const FnCallArg *param = &fn_syntax->args[i]; JsonElement *json_param = JsonObjectCreate(2); JsonObjectAppendString(json_param, "type", DataTypeToString(param->dtype)); JsonObjectAppendString(json_param, "range", param->pattern); JsonArrayAppendObject(params, json_param); } JsonObjectAppendArray(json_fn, "parameters", params); } JsonObjectAppendBool(json_fn, "variadic", fn_syntax->options & FNCALL_OPTION_VARARG); JsonObjectAppendBool(json_fn, "cached", fn_syntax->options & FNCALL_OPTION_CACHED); JsonObjectAppendString(json_fn, "category", FnCallCategoryToString(fn_syntax->category)); return json_fn; } static JsonElement *FunctionsToJson(void) { JsonElement *functions = JsonObjectCreate(500); for (int i = 0; CF_FNCALL_TYPES[i].name; i++) { const FnCallType *fn_syntax = &CF_FNCALL_TYPES[i]; if (fn_syntax->status == SYNTAX_STATUS_REMOVED) { continue; } JsonObjectAppendObject(functions, fn_syntax->name, FnCallTypeToJson(fn_syntax)); } return functions; } JsonElement *SyntaxToJson(void) { JsonElement *syntax_tree = JsonObjectCreate(3); JsonObjectAppendObject(syntax_tree, "bundleTypes", BundleTypesToJson()); JsonObjectAppendObject(syntax_tree, "promiseTypes", PromiseTypesToJson()); JsonObjectAppendObject(syntax_tree, "bodyTypes", BodyTypesToJson()); JsonObjectAppendObject(syntax_tree, "functions", FunctionsToJson()); return syntax_tree; } cfengine-3.6.2/libpromises/dbm_migration.h0000664000175100017510000000223112243421446020332 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_DB_MIGRATION_H #define CFENGINE_DB_MIGRATION_H #include typedef bool (*DBMigrationFunction)(DBHandle *db); bool DBMigrate(DBHandle *db, dbid id); #endif cfengine-3.6.2/libpromises/dbm_tokyocab.c0000664000175100017510000002574712400110676020163 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* * Implementation using Tokyo Cabinet hash API. */ #include #include #include #include #ifdef TCDB # include # include struct DBPriv_ { /* * This mutex prevents destructive modifications of the database (removing * records) while the cursor is active on it. */ pthread_mutex_t cursor_lock; TCHDB *hdb; }; struct DBCursorPriv_ { DBPriv *db; char *current_key; int current_key_size; char *curval; /* * Removing a key underneath the active cursor stops the database iteration, * so if key needs to be deleted while database is iterated, this fact is * remembered and once iterator advances to next key, this pending delete is * executed. * * Writes to key underneath the active cursor are safe, so only deletes are * tracked. */ bool pending_delete; }; /******************************************************************************/ static bool LockCursor(DBPriv *db) { int ret = pthread_mutex_lock(&db->cursor_lock); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to obtain cursor lock for Tokyo Cabinet database. (pthread_mutex_lock: %s)", GetErrorStr()); return false; } return true; } static void UnlockCursor(DBPriv *db) { int ret = pthread_mutex_unlock(&db->cursor_lock); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to release cursor lock for Tokyo Cabinet database. (pthread_mutex_unlock: %s)", GetErrorStr()); } } const char *DBPrivGetFileExtension(void) { return "tcdb"; } static const char *ErrorMessage(TCHDB *hdb) { return tchdberrmsg(tchdbecode(hdb)); } static bool OpenTokyoDatabase(const char *filename, TCHDB **hdb) { *hdb = tchdbnew(); if (!tchdbsetmutex(*hdb)) { return false; } if (!tchdbopen(*hdb, filename, HDBOWRITER | HDBOCREAT)) { return false; } static int threshold = -1; /* GLOBAL_X */ if (threshold == -1) { /** Optimize always if TCDB_OPTIMIZE_PERCENT is equal to 100 Never optimize if TCDB_OPTIMIZE_PERCENT is equal to 0 */ const char *perc = getenv("TCDB_OPTIMIZE_PERCENT"); if (perc != NULL) { /* Environment variable exists */ char *end; long result = strtol(perc, &end, 10); /* Environment variable is a number and in 0..100 range */ if (!*end && result >-1 && result < 101) { threshold = 100 - (int)result; } else { /* This corresponds to 1% */ threshold = 99; } } else { /* This corresponds to 1% */ threshold = 99; } } if ((threshold != 100) && (threshold == 0 || (int)(rand()%threshold) == 0)) { if (!tchdboptimize(*hdb, -1, -1, -1, false)) { tchdbclose(*hdb); return false; } } return true; } DBPriv *DBPrivOpenDB(const char *dbpath, ARG_UNUSED dbid id) { DBPriv *db = xcalloc(1, sizeof(DBPriv)); pthread_mutex_init(&db->cursor_lock, NULL); if (!OpenTokyoDatabase(dbpath, &db->hdb)) { Log(LOG_LEVEL_ERR, "Could not open Tokyo database at path '%s'. (OpenTokyoDatabase: %s)", dbpath, ErrorMessage(db->hdb)); int errcode = tchdbecode(db->hdb); if(errcode != TCEMETA && errcode != TCEREAD) { goto err; } tchdbdel(db->hdb); return DB_PRIV_DATABASE_BROKEN; } return db; err: pthread_mutex_destroy(&db->cursor_lock); tchdbdel(db->hdb); free(db); return NULL; } void DBPrivCloseDB(DBPriv *db) { int ret; if ((ret = pthread_mutex_destroy(&db->cursor_lock)) != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to destroy mutex during Tokyo Cabinet database handle close. (pthread_mutex_destroy: %s)", GetErrorStr()); } if (!tchdbclose(db->hdb)) { Log(LOG_LEVEL_ERR, "Closing database failed. (tchdbclose: %s)", ErrorMessage(db->hdb)); } tchdbdel(db->hdb); free(db); } void DBPrivCommit(ARG_UNUSED DBPriv *db) { } bool DBPrivHasKey(DBPriv *db, const void *key, int key_size) { // FIXME: distinguish between "entry not found" and "error occured" return tchdbvsiz(db->hdb, key, key_size) != -1; } int DBPrivGetValueSize(DBPriv *db, const void *key, int key_size) { return tchdbvsiz(db->hdb, key, key_size); } bool DBPrivRead(DBPriv *db, const void *key, int key_size, void *dest, int dest_size) { if (tchdbget3(db->hdb, key, key_size, dest, dest_size) == -1) { if (tchdbecode(db->hdb) != TCENOREC) { Log(LOG_LEVEL_ERR, "Could not read key '%s': (tchdbget3: %s)", (const char *)key, ErrorMessage(db->hdb)); } return false; } return true; } static bool Write(TCHDB *hdb, const void *key, int key_size, const void *value, int value_size) { if (!tchdbput(hdb, key, key_size, value, value_size)) { Log(LOG_LEVEL_ERR, "Could not write key to Tokyo path '%s'. (tchdbput: %s)", tchdbpath(hdb), ErrorMessage(hdb)); return false; } return true; } static bool Delete(TCHDB *hdb, const void *key, int key_size) { if (!tchdbout(hdb, key, key_size) && tchdbecode(hdb) != TCENOREC) { Log(LOG_LEVEL_ERR, "Could not delete Tokyo key. (tchdbout: %s)", ErrorMessage(hdb)); return false; } return true; } /* * This one has to be locked against cursor, or interaction between * write/pending delete might yield surprising results. */ bool DBPrivWrite(DBPriv *db, const void *key, int key_size, const void *value, int value_size) { /* FIXME: get a cursor and see what is the current key */ int ret = Write(db->hdb, key, key_size, value, value_size); return ret; } /* * This one has to be locked against cursor -- deleting entries might interrupt * iteration. */ bool DBPrivDelete(DBPriv *db, const void *key, int key_size) { if (!LockCursor(db)) { return false; } int ret = Delete(db->hdb, key, key_size); UnlockCursor(db); return ret; } DBCursorPriv *DBPrivOpenCursor(DBPriv *db) { if (!LockCursor(db)) { return false; } DBCursorPriv *cursor = xcalloc(1, sizeof(DBCursorPriv)); cursor->db = db; /* Cursor remains locked */ return cursor; } bool DBPrivAdvanceCursor(DBCursorPriv *cursor, void **key, int *key_size, void **value, int *value_size) { *key = tchdbgetnext3(cursor->db->hdb, cursor->current_key, cursor->current_key_size, key_size, (const char **)value, value_size); /* * If there is pending delete on the key, apply it */ if (cursor->pending_delete) { Delete(cursor->db->hdb, cursor->current_key, cursor->current_key_size); } /* This will free the value as well: tchdbgetnext3 returns single allocated * chunk of memory */ free(cursor->current_key); cursor->current_key = *key; cursor->current_key_size = *key_size; cursor->pending_delete = false; return *key != NULL; } bool DBPrivDeleteCursorEntry(DBCursorPriv *cursor) { cursor->pending_delete = true; return true; } bool DBPrivWriteCursorEntry(DBCursorPriv *cursor, const void *value, int value_size) { /* * If a pending deletion of entry has been requested, cancel it */ cursor->pending_delete = false; return Write(cursor->db->hdb, cursor->current_key, cursor->current_key_size, value, value_size); } void DBPrivCloseCursor(DBCursorPriv *cursor) { DBPriv *db = cursor->db; if (cursor->pending_delete) { Delete(db->hdb, cursor->current_key, cursor->current_key_size); } free(cursor->current_key); free(cursor); /* Cursor lock was obtained in DBPrivOpenCursor */ UnlockCursor(db); } char *DBPrivDiagnose(const char *dbpath) { #define SWAB64(num) \ ( \ ((num & 0x00000000000000ffULL) << 56) | \ ((num & 0x000000000000ff00ULL) << 40) | \ ((num & 0x0000000000ff0000ULL) << 24) | \ ((num & 0x00000000ff000000ULL) << 8) | \ ((num & 0x000000ff00000000ULL) >> 8) | \ ((num & 0x0000ff0000000000ULL) >> 24) | \ ((num & 0x00ff000000000000ULL) >> 40) | \ ((num & 0xff00000000000000ULL) >> 56) \ ) static const char *const MAGIC="ToKyO CaBiNeT"; FILE *fp = fopen(dbpath, "r"); if(!fp) { return StringFormat("Error opening file '%s': %s", dbpath, strerror(errno)); } if(fseek(fp, 0, SEEK_END) != 0) { fclose(fp); return StringFormat("Error seeking to end: %s\n", strerror(errno)); } uint64_t size = ftell(fp); if(size < 256) { fclose(fp); return StringFormat("Seek-to-end size less than minimum required: %zd", size); } char hbuf[256]; memset(hbuf, 0, (size_t)256); if(fseek(fp, 0, SEEK_SET) != 0) { fclose(fp); return StringFormat("Error seeking to offset 256: %s", strerror(errno)); } if(fread(&hbuf, 256, 1, fp) != 1) { fclose(fp); return StringFormat("Error reading 256 bytes: %s\n", strerror(errno)); } fclose(fp); if(strncmp(hbuf, MAGIC, strlen(MAGIC)) != 0) { return StringFormat("Magic string mismatch"); } uint64_t declared_size = 0; memcpy(&declared_size, hbuf+56, sizeof(uint64_t)); if (declared_size == size) { return NULL; // all is well } else { declared_size = SWAB64(declared_size); if (declared_size == size) { return StringFormat("Endianness mismatch, declared size SWAB64 '%zd' equals seek-to-end size '%zd'", declared_size, size); } else { return StringFormat("Size mismatch, declared size SWAB64 '%zd', seek-to-end-size '%zd'", declared_size, size); } } } #endif cfengine-3.6.2/libpromises/unix.h0000644000175100017510000000222012316547775016515 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_UNIX_H #define CFENGINE_UNIX_H #include void ProcessSignalTerminate(pid_t pid); int GetCurrentUserName(char *userName, int userNameLen); #endif cfengine-3.6.2/libpromises/enterprise_extension.c0000664000175100017510000000432312412324530021764 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* #### THIS FILE WAS AUTOGENERATED FROM extension_template.* #### */ #include #include #include #ifndef BUILTIN_EXTENSIONS static pthread_once_t enterprise_library_once = PTHREAD_ONCE_INIT; static void *enterprise_library_handle = NULL; static void enterprise_library_assign(); void *enterprise_library_open() { if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") != NULL) { return extension_library_open(ENTERPRISE_LIBRARY_NAME); } int ret = pthread_once(&enterprise_library_once, &enterprise_library_assign); if (ret != 0) { Log(LOG_LEVEL_ERR, "Could not initialize Extension Library: %s: %s", ENTERPRISE_LIBRARY_NAME, strerror(ret)); return NULL; } return enterprise_library_handle; } static void enterprise_library_assign() { enterprise_library_handle = extension_library_open(ENTERPRISE_LIBRARY_NAME); } void enterprise_library_close(void *handle) { if (getenv("CFENGINE_TEST_OVERRIDE_EXTENSION_LIBRARY_DO_CLOSE") != NULL) { return extension_library_close(handle); } // Normally we don't ever close the extension library, because we may have // pointer references to it. } #endif // BUILTIN_EXTENSIONS cfengine-3.6.2/libpromises/item_lib.h0000644000175100017510000001010412316547775017316 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ITEM_LIB_H #define CFENGINE_ITEM_LIB_H #include #include #include struct Item_ { char *name; char *classes; int counter; time_t time; Item *next; }; typedef enum { ITEM_MATCH_TYPE_LITERAL_START, ITEM_MATCH_TYPE_LITERAL_COMPLETE, ITEM_MATCH_TYPE_LITERAL_SOMEWHERE, ITEM_MATCH_TYPE_REGEX_COMPLETE, ITEM_MATCH_TYPE_LITERAL_START_NOT, ITEM_MATCH_TYPE_LITERAL_COMPLETE_NOT, ITEM_MATCH_TYPE_LITERAL_SOMEWHERE_NOT, ITEM_MATCH_TYPE_REGEX_COMPLETE_NOT } ItemMatchType; void PrintItemList(const Item *list, Writer *w); void PrependFullItem(Item **liststart, const char *itemstring, const char *classes, int counter, time_t t); Item *ReturnItemIn(Item *list, const char *item); Item *ReturnItemInClass(Item *list, const char *item, const char *classes); Item *ReturnItemAtIndex(Item *list, int index); Item *EndOfList(Item *start); void PrependItemList(Item **liststart, const char *itemstring); void InsertAfter(Item **filestart, Item *ptr, const char *string); bool RawSaveItemList(const Item *liststart, const char *filename, NewLineMode new_line_mode); Item *RawLoadItemList(const char *filename); Item *SplitStringAsItemList(const char *string, char sep); Item *SplitString(const char *string, char sep); int DeleteItemGeneral(Item **filestart, const char *string, ItemMatchType type); int DeleteItemLiteral(Item **filestart, const char *string); int DeleteItemStarting(Item **list, const char *string); int DeleteItemNotStarting(Item **list, const char *string); int DeleteItemMatching(Item **list, const char *string); int DeleteItemNotMatching(Item **list, const char *string); int DeleteItemContaining(Item **list, const char *string); int DeleteItemNotContaining(Item **list, const char *string); int ListLen(const Item *list); bool IsItemIn(const Item *list, const char *item); bool ListsCompare(const Item *list1, const Item *list2); int IsMatchItemIn(const Item *list, const char *item); Item *ConcatLists(Item *list1, Item *list2); void CopyList(Item **dest, const Item *source); void IdempItemCount(Item **liststart, const char *itemstring, const char *classes); Item *IdempPrependItem(Item **liststart, const char *itemstring, const char *classes); Item *IdempPrependItemClass(Item **liststart, const char *itemstring, const char *classes); Item *ReverseItemList(Item *list); /* Eats list, spits it out reversed. */ Item *PrependItem(Item **liststart, const char *itemstring, const char *classes); /* Warning: AppendItem()'s cost is proportional to list length; it is * usually cheaper to build a list using PrependItem, then reverse it; * building it with AppendItem() is quadratic in length. */ void AppendItem(Item **liststart, const char *itemstring, const char *classes); void DeleteItemList(Item *item); void DeleteItem(Item **liststart, Item *item); void IncrementItemListCounter(Item *ptr, const char *string); void SetItemListCounter(Item *ptr, const char *string, int value); char *ItemList2CSV(const Item *list); size_t ItemList2CSV_bound(const Item *list, char *buf, size_t buf_size, char separator); int ItemListSize(const Item *list); #endif cfengine-3.6.2/libpromises/dbm_lmdb.c0000664000175100017510000003561012400110676017254 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* * Implementation using LMDB API. */ #include #include #include #include #include #include #include #ifdef LMDB #include // Shared between threads. struct DBPriv_ { MDB_env *env; MDB_dbi dbi; // Used to keep track of transactions. // We set this to the transaction address when a thread creates a // transaction, and back to 0x0 when it is destroyed. pthread_key_t txn_key; }; // Not shared between threads. typedef struct DBTxn_ { MDB_txn *txn; // Whether txn is a read/write (true) or read-only (false) transaction. bool rw_txn; } DBTxn; struct DBCursorPriv_ { DBPriv *db; MDB_cursor *mc; MDB_val delkey; void *curkv; bool pending_delete; }; /******************************************************************************/ static int GetReadTransaction(DBPriv *db, MDB_txn **txn) { DBTxn *db_txn = pthread_getspecific(db->txn_key); int rc = MDB_SUCCESS; if (!db_txn) { db_txn = xcalloc(1, sizeof(DBTxn)); pthread_setspecific(db->txn_key, db_txn); } if (!db_txn->txn) { rc = mdb_txn_begin(db->env, NULL, MDB_RDONLY, &db_txn->txn); if (rc != MDB_SUCCESS) { Log(LOG_LEVEL_ERR, "Unable to open read transaction: %s", mdb_strerror(rc)); } } *txn = db_txn->txn; return rc; } static int GetWriteTransaction(DBPriv *db, MDB_txn **txn) { DBTxn *db_txn = pthread_getspecific(db->txn_key); int rc = MDB_SUCCESS; if (!db_txn) { db_txn = xcalloc(1, sizeof(DBTxn)); pthread_setspecific(db->txn_key, db_txn); } if (db_txn->txn && !db_txn->rw_txn) { rc = mdb_txn_commit(db_txn->txn); if (rc != MDB_SUCCESS) { Log(LOG_LEVEL_ERR, "Unable to close read-only transaction: %s", mdb_strerror(rc)); } db_txn->txn = NULL; } if (!db_txn->txn) { rc = mdb_txn_begin(db->env, NULL, 0, &db_txn->txn); if (rc == MDB_SUCCESS) { db_txn->rw_txn = true; } else { Log(LOG_LEVEL_ERR, "Unable to open write transaction: %s", mdb_strerror(rc)); } } *txn = db_txn->txn; return rc; } static void AbortTransaction(DBPriv *db) { DBTxn *db_txn = pthread_getspecific(db->txn_key); if (db_txn != NULL) { if (db_txn->txn != NULL) { mdb_txn_abort(db_txn->txn); } pthread_setspecific(db->txn_key, NULL); free(db_txn); } } static void DestroyTransaction(void *ptr) { DBTxn *db_txn = (DBTxn *)ptr; UnexpectedError("Transaction object still exists when terminating thread"); if (db_txn->txn) { UnexpectedError("Transaction still open when terminating thread!"); mdb_txn_abort(db_txn->txn); } free(db_txn); } const char *DBPrivGetFileExtension(void) { return "lmdb"; } #ifndef LMDB_MAXSIZE #define LMDB_MAXSIZE 104857600 #endif /* Lastseen default number of maxreaders = 4x the default lmdb maxreaders */ #define DEFAULT_LASTSEEN_MAXREADERS (126*4) DBPriv *DBPrivOpenDB(const char *dbpath, dbid id) { DBPriv *db = xcalloc(1, sizeof(DBPriv)); MDB_txn *txn = NULL; int rc; rc = pthread_key_create(&db->txn_key, &DestroyTransaction); if (rc) { Log(LOG_LEVEL_ERR, "Could not create transaction key. (pthread_key_create: '%s')", GetErrorStrFromCode(rc)); free(db); return NULL; } rc = mdb_env_create(&db->env); if (rc) { Log(LOG_LEVEL_ERR, "Could not create handle for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } rc = mdb_env_set_mapsize(db->env, LMDB_MAXSIZE); if (rc) { Log(LOG_LEVEL_ERR, "Could not set mapsize for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } if (id == dbid_lastseen) { /* lastseen needs by default 4x more reader locks than other DBs*/ rc = mdb_env_set_maxreaders(db->env, DEFAULT_LASTSEEN_MAXREADERS); if (rc) { Log(LOG_LEVEL_ERR, "Could not set maxreaders for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } } if (id != dbid_locks) { rc = mdb_env_open(db->env, dbpath, MDB_NOSUBDIR, 0644); } else { rc = mdb_env_open(db->env, dbpath, MDB_NOSUBDIR|MDB_NOSYNC, 0644); } if (rc) { Log(LOG_LEVEL_ERR, "Could not open database %s: %s", dbpath, mdb_strerror(rc)); goto err; } rc = mdb_txn_begin(db->env, NULL, MDB_RDONLY, &txn); if (rc) { Log(LOG_LEVEL_ERR, "Could not open database txn %s: %s", dbpath, mdb_strerror(rc)); goto err; } rc = mdb_open(txn, NULL, 0, &db->dbi); if (rc) { Log(LOG_LEVEL_ERR, "Could not open database dbi %s: %s", dbpath, mdb_strerror(rc)); mdb_txn_abort(txn); goto err; } rc = mdb_txn_commit(txn); if (rc) { Log(LOG_LEVEL_ERR, "Could not commit database dbi %s: %s", dbpath, mdb_strerror(rc)); goto err; } return db; err: if (db->env) { mdb_env_close(db->env); } pthread_key_delete(db->txn_key); free(db); if (rc == MDB_INVALID) { return DB_PRIV_DATABASE_BROKEN; } return NULL; } void DBPrivCloseDB(DBPriv *db) { /* Abort LMDB transaction of the current thread. There should only be some * transaction open when the signal handler or atexit() hook is called. */ AbortTransaction(db); if (db->env) { mdb_env_close(db->env); } pthread_key_delete(db->txn_key); free(db); } void DBPrivCommit(DBPriv *db) { DBTxn *db_txn = pthread_getspecific(db->txn_key); if (db_txn && db_txn->txn) { int rc = mdb_txn_commit(db_txn->txn); if (rc != MDB_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not commit database transaction: %s", mdb_strerror(rc)); } } pthread_setspecific(db->txn_key, NULL); free(db_txn); } bool DBPrivHasKey(DBPriv *db, const void *key, int key_size) { MDB_val mkey, data; MDB_txn *txn; int rc; // FIXME: distinguish between "entry not found" and "error occured" rc = GetReadTransaction(db, &txn); if (rc == MDB_SUCCESS) { mkey.mv_data = (void *)key; mkey.mv_size = key_size; rc = mdb_get(txn, db->dbi, &mkey, &data); if (rc && rc != MDB_NOTFOUND) { Log(LOG_LEVEL_ERR, "Could not read database entry: %s", mdb_strerror(rc)); AbortTransaction(db); } } return rc == MDB_SUCCESS; } int DBPrivGetValueSize(DBPriv *db, const void *key, int key_size) { MDB_val mkey, data; MDB_txn *txn; int rc; data.mv_size = 0; rc = GetReadTransaction(db, &txn); if (rc == MDB_SUCCESS) { mkey.mv_data = (void *)key; mkey.mv_size = key_size; rc = mdb_get(txn, db->dbi, &mkey, &data); if (rc && rc != MDB_NOTFOUND) { Log(LOG_LEVEL_ERR, "Could not read database entry: %s", mdb_strerror(rc)); AbortTransaction(db); } } return data.mv_size; } bool DBPrivRead(DBPriv *db, const void *key, int key_size, void *dest, int dest_size) { MDB_val mkey, data; MDB_txn *txn; int rc; bool ret = false; rc = GetReadTransaction(db, &txn); if (rc == MDB_SUCCESS) { mkey.mv_data = (void *)key; mkey.mv_size = key_size; rc = mdb_get(txn, db->dbi, &mkey, &data); if (rc == MDB_SUCCESS) { if (dest_size > data.mv_size) { dest_size = data.mv_size; } memcpy(dest, data.mv_data, dest_size); ret = true; } else if (rc != MDB_NOTFOUND) { Log(LOG_LEVEL_ERR, "Could not read database entry: %s", mdb_strerror(rc)); AbortTransaction(db); } } return ret; } bool DBPrivWrite(DBPriv *db, const void *key, int key_size, const void *value, int value_size) { MDB_val mkey, data; MDB_txn *txn; int rc = GetWriteTransaction(db, &txn); if (rc == MDB_SUCCESS) { mkey.mv_data = (void *)key; mkey.mv_size = key_size; data.mv_data = (void *)value; data.mv_size = value_size; rc = mdb_put(txn, db->dbi, &mkey, &data, 0); if (rc != MDB_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not write database entry: %s", mdb_strerror(rc)); AbortTransaction(db); } } return rc == MDB_SUCCESS; } bool DBPrivDelete(DBPriv *db, const void *key, int key_size) { MDB_val mkey; MDB_txn *txn; int rc = GetWriteTransaction(db, &txn); if (rc == MDB_SUCCESS) { mkey.mv_data = (void *)key; mkey.mv_size = key_size; rc = mdb_del(txn, db->dbi, &mkey, NULL); if (rc == MDB_NOTFOUND) { Log(LOG_LEVEL_DEBUG, "Entry not found: %s", mdb_strerror(rc)); } else if (rc != MDB_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not delete: %s", mdb_strerror(rc)); AbortTransaction(db); } } return rc == MDB_SUCCESS; } DBCursorPriv *DBPrivOpenCursor(DBPriv *db) { DBCursorPriv *cursor = NULL; MDB_txn *txn; int rc; MDB_cursor *mc; rc = GetWriteTransaction(db, &txn); if (rc == MDB_SUCCESS) { rc = mdb_cursor_open(txn, db->dbi, &mc); if (rc == MDB_SUCCESS) { cursor = xcalloc(1, sizeof(DBCursorPriv)); cursor->db = db; cursor->mc = mc; } else { Log(LOG_LEVEL_ERR, "Could not open cursor: %s", mdb_strerror(rc)); AbortTransaction(db); } /* txn remains with cursor */ } return cursor; } bool DBPrivAdvanceCursor(DBCursorPriv *cursor, void **key, int *key_size, void **value, int *value_size) { MDB_val mkey, data; int rc; bool retval = false; if (cursor->curkv) { free(cursor->curkv); cursor->curkv = NULL; } if ((rc = mdb_cursor_get(cursor->mc, &mkey, &data, MDB_NEXT)) == MDB_SUCCESS) { // Align second buffer to 64-bit boundary, to avoid alignment errors on // certain platforms. size_t keybuf_size = mkey.mv_size; if (keybuf_size & 0x7) { keybuf_size += 8 - (keybuf_size % 8); } cursor->curkv = xmalloc(keybuf_size + data.mv_size); memcpy(cursor->curkv, mkey.mv_data, mkey.mv_size); *key = cursor->curkv; *key_size = mkey.mv_size; *value_size = data.mv_size; memcpy((char *)cursor->curkv+keybuf_size, data.mv_data, data.mv_size); *value = (char *)cursor->curkv + keybuf_size; retval = true; } else if (rc != MDB_NOTFOUND) { Log(LOG_LEVEL_ERR, "Could not advance cursor: %s", mdb_strerror(rc)); } if (cursor->pending_delete) { int r2; /* Position on key to delete */ r2 = mdb_cursor_get(cursor->mc, &cursor->delkey, NULL, MDB_SET); if (r2 == MDB_SUCCESS) { r2 = mdb_cursor_del(cursor->mc, 0); } /* Reposition the cursor if it was valid before */ if (rc == MDB_SUCCESS) { mkey.mv_data = *key; rc = mdb_cursor_get(cursor->mc, &mkey, NULL, MDB_SET); } cursor->pending_delete = false; } return retval; } bool DBPrivDeleteCursorEntry(DBCursorPriv *cursor) { int rc = mdb_cursor_get(cursor->mc, &cursor->delkey, NULL, MDB_GET_CURRENT); if (rc == MDB_SUCCESS) { cursor->pending_delete = true; } return rc == MDB_SUCCESS; } bool DBPrivWriteCursorEntry(DBCursorPriv *cursor, const void *value, int value_size) { MDB_val data; int rc; cursor->pending_delete = false; data.mv_data = (void *)value; data.mv_size = value_size; if (cursor->curkv) { MDB_val curkey; curkey.mv_data = cursor->curkv; curkey.mv_size = sizeof(cursor->curkv); if ((rc = mdb_cursor_put(cursor->mc, &curkey, &data, MDB_CURRENT)) != MDB_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not write cursor entry: %s", mdb_strerror(rc)); } } else { Log(LOG_LEVEL_ERR, "Could not write cursor entry: cannot find current key"); rc = MDB_INVALID; } return rc == MDB_SUCCESS; } void DBPrivCloseCursor(DBCursorPriv *cursor) { if (cursor->curkv) { free(cursor->curkv); } if (cursor->pending_delete) { mdb_cursor_del(cursor->mc, 0); } mdb_cursor_close(cursor->mc); free(cursor); } char *DBPrivDiagnose(const char *dbpath) { return StringFormat("Unable to diagnose LMDB file (not implemented) for '%s'", dbpath); } int UpdateLastSeenMaxReaders(int maxreaders) { int rc = 0; /* We assume that every cf_lastseen DB has already a minimum of 504 maxreaders */ if (maxreaders > DEFAULT_LASTSEEN_MAXREADERS) { char workbuf[CF_BUFSIZE]; MDB_env *env = NULL; rc = mdb_env_create(&env); if (rc) { Log(LOG_LEVEL_ERR, "Could not create lastseen database env : %s", mdb_strerror(rc)); goto err; } rc = mdb_env_set_maxreaders(env, maxreaders); if (rc) { Log(LOG_LEVEL_ERR, "Could not change lastseen maxreaders to %d : %s", maxreaders, mdb_strerror(rc)); goto err; } snprintf(workbuf, CF_BUFSIZE, "%s%ccf_lastseen.lmdb", GetWorkDir(), FILE_SEPARATOR); rc = mdb_env_open(env, workbuf, MDB_NOSUBDIR, 0644); if (rc) { Log(LOG_LEVEL_ERR, "Could not open lastseen database env : %s", mdb_strerror(rc)); } err: if (env) { mdb_env_close(env); } } return rc; } #endif cfengine-3.6.2/libpromises/mod_services.h0000664000175100017510000000217212243421446020205 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_SERVICES_H #define CFENGINE_MOD_SERVICES_H #include extern const PromiseTypeSyntax CF_SERVICES_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/dbm_priv.h0000644000175100017510000000534712352022221017317 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_DBM_PRIV_H #define CFENGINE_DBM_PRIV_H /* DBM implementation is supposed to define the following structures and * implement the following functions */ typedef struct DBPriv_ DBPriv; typedef struct DBCursorPriv_ DBCursorPriv; const char *DBPrivGetFileExtension(void); #define DB_PRIV_DATABASE_BROKEN ((DBPriv *)-1) /* * These two functions will always be called with a per-database lock held. */ /* * Should return either * - NULL in case of generic error * - DB_PRIV_DATABASE_BROKEN in case database file is broken, need to be moved away and attempt to open database again should be performed. * - valid pointer to DBPriv * in case database was opened successfully. */ DBPriv *DBPrivOpenDB(const char *dbpath, dbid id); void DBPrivCloseDB(DBPriv *hdbp); void DBPrivCommit(DBPriv *hdbp); bool DBPrivHasKey(DBPriv *db, const void *key, int key_size); int DBPrivGetValueSize(DBPriv *db, const void *key, int key_size); bool DBPrivRead(DBPriv *db, const void *key, int key_size, void *dest, int dest_size); bool DBPrivWrite(DBPriv *db, const void *key, int key_size, const void *value, int value_size); bool DBPrivDelete(DBPriv *db, const void *key, int key_size); DBCursorPriv *DBPrivOpenCursor(DBPriv *db); bool DBPrivAdvanceCursor(DBCursorPriv *cursor, void **key, int *key_size, void **value, int *value_size); bool DBPrivDeleteCursorEntry(DBCursorPriv *cursor); bool DBPrivWriteCursorEntry(DBCursorPriv *cursor, const void *value, int value_size); void DBPrivCloseCursor(DBCursorPriv *cursor); /** * @brief Check a database file for consistency * @param dbpath Path to database file * @return NULL if successful, else an error string that must be freed */ char *DBPrivDiagnose(const char *dbpath); #endif cfengine-3.6.2/libpromises/mod_files.h0000664000175100017510000000233412243421446017464 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_FILES_H #define CFENGINE_MOD_FILES_H #include extern const PromiseTypeSyntax CF_FILES_PROMISE_TYPES[]; extern const ConstraintSyntax CF_COMMON_EDITBODIES[]; extern const ConstraintSyntax CF_COMMON_XMLBODIES[]; #endif cfengine-3.6.2/libpromises/mod_measurement.c0000664000175100017510000000603712243421446020706 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax match_value_constraints[] = { /* Row models */ ConstraintSyntaxNewString("select_line_matching", CF_ANYSTRING, "Regular expression for matching line location", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("select_line_number", CF_VALRANGE, "Read from the n-th line of the output (fixed format)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("extraction_regex", "", "Regular expression that should contain a single backreference for extracting a value", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("track_growing_file", "If true, cfengine remembers the position to which is last read when opening the file, and resets to the start if the file has since been truncated", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("select_multiline_policy", "average,sum,first,last", "Regular expression for matching line location", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax match_value_body = BodySyntaxNew("match_value", match_value_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax CF_MEASURE_BODIES[] = { ConstraintSyntaxNewOption("stream_type", "pipe,file", "The datatype being collected.", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("data_type", "counter,int,real,string,slist", "The datatype being collected.", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("history_type", "weekly,scalar,static,log", "Whether the data can be seen as a time-series or just an isolated value", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("units", "", "The engineering dimensions of this value or a note about its intent used in plots", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("match_value", &match_value_body, "Criteria for extracting the measurement from a datastream", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_MEASUREMENT_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("monitor", "measurements", CF_MEASURE_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/mod_packages.c0000664000175100017510000001626012243421446020136 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax package_method_constraints[] = { ConstraintSyntaxNewString("package_add_command", CF_PATHRANGE, "Command to install a package to the system", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_arch_regex", "", "Regular expression with one backreference to extract package architecture string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("package_changes", "individual,bulk", "Menu option - whether to group packages into a single aggregate command", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_delete_command", CF_PATHRANGE, "Command to remove a package from the system", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_delete_convention", "", "This is how the package manager expects the package to be referred to in the deletion part of a package update, e.g. $(name)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("package_file_repositories", "", "A list of machine-local directories to search for packages", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_installed_regex", "", "Regular expression which matches packages that are already installed", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_default_arch_command", CF_ABSPATHRANGE, "Command to detect the default packages' architecture", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_list_arch_regex", "", "Regular expression with one backreference to extract package architecture string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_list_command", CF_PATHRANGE, "Command to obtain a list of available packages", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_list_name_regex", "", "Regular expression with one backreference to extract package name string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_list_update_command", "", "Command to update the list of available packages (if any)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("package_list_update_ifelapsed", CF_INTRANGE, "The ifelapsed locking time in between updates of the package list", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_list_version_regex", "", "Regular expression with one backreference to extract package version string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_name_convention", "", "This is how the package manager expects the package to be referred to, e.g. $(name).$(arch)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_name_regex", "", "Regular expression with one backreference to extract package name string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_noverify_regex", "", "Regular expression to match verification failure output", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("package_noverify_returncode", CF_INTRANGE, "Integer return code indicating package verification failure", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_patch_arch_regex", "", "Regular expression with one backreference to extract update architecture string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_patch_command", CF_PATHRANGE, "Command to update to the latest patch release of an installed package", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_patch_installed_regex", "", "Regular expression which matches packages that are already installed", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_patch_list_command", CF_PATHRANGE, "Command to obtain a list of available patches or updates", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_patch_name_regex", "", "Regular expression with one backreference to extract update name string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_patch_version_regex", "", "Regular expression with one backreference to extract update version string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_update_command", CF_PATHRANGE, "Command to update to the latest version a currently installed package", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_verify_command", CF_PATHRANGE, "Command to verify the correctness of an installed package", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_version_regex", "", "Regular expression with one backreference to extract package version string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_multiline_start", "", "Regular expression which matches the start of a new package in multiline output", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("package_commands_useshell", "Whether to use shell for commands in this body. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_version_less_command", CF_PATHRANGE, "Command to check whether first supplied package version is less than second one", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_version_equal_command", CF_PATHRANGE, "Command to check whether first supplied package version is equal to second one", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax package_method_body = BodySyntaxNew("package_method", package_method_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax packages_constraints[] = { ConstraintSyntaxNewStringList("package_architectures", "", "Select the architecture for package selection", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("package_method", &package_method_body, "Criteria for installation and verification", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("package_policy", "add,delete,reinstall,update,addupdate,patch,verify", "Criteria for package installation/upgrade on the current system. Default value: verify", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("package_select", ">,<,==,!=,>=,<=", "A criterion for first acceptable match relative to \"package_version\"", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("package_version", "", "Version reference point for determining promised version", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_PACKAGES_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "packages", packages_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/extensions.h0000664000175100017510000000245712243421446017730 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #ifdef BUILTIN_EXTENSIONS // No effect if using builtin extensions. static inline void extension_libraries_disable() { } #else // !BUILTIN_EXTENSIONS void extension_libraries_disable(); void *extension_library_open(const char *name); void extension_library_close(void *handle); #endif // !BUILTIN_EXTENSIONS cfengine-3.6.2/libpromises/expand.c0000664000175100017510000011627012411001073016765 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CF_MAPPEDLIST '#' static PromiseResult ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp, Rlist *lists, Rlist *containers, PromiseActuator *ActOnPromise, void *param); static void ExpandAndMapIteratorsFromScalar(EvalContext *ctx, const Bundle *bundle, char *string, size_t length, int level, Rlist **scalars, Rlist **lists, Rlist **containers, Rlist **full_expansion); static void CopyLocalizedReferencesToBundleScope(EvalContext *ctx, const Bundle *bundle, const Rlist *ref_names); /* Expanding variables is easy -- expanding lists automagically requires some thought. Remember that promiser <=> RVAL_TYPE_SCALAR promisee <=> RVAL_TYPE_LIST Expanding all bodies in the constraint list, we have lval <=> RVAL_TYPE_LIST|RVAL_TYPE_SCALAR Now the rule for variable substitution is that any list variable @(name) substituted directly for a LIST is not iterated, but dropped into place, i.e. in list-lvals and the promisee (since this would be equivalent to a re-concatenation of the expanded separate promises) Any list variable occuring within a scalar or in place of a scalar is assumed to be iterated i.e. $(name). To expand a promise, we build temporary hash tables. There are two stages, to this - one is to create a promise copy including all of the body templates and translate the parameters. This requires one round of expansion with scopeid "body". Then we use this fully assembled promise and expand vars and function calls. To expand the variables in a promise we need to -- first get all strings, also parameterized bodies, which could also be lists / // MapIteratorsFromRval("scope",&lol,"ksajd$(one)$(two)...$(three)"); \/ -- compile an ordered list of variables involved , with types - / assume all are lists - these are never inside sub-bodies by design, \/ so all expansion data are in the promise itself can also be variables based on list items - derived like arrays x[i] -- Copy the promise to a temporary promise + constraint list, expanding one by one, / then execute that \/ -- In a sub-bundle, create a new context and make hashes of the the transferred variables in the temporary context -- bodies cannot contain iterators -- we've already checked types of lhs rhs, must match so an iterator can only be in a non-naked variable? -- form the outer loops to generate combinations Note, we map the current context into a fluid context "this" that maps every list into a scalar during iteration. Thus "this" never contains lists. This presents a problem for absolute references like $(abs.var), since these cannot be mapped into "this" without some magic. **********************************************************************/ PromiseResult ExpandPromise(EvalContext *ctx, const Promise *pp, PromiseActuator *ActOnPromise, void *param) { Log(LOG_LEVEL_VERBOSE, "Evaluating promise '%s'", pp->promiser); if (!IsDefinedClass(ctx, pp->classes)) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); Log(LOG_LEVEL_VERBOSE, "Skipping whole next promise (%s), as context %s is not relevant", pp->promiser, pp->classes); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); } else { Log(LOG_LEVEL_VERBOSE, "Skipping next promise '%s', as context '%s' is not relevant", pp->promiser, pp->classes); } return PROMISE_RESULT_SKIPPED; } Rlist *lists = NULL; Rlist *scalars = NULL; Rlist *containers = NULL; Promise *pcopy = DeRefCopyPromise(ctx, pp); MapIteratorsFromRval(ctx, PromiseGetBundle(pp), (Rval) { pcopy->promiser, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers); if (pcopy->promisee.item != NULL) { MapIteratorsFromRval(ctx, PromiseGetBundle(pp), pp->promisee, &scalars, &lists, &containers); } for (size_t i = 0; i < SeqLength(pcopy->conlist); i++) { Constraint *cp = SeqAt(pcopy->conlist, i); MapIteratorsFromRval(ctx, PromiseGetBundle(pp), cp->rval, &scalars, &lists, &containers); } CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), lists); CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), scalars); CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), containers); PromiseResult result = ExpandPromiseAndDo(ctx, pcopy, lists, containers, ActOnPromise, param); PromiseDestroy(pcopy); RlistDestroy(lists); RlistDestroy(scalars); RlistDestroy(containers); return result; } static PromiseResult ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp, Rlist *lists, Rlist *containers, PromiseActuator *ActOnPromise, void *param) { const char *handle = PromiseGetHandle(pp); EvalContextStackPushPromiseFrame(ctx, pp, true); PromiseIterator *iter_ctx = NULL; size_t i = 0; PromiseResult result = PROMISE_RESULT_SKIPPED; Buffer *expbuf = BufferNew(); for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); i++, PromiseIteratorNext(iter_ctx)) { if (handle) { // This ordering is necessary to get automated canonification BufferClear(expbuf); ExpandScalar(ctx, NULL, "this", handle, expbuf); CanonifyNameInPlace(BufferGet(expbuf)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", BufferData(expbuf), CF_DATA_TYPE_STRING, "source=promise"); } else { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), CF_DATA_TYPE_STRING, "source=promise"); } const Promise *pexp = EvalContextStackPushPromiseIterationFrame(ctx, i, iter_ctx); if (!pexp) { // excluded result = PromiseResultUpdate(result, PROMISE_RESULT_SKIPPED); continue; } PromiseResult iteration_result = ActOnPromise(ctx, pexp, param); NotifyDependantPromises(ctx, pexp, iteration_result); result = PromiseResultUpdate(result, iteration_result); if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0) { VerifyVarPromise(ctx, pexp, true); } EvalContextStackPopFrame(ctx); } BufferDestroy(expbuf); PromiseIteratorDestroy(iter_ctx); EvalContextStackPopFrame(ctx); return result; } void MapIteratorsFromRval(EvalContext *ctx, const Bundle *bundle, Rval rval, Rlist **scalars, Rlist **lists, Rlist **containers) { assert(rval.item); if (rval.item == NULL) { return; } switch (rval.type) { case RVAL_TYPE_SCALAR: { char *val = RvalScalarValue(rval); size_t val_len = strlen(val); ExpandAndMapIteratorsFromScalar(ctx, bundle, val, val_len, 0, scalars, lists, containers, NULL); } break; case RVAL_TYPE_LIST: for (const Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next) { MapIteratorsFromRval(ctx, bundle, rp->val, scalars, lists, containers); } break; case RVAL_TYPE_FNCALL: ExpandAndMapIteratorsFromScalar(ctx, bundle, RvalFnCallValue(rval)->name, strlen(RvalFnCallValue(rval)->name), 0, scalars, lists, containers, NULL); for (const Rlist *rp = RvalFnCallValue(rval)->args; rp; rp = rp->next) { Log(LOG_LEVEL_DEBUG, "Looking at arg for function-like object '%s'", RvalFnCallValue(rval)->name); MapIteratorsFromRval(ctx, bundle, rp->val, scalars, lists, containers); } break; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_NOPROMISEE: Log(LOG_LEVEL_DEBUG, "Unknown Rval type for scope '%s'", bundle->name); break; } } /*********************************************************************/ static void RlistConcatInto(Rlist **dest, const Rlist *src, const char *extension) { assert(dest); size_t count = 0; for (const Rlist *rp = src; rp != NULL; rp = rp->next) { count++; char temp[CF_EXPANDSIZE] = ""; snprintf(temp, CF_EXPANDSIZE, "%s%s", RlistScalarValue(rp), extension); RlistAppendScalarIdemp(dest, temp); } if (count == 0) { RlistAppendScalarIdemp(dest, extension); } } static void MangleVarRefString(char *ref_str, size_t len) { for (size_t i = 0; i < len; i++) { if (ref_str[i] == ':') { ref_str[i] = '*'; } else if (ref_str[i] == '.') { ref_str[i] = '#'; } else if (ref_str[i] == '\0' || ref_str[i] == '[') { return; } } } static void DeMangleVarRefString(char *ref_str, size_t len) { for (size_t i = 0; i < len; i++) { if (ref_str[i] == '*') { ref_str[i] = ':'; } else if (ref_str[i] == '#') { ref_str[i] = '.'; } else if (ref_str[i] == '[') { return; } } } static void ExpandAndMapIteratorsFromScalar(EvalContext *ctx, const Bundle *bundle, char *string, size_t length, int level, Rlist **scalars, Rlist **lists, Rlist **containers, Rlist **full_expansion) { assert(string); if (!string) { return; } Buffer *value = BufferNew(); for (size_t i = 0; i < length; i++) { const char *sp = string + i; Rlist *tmp_list = NULL; BufferClear(value); if (ExtractScalarPrefix(value, sp, length - i)) { if (full_expansion) { RlistConcatInto(&tmp_list, *full_expansion, BufferData(value)); RlistDestroy(*full_expansion); *full_expansion = tmp_list; tmp_list = NULL; } sp += BufferSize(value); i += BufferSize(value); BufferClear(value); if (i >= length) { break; } } if (*sp == '$') { BufferClear(value); ExtractScalarReference(value, sp, length - i, true); if (BufferSize(value) > 0) { Rlist *inner_expansion = NULL; Rlist *exp = NULL; int success = 0; VarRef *ref = VarRefParse(BufferData(value)); int increment = BufferSize(value) - 1 + 3; // Handle any embedded variables char *substring = string + i + 2; ExpandAndMapIteratorsFromScalar(ctx, bundle, substring, BufferSize(value), level+1, scalars, lists, containers, &inner_expansion); for (exp = inner_expansion; exp != NULL; exp = exp->next) { // If a list is non-local, i.e. $(bundle.var), map it to local $(bundle#var) // NB without modifying variables as we map them, it's not // possible to handle remote lists referenced by a variable // scope. For example: // scope => "test."; var => "somelist"; $($(scope)$(var)) fails // varname => "test.somelist"; $($(varname)) also fails // TODO Unless the consumer handles it? const char *inner_ref_str = RlistScalarValue(exp); VarRef *inner_ref = VarRefParseFromBundle(inner_ref_str, bundle); // var is the expanded name of the variable in its native context // finalname will be the mapped name in the local context "this." DataType value_type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, inner_ref, &value_type); if (value) { char *mangled_inner_ref = xstrdup(inner_ref_str); MangleVarRefString(mangled_inner_ref, strlen(mangled_inner_ref)); success++; switch (DataTypeToRvalType(value_type)) { case RVAL_TYPE_LIST: if (level > 0) { RlistPrependScalarIdemp(lists, mangled_inner_ref); } else { RlistAppendScalarIdemp(lists, mangled_inner_ref); } if (full_expansion) { for (const Rlist *rp = value; rp != NULL; rp = rp->next) { // append each slist item to each of full_expansion RlistConcatInto(&tmp_list, *full_expansion, RlistScalarValue(rp)); } } break; case RVAL_TYPE_SCALAR: RlistAppendScalarIdemp(scalars, mangled_inner_ref); if (full_expansion) { // append the scalar value to each of full_expansion RlistConcatInto(&tmp_list, *full_expansion, value); } break; case RVAL_TYPE_CONTAINER: if (level > 0) { RlistPrependScalarIdemp(containers, mangled_inner_ref); } else { RlistAppendScalarIdemp(containers, mangled_inner_ref); } break; case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: break; } free(mangled_inner_ref); } VarRefDestroy(inner_ref); } RlistDestroy(inner_expansion); if (full_expansion) { RlistDestroy(*full_expansion); *full_expansion = tmp_list; tmp_list = NULL; } // No need to map this.* even though it's technically qualified if (success && IsQualifiedVariable(BufferData(value)) && strcmp(ref->scope, "this") != 0) { char *dotpos = strchr(substring, '.'); if (dotpos) { *dotpos = CF_MAPPEDLIST; // replace '.' with '#' } if (strchr(BufferData(value), ':')) { char *colonpos = strchr(substring, ':'); if (colonpos) { *colonpos = '*'; } } } VarRefDestroy(ref); sp += increment; i += increment; } } } BufferDestroy(value); } /*********************************************************************/ static Rval ExpandListEntry(EvalContext *ctx, const char *ns, const char *scope, int expandnaked, Rval entry) { if (entry.type == RVAL_TYPE_SCALAR && IsNakedVar(entry.item, '@')) { if (expandnaked) { char naked[CF_MAXVARSIZE]; GetNaked(naked, entry.item); if (IsExpandable(naked)) { Buffer *out = BufferNew(); ExpandScalar(ctx, ns, scope, naked, out); strlcpy(naked, BufferData(out), CF_MAXVARSIZE); BufferDestroy(out); } if (!IsExpandable(naked)) { VarRef *ref = VarRefParseFromScope(naked, scope); DataType value_type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &value_type); VarRefDestroy(ref); if (value) { return ExpandPrivateRval(ctx, ns, scope, value, DataTypeToRvalType(value_type)); } } } else { return RvalNew(entry.item, RVAL_TYPE_SCALAR); } } return ExpandPrivateRval(ctx, ns, scope, entry.item, entry.type); } Rlist *ExpandList(EvalContext *ctx, const char *ns, const char *scope, const Rlist *list, int expandnaked) { Rlist *start = NULL; for (const Rlist *rp = list; rp != NULL; rp = rp->next) { Rval returnval = ExpandListEntry(ctx, ns, scope, expandnaked, rp->val); RlistAppend(&start, returnval.item, returnval.type); RvalDestroy(returnval); } return start; } /*********************************************************************/ Rval ExpandPrivateRval(EvalContext *ctx, const char *ns, const char *scope, const void *rval_item, RvalType rval_type) { Rval returnval; returnval.item = NULL; returnval.type = RVAL_TYPE_NOPROMISEE; switch (rval_type) { case RVAL_TYPE_SCALAR: { Buffer *buffer = BufferNew(); ExpandScalar(ctx, ns, scope, rval_item, buffer); returnval = (Rval) { BufferClose(buffer), RVAL_TYPE_SCALAR }; } break; case RVAL_TYPE_LIST: returnval.item = ExpandList(ctx, ns, scope, rval_item, true); returnval.type = RVAL_TYPE_LIST; break; case RVAL_TYPE_FNCALL: returnval.item = ExpandFnCall(ctx, ns, scope, rval_item); returnval.type = RVAL_TYPE_FNCALL; break; case RVAL_TYPE_CONTAINER: returnval = RvalNew(rval_item, RVAL_TYPE_CONTAINER); break; case RVAL_TYPE_NOPROMISEE: break; } return returnval; } /*********************************************************************/ Rval ExpandBundleReference(EvalContext *ctx, const char *ns, const char *scope, Rval rval) { // Allocates new memory for the copy switch (rval.type) { case RVAL_TYPE_SCALAR: { Buffer *buffer = BufferNew(); ExpandScalar(ctx, ns, scope, RvalScalarValue(rval), buffer); return (Rval) { BufferClose(buffer), RVAL_TYPE_SCALAR }; } case RVAL_TYPE_FNCALL: return (Rval) {ExpandFnCall(ctx, ns, scope, RvalFnCallValue(rval)), RVAL_TYPE_FNCALL}; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_LIST: case RVAL_TYPE_NOPROMISEE: return RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } assert(false); return RvalNew(NULL, RVAL_TYPE_NOPROMISEE); } bool ExpandScalar(const EvalContext *ctx, const char *ns, const char *scope, const char *string, Buffer *out) { assert(string); if (strlen(string) == 0) { return true; } bool fully_expanded = true; Buffer *current_item = BufferNew(); for (const char *sp = string; *sp != '\0'; sp++) { BufferClear(current_item); ExtractScalarPrefix(current_item, sp, strlen(sp)); BufferAppend(out, BufferData(current_item), BufferSize(current_item)); sp += BufferSize(current_item); if (*sp == '\0') { break; } BufferClear(current_item); char varstring = sp[1]; ExtractScalarReference(current_item, sp, strlen(sp), true); sp += BufferSize(current_item) + 2; if (IsCf3VarString(BufferData(current_item))) { Buffer *temp = BufferCopy(current_item); BufferClear(current_item); ExpandScalar(ctx, ns, scope, BufferData(temp), current_item); BufferDestroy(temp); } if (!IsExpandable(BufferData(current_item))) { DataType type = CF_DATA_TYPE_NONE; const void *value = NULL; { VarRef *ref = VarRefParseFromNamespaceAndScope(BufferData(current_item), ns, scope, CF_NS, '.'); value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); } if (value) { switch (DataTypeToRvalType(type)) { case RVAL_TYPE_SCALAR: BufferAppendString(out, value); continue; case RVAL_TYPE_CONTAINER: if (JsonGetElementType((JsonElement*)value) == JSON_ELEMENT_TYPE_PRIMITIVE) { BufferAppendString(out, JsonPrimitiveGetAsString((JsonElement*)value)); continue; } break; default: break; } } } if (varstring == '{') { BufferAppendF(out, "${%s}", BufferData(current_item)); } else { BufferAppendF(out, "$(%s)", BufferData(current_item)); } } BufferDestroy(current_item); return fully_expanded; } /*********************************************************************/ Rval EvaluateFinalRval(EvalContext *ctx, const Policy *policy, const char *ns, const char *scope, Rval rval, bool forcelist, const Promise *pp) { assert(ctx); assert(policy); Rval returnval; if (rval.type == RVAL_TYPE_SCALAR && IsNakedVar(rval.item, '@')) { /* Treat lists specially here */ char naked[CF_MAXVARSIZE]; GetNaked(naked, rval.item); if (IsExpandable(naked)) { returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type); } else { VarRef *ref = VarRefParseFromScope(naked, scope); DataType value_type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &value_type); if (!value || DataTypeToRvalType(value_type) != RVAL_TYPE_LIST) { returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type); } else { returnval.item = ExpandList(ctx, ns, scope, value, true); returnval.type = RVAL_TYPE_LIST; } VarRefDestroy(ref); } } else if (forcelist) /* We are replacing scalar @(name) with list */ { returnval = ExpandPrivateRval(ctx, ns, scope, rval.item, rval.type); } else if (FnCallIsBuiltIn(rval)) { returnval = RvalCopy(rval); } else { returnval = ExpandPrivateRval(ctx, NULL, "this", rval.item, rval.type); } switch (returnval.type) { case RVAL_TYPE_SCALAR: case RVAL_TYPE_CONTAINER: break; case RVAL_TYPE_LIST: for (Rlist *rp = RvalRlistValue(returnval); rp; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_FNCALL: { FnCall *fp = RlistFnCallValue(rp); rp->val = FnCallEvaluate(ctx, policy, fp, pp).rval; FnCallDestroy(fp); break; } case RVAL_TYPE_SCALAR: if (EvalContextStackCurrentPromise(ctx) && IsCf3VarString(RlistScalarValue(rp))) { void *prior = rp->val.item; rp->val = ExpandPrivateRval(ctx, NULL, "this", prior, RVAL_TYPE_SCALAR); free(prior); } /* else: returnval unchanged. */ break; default: assert(!"Bad type for entry in Rlist"); } } break; case RVAL_TYPE_FNCALL: if (FnCallIsBuiltIn(returnval)) { FnCall *fp = RvalFnCallValue(returnval); returnval = FnCallEvaluate(ctx, policy, fp, pp).rval; FnCallDestroy(fp); } break; default: assert(returnval.item == NULL); /* else we're leaking it */ returnval.item = NULL; returnval.type = RVAL_TYPE_NOPROMISEE; break; } return returnval; } /*********************************************************************/ static void CopyLocalizedReferencesToBundleScope(EvalContext *ctx, const Bundle *bundle, const Rlist *ref_names) { for (const Rlist *rp = ref_names; rp != NULL; rp = rp->next) { const char *mangled = RlistScalarValue(rp); char *demangled = xstrdup(mangled); DeMangleVarRefString(demangled, strlen(demangled)); if (strchr(RlistScalarValue(rp), CF_MAPPEDLIST)) { VarRef *demangled_ref = VarRefParseFromBundle(demangled, bundle); DataType value_type; const void *value = EvalContextVariableGet(ctx, demangled_ref, &value_type); if (!value) { ProgrammingError("Couldn't find extracted variable '%s'", mangled); } VarRef *mangled_ref = VarRefParseFromBundle(mangled, bundle); switch (DataTypeToRvalType(value_type)) { case RVAL_TYPE_LIST: { Rlist *list = RlistCopy(value); RlistFlatten(ctx, &list); EvalContextVariablePut(ctx, mangled_ref, list, value_type, "source=agent"); RlistDestroy(list); } break; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_SCALAR: EvalContextVariablePut(ctx, mangled_ref, value, value_type, "source=agent"); break; case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: ProgrammingError("Illegal rval type in switch %d", DataTypeToRvalType(value_type)); } VarRefDestroy(mangled_ref); VarRefDestroy(demangled_ref); } free(demangled); } } void BundleResolve(EvalContext *ctx, const Bundle *bundle) { Log(LOG_LEVEL_DEBUG, "Resolving variables in bundle '%s' '%s'", bundle->type, bundle->name); if (strcmp(bundle->type, "common") == 0) { for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *pt = SeqAt(bundle->promise_types, j); if (strcmp(pt->name, "classes") == 0) { EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); ExpandPromise(ctx, pp, VerifyClassPromise, NULL); } EvalContextStackPopFrame(ctx); } } } for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *pt = SeqAt(bundle->promise_types, j); if (strcmp(pt->name, "vars") == 0) { EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); ExpandPromise(ctx, pp, (PromiseActuator*)VerifyVarPromise, NULL); } EvalContextStackPopFrame(ctx); } } } ProtocolVersion ProtocolVersionParse(const char *s) { if (s == NULL || strcmp(s, "0") == 0 || strcmp(s, "undefined") == 0) { return CF_PROTOCOL_UNDEFINED; } if (strcmp(s, "1") == 0 || strcmp(s, "classic") == 0) { return CF_PROTOCOL_CLASSIC; } else if (strcmp(s, "2") == 0) { return CF_PROTOCOL_TLS; } else if (strcmp(s, "latest") == 0) { return CF_PROTOCOL_LATEST; } else { return CF_PROTOCOL_UNDEFINED; } } static void ResolveControlBody(EvalContext *ctx, GenericAgentConfig *config, const Body *control_body) { const ConstraintSyntax *body_syntax = NULL; Rval returnval; assert(strcmp(control_body->name, "control") == 0); for (int i = 0; CONTROL_BODIES[i].constraints != NULL; i++) { body_syntax = CONTROL_BODIES[i].constraints; if (strcmp(control_body->type, CONTROL_BODIES[i].body_type) == 0) { break; } } if (body_syntax == NULL) { FatalError(ctx, "Unknown agent"); } char scope[CF_BUFSIZE]; snprintf(scope, CF_BUFSIZE, "%s_%s", control_body->name, control_body->type); Log(LOG_LEVEL_DEBUG, "Initiate control variable convergence for scope '%s'", scope); EvalContextStackPushBodyFrame(ctx, NULL, control_body, NULL); for (size_t i = 0; i < SeqLength(control_body->conlist); i++) { Constraint *cp = SeqAt(control_body->conlist, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_BUNDLESEQUENCE].lval) == 0) { returnval = ExpandPrivateRval(ctx, NULL, scope, cp->rval.item, cp->rval.type); } else { returnval = EvaluateFinalRval(ctx, control_body->parent_policy, NULL, scope, cp->rval, true, NULL); } VarRef *ref = VarRefParseFromScope(cp->lval, scope); EvalContextVariableRemove(ctx, ref); if (!EvalContextVariablePut(ctx, ref, returnval.item, ConstraintSyntaxGetDataType(body_syntax, cp->lval), "source=promise")) { Log(LOG_LEVEL_ERR, "Rule from %s at/before line %zu", control_body->source_path, cp->offset.line); } VarRefDestroy(ref); if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_OUTPUT_PREFIX].lval) == 0) { strlcpy(VPREFIX, returnval.item, CF_MAXVARSIZE); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_DOMAIN].lval) == 0) { strcpy(VDOMAIN, cp->rval.item); Log(LOG_LEVEL_VERBOSE, "SET domain = %s", VDOMAIN); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "domain"); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost"); snprintf(VFQNAME, CF_MAXVARSIZE, "%s.%s", VUQNAME, VDOMAIN); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost", VFQNAME, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=Host name"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "domain", VDOMAIN, CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, VDOMAIN, "source=agent"); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_INPUTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_inputs %s", RvalScalarValue(cp->rval)); config->ignore_missing_inputs = BooleanFromString(cp->rval.item); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_IGNORE_MISSING_BUNDLES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET ignore_missing_bundles %s", RvalScalarValue(cp->rval)); config->ignore_missing_bundles = BooleanFromString(cp->rval.item); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_CACHE_SYSTEM_FUNCTIONS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET cache_system_functions %s", RvalScalarValue(cp->rval)); bool cache_system_functions = BooleanFromString(RvalScalarValue(cp->rval)); EvalContextSetEvalOption(ctx, EVAL_OPTION_CACHE_SYSTEM_FUNCTIONS, cache_system_functions); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_PROTOCOL_VERSION].lval) == 0) { config->protocol_version = ProtocolVersionParse(RvalScalarValue(cp->rval)); Log(LOG_LEVEL_VERBOSE, "SET common protocol_version: %s", PROTOCOL_VERSION_STRING[config->protocol_version]); } if (strcmp(cp->lval, CFG_CONTROLBODY[COMMON_CONTROL_GOALPATTERNS].lval) == 0) { /* Ignored */ continue; } RvalDestroy(returnval); } EvalContextStackPopFrame(ctx); } void PolicyResolve(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) == 0) { EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); BundleResolve(ctx, bundle); EvalContextStackPopFrame(ctx); } } for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bundle = SeqAt(policy->bundles, i); if (strcmp("common", bundle->type) != 0) { EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); BundleResolve(ctx, bundle); EvalContextStackPopFrame(ctx); } } for (size_t i = 0; i < SeqLength(policy->bodies); i++) { Body *bdp = SeqAt(policy->bodies, i); if (strcmp(bdp->name, "control") == 0) { ResolveControlBody(ctx, config, bdp); } } } bool IsExpandable(const char *str) { char left = 'x', right = 'x'; int dollar = false; int bracks = 0, vars = 0; for (const char *sp = str; *sp != '\0'; sp++) /* check for varitems */ { switch (*sp) { case '$': if (*(sp + 1) == '{' || *(sp + 1) == '(') { dollar = true; } break; case '(': case '{': if (dollar) { left = *sp; bracks++; } break; case ')': case '}': if (dollar) { bracks--; right = *sp; } break; } if (left == '(' && right == ')' && dollar && (bracks == 0)) { vars++; dollar = false; } if (left == '{' && right == '}' && dollar && (bracks == 0)) { vars++; dollar = false; } } if (bracks != 0) { Log(LOG_LEVEL_DEBUG, "If this is an expandable variable string then it contained syntax errors"); return false; } if (vars > 0) { Log(LOG_LEVEL_DEBUG, "Expanding variable '%s': found %d variables", str, vars); } return (vars > 0); } /*********************************************************************/ bool IsNakedVar(const char *str, char vtype) { int count = 0; if (str == NULL || strlen(str) == 0) { return false; } char last = *(str + strlen(str) - 1); if (strlen(str) < 3) { return false; } if (*str != vtype) { return false; } switch (*(str + 1)) { case '(': if (last != ')') { return false; } break; case '{': if (last != '}') { return false; } break; default: return false; break; } for (const char *sp = str; *sp != '\0'; sp++) { switch (*sp) { case '(': case '{': case '[': count++; break; case ')': case '}': case ']': count--; /* The last character must be the end of the variable */ if (count == 0 && strlen(sp) > 1) { return false; } break; } } if (count != 0) { return false; } return true; } /*********************************************************************/ void GetNaked(char *s2, const char *s1) /* copy @(listname) -> listname */ { if (strlen(s1) < 4) { Log(LOG_LEVEL_ERR, "Naked variable expected, but '%s' is malformed", s1); strlcpy(s2, s1, CF_MAXVARSIZE); return; } memset(s2, 0, CF_MAXVARSIZE); strncpy(s2, s1 + 2, strlen(s1) - 3); } /*********************************************************************/ bool IsVarList(const char *var) { if ('@' != var[0]) { return false; } /* * Minimum size for a list is 4: * '@' + '(' + name + ')' */ if (strlen(var) < 4) { return false; } return true; } PromiseResult CommonEvalPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert(param == NULL); if (SHOWREPORTS) { ShowPromise(pp); } PromiseRecheckAllConstraints(ctx, pp); return PROMISE_RESULT_NOOP; } cfengine-3.6.2/libpromises/mod_knowledge.h0000664000175100017510000000217512243421446020344 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_KNOWLEDGE_H #define CFENGINE_MOD_KNOWLEDGE_H #include extern const PromiseTypeSyntax CF_KNOWLEDGE_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/verify_classes.c0000664000175100017510000002403012411001073020517 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include /* StringHash */ #include /* StringMatchFull */ static int EvalClassExpression(EvalContext *ctx, Constraint *cp, const Promise *pp); static bool ValidClassName(const char *str); PromiseResult VerifyClassPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert(param == NULL); Attributes a = GetClassContextAttributes(ctx, pp); if (!StringMatchFull("[a-zA-Z0-9_]+", pp->promiser)) { Log(LOG_LEVEL_VERBOSE, "Class identifier '%s' contains illegal characters - canonifying", pp->promiser); xsnprintf(pp->promiser, strlen(pp->promiser) + 1, "%s", CanonifyName(pp->promiser)); } if (a.context.nconstraints == 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "No constraints for class promise '%s'", pp->promiser); return PROMISE_RESULT_FAIL; } if (a.context.nconstraints > 1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Irreconcilable constraints in classes for '%s'", pp->promiser); return PROMISE_RESULT_FAIL; } if (EvalClassExpression(ctx, a.context.expression, pp)) { if (!ValidClassName(pp->promiser)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Attempted to name a class '%s', which is an illegal class identifier", pp->promiser); return PROMISE_RESULT_FAIL; } else { char *tags = NULL; { Buffer *tag_buffer = BufferNew(); BufferAppendString(tag_buffer, "source=promise"); for (const Rlist *rp = PromiseGetConstraintAsList(ctx, "meta", pp); rp; rp = rp->next) { BufferAppendChar(tag_buffer, ','); BufferAppendString(tag_buffer, RlistScalarValue(rp)); } tags = BufferClose(tag_buffer); } if (/* Persistent classes are always global: */ a.context.persistent > 0 || /* Namespace-scope is global: */ a.context.scope == CONTEXT_SCOPE_NAMESPACE || /* If there is no explicit scope, common bundles define global * classes, other bundles define local classes: */ (a.context.scope == CONTEXT_SCOPE_NONE && 0 == strcmp(PromiseGetBundle(pp)->type, "common"))) { Log(LOG_LEVEL_VERBOSE, "Adding global class '%s'", pp->promiser); EvalContextClassPutSoft(ctx, pp->promiser, CONTEXT_SCOPE_NAMESPACE, tags); } else { Log(LOG_LEVEL_VERBOSE, "Adding local bundle class '%s'", pp->promiser); EvalContextClassPutSoft(ctx, pp->promiser, CONTEXT_SCOPE_BUNDLE, tags); } if (a.context.persistent > 0) { Log(LOG_LEVEL_VERBOSE, "Adding persistent class '%s'. (%d minutes)", pp->promiser, a.context.persistent); EvalContextHeapPersistentSave(ctx, pp->promiser, a.context.persistent, CONTEXT_STATE_POLICY_RESET, tags); } free(tags); return PROMISE_RESULT_NOOP; } } return PROMISE_RESULT_NOOP; } static int EvalClassExpression(EvalContext *ctx, Constraint *cp, const Promise *pp) { assert(pp); int result_and = true; int result_or = false; int result_xor = 0; int result = 0, total = 0; char buffer[CF_MAXVARSIZE]; Rlist *rp; if (cp == NULL) // ProgrammingError ? We'll crash RSN anyway ... { Log(LOG_LEVEL_ERR, "EvalClassExpression internal diagnostic discovered an ill-formed condition"); } if (!IsDefinedClass(ctx, pp->classes)) { return false; } if (IsDefinedClass(ctx, pp->promiser)) { if (PromiseGetConstraintAsInt(ctx, "persistence", pp) == 0) { Log(LOG_LEVEL_VERBOSE, " ?> Cancelling cached persistent class %s", pp->promiser); EvalContextHeapPersistentRemove(pp->promiser); } return false; } switch (cp->rval.type) { Rval rval; FnCall *fp; case RVAL_TYPE_FNCALL: fp = RvalFnCallValue(cp->rval); /* Special expansion of functions for control, best effort only: */ FnCallResult res = FnCallEvaluate(ctx, PromiseGetPolicy(pp), fp, pp); FnCallDestroy(fp); cp->rval = res.rval; break; case RVAL_TYPE_LIST: for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { rval = EvaluateFinalRval(ctx, PromiseGetPolicy(pp), NULL, "this", rp->val, true, pp); RvalDestroy(rp->val); rp->val = rval; } break; default: rval = ExpandPrivateRval(ctx, NULL, "this", cp->rval.item, cp->rval.type); RvalDestroy(cp->rval); cp->rval = rval; break; } if (strcmp(cp->lval, "expression") == 0) { return (cp->rval.type == RVAL_TYPE_SCALAR && IsDefinedClass(ctx, RvalScalarValue(cp->rval))); } if (strcmp(cp->lval, "not") == 0) { return (cp->rval.type == RVAL_TYPE_SCALAR && !IsDefinedClass(ctx, RvalScalarValue(cp->rval))); } // Class selection if (strcmp(cp->lval, "select_class") == 0) { char splay[CF_MAXVARSIZE]; int i, n; double hash; total = 0; for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { total++; } if (total == 0) { Log(LOG_LEVEL_ERR, "No classes to select on RHS"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } snprintf(splay, CF_MAXVARSIZE, "%s+%s+%ju", VFQNAME, VIPADDRESS, (uintmax_t)getuid()); hash = (double) StringHash(splay, 0, CF_HASHTABLESIZE); n = (int) (total * hash / (double) CF_HASHTABLESIZE); for (rp = (Rlist *) cp->rval.item, i = 0; rp != NULL; rp = rp->next, i++) { if (i == n) { EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise"); return true; } } } /* If we get here, anything remaining on the RHS must be a clist */ if (cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_ERR, "RHS of promise body attribute '%s' is not a list", cp->lval); PromiseRef(LOG_LEVEL_ERR, pp); return true; } // Class distributions if (strcmp(cp->lval, "dist") == 0) { for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { result = IntFromString(RlistScalarValue(rp)); if (result < 0) { Log(LOG_LEVEL_ERR, "Non-positive integer in class distribution"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } total += result; } if (total == 0) { Log(LOG_LEVEL_ERR, "An empty distribution was specified on RHS"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } double fluct = drand48(); double cum = 0.0; for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { double prob = ((double) IntFromString(RlistScalarValue(rp))) / ((double) total); cum += prob; if (fluct < cum) { break; } } snprintf(buffer, CF_MAXVARSIZE - 1, "%s_%s", pp->promiser, RlistScalarValue(rp)); if (strcmp(PromiseGetBundle(pp)->type, "common") == 0) { EvalContextClassPutSoft(ctx, buffer, CONTEXT_SCOPE_NAMESPACE, "source=promise"); } else { EvalContextClassPutSoft(ctx, buffer, CONTEXT_SCOPE_BUNDLE, "source=promise"); } return true; } /* and/or/xor expressions */ for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { if (rp->val.type != RVAL_TYPE_SCALAR) { return false; } result = IsDefinedClass(ctx, RlistScalarValue(rp)); result_and = result_and && result; result_or = result_or || result; result_xor ^= result; } // Class combinations if (strcmp(cp->lval, "or") == 0) { return result_or; } if (strcmp(cp->lval, "xor") == 0) { return (result_xor == 1) ? true : false; } if (strcmp(cp->lval, "and") == 0) { return result_and; } return false; } static bool ValidClassName(const char *str) { ParseResult res = ParseExpression(str, 0, strlen(str)); if (res.result) { FreeExpression(res.result); } return res.result && res.position == strlen(str); } cfengine-3.6.2/libpromises/files_hashes.c0000664000175100017510000001401512400110676020145 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* BN_* */ #include /* EVP_* */ #include #include #include #include #include #include #include /* StringBytesToHex */ #include /* UnexpectedError */ void HashFile(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type) { FILE *file; EVP_MD_CTX context; int len, md_len; unsigned char buffer[1024]; const EVP_MD *md = NULL; if ((file = safe_fopen(filename, "rb")) == NULL) { Log(LOG_LEVEL_INFO, "Cannot open file for hashing '%s'. (fopen: %s)", filename, GetErrorStr()); } else { md = EVP_get_digestbyname(HashNameFromId(type)); EVP_DigestInit(&context, md); while ((len = fread(buffer, 1, 1024, file))) { EVP_DigestUpdate(&context, buffer, len); } EVP_DigestFinal(&context, digest, &md_len); /* Digest length stored in md_len */ fclose(file); } } /*******************************************************************/ void HashString(const char *buffer, int len, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type) { EVP_MD_CTX context; const EVP_MD *md = NULL; int md_len; switch (type) { case HASH_METHOD_CRYPT: Log(LOG_LEVEL_ERR, "The crypt support is not presently implemented, please use another algorithm instead"); memset(digest, 0, EVP_MAX_MD_SIZE + 1); break; default: md = EVP_get_digestbyname(HashNameFromId(type)); if (md == NULL) { Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", HashNameFromId(type)); } EVP_DigestInit(&context, md); EVP_DigestUpdate(&context, (unsigned char *) buffer, (size_t) len); EVP_DigestFinal(&context, digest, &md_len); break; } } /*******************************************************************/ void HashPubKey(RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type) { EVP_MD_CTX context; const EVP_MD *md = NULL; int md_len, i, buf_len, actlen; unsigned char *buffer; if (key->n) { buf_len = (size_t) BN_num_bytes(key->n); } else { buf_len = 0; } if (key->e) { if (buf_len < (i = (size_t) BN_num_bytes(key->e))) { buf_len = i; } } buffer = xmalloc(buf_len + 10); switch (type) { case HASH_METHOD_CRYPT: Log(LOG_LEVEL_ERR, "The crypt support is not presently implemented, please use sha256 instead"); break; default: md = EVP_get_digestbyname(HashNameFromId(type)); if (md == NULL) { Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", HashNameFromId(type)); } EVP_DigestInit(&context, md); actlen = BN_bn2bin(key->n, buffer); EVP_DigestUpdate(&context, buffer, actlen); actlen = BN_bn2bin(key->e, buffer); EVP_DigestUpdate(&context, buffer, actlen); EVP_DigestFinal(&context, digest, &md_len); break; } free(buffer); } /*******************************************************************/ int HashesMatch(const unsigned char digest1[EVP_MAX_MD_SIZE + 1], const unsigned char digest2[EVP_MAX_MD_SIZE + 1], HashMethod type) { int i, size = EVP_MAX_MD_SIZE; size = HashSizeFromId(type); for (i = 0; i < size; i++) { if (digest1[i] != digest2[i]) { return false; } } return true; } /* TODO rewrite this ugliness, currently it's not safe, it truncates! */ /** * @WARNING #dst must have enough space to hold the result! */ char *HashPrintSafe(char *dst, size_t dst_size, const unsigned char *digest, HashMethod type, bool use_prefix) { const char *prefix; if (use_prefix) { switch (type) { case HASH_METHOD_MD5: prefix = "MD5="; break; default: prefix = "SHA="; break; } } else { prefix = ""; } size_t dst_len = MIN(dst_size - 1, strlen(prefix)); memcpy(dst, prefix, dst_len); size_t digest_len = HashSizeFromId(type); assert(dst_size >= strlen(prefix) + digest_len*2 + 1); #ifndef NDEBUG // Avoids warning. size_t ret = #endif StringBytesToHex(&dst[dst_len], dst_size - dst_len, digest, digest_len); assert(ret == 2 * digest_len); #if 0 /* TODO return proper exit status and check it in the callers */ if (ret < 2 * digest_len) { return NULL; } #endif return dst; } char *SkipHashType(char *hash) { char *str = hash; if(BEGINSWITH(hash, "MD5=") || BEGINSWITH(hash, "SHA=")) { str = hash + 4; } return str; } cfengine-3.6.2/libpromises/process_aix.c0000644000175100017510000000416412352022221020023 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include /* * AIX 5.3 is missing this declaration */ #ifndef HAVE_GETPROCS64 int getprocs64(struct procentry64 *, int, struct fdsinfo64 *, int, pid_t *, int); #endif static bool FillProcEntry(struct procentry64* pe, pid_t pid) { pid_t nextpid = pid; int ret = getprocs64(pe, sizeof(pe), NULL, 0, &nextpid, 1); /* * getprocs64 may * - return -1 => we can't access this process (EPERM) * - return 0 => end of process table, no such process * - return another process' info => no such process */ return ret == 1 && pe->pi_pid == pid; } time_t GetProcessStartTime(pid_t pid) { struct procentry64 pe; if (FillProcEntry(&pe, pid)) { return pe.pi_start; } else { return PROCESS_START_TIME_UNKNOWN; } } ProcessState GetProcessState(pid_t pid) { struct procentry64 pe; if (FillProcEntry(&pe, pid)) { return pe.pi_state == SSTOP ? PROCESS_STATE_STOPPED : PROCESS_STATE_RUNNING; } else { return PROCESS_STATE_DOES_NOT_EXIST; } } cfengine-3.6.2/libpromises/mod_common.c0000664000175100017510000011721612411001073017636 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* This is a root node in the syntax tree */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CF_LOGRANGE "stdout|udp_syslog|(\042?[a-zA-Z]:\\\\.*)|(/.*)" #define CF_FACILITY "LOG_USER,LOG_DAEMON,LOG_LOCAL0,LOG_LOCAL1,LOG_LOCAL2,LOG_LOCAL3,LOG_LOCAL4,LOG_LOCAL5,LOG_LOCAL6,LOG_LOCAL7" static const char *const POLICY_ERROR_VARS_CONSTRAINT_DUPLICATE_TYPE = "Variable contains existing data type contstraint %s, tried to " "redefine with %s"; static const char *const POLICY_ERROR_VARS_PROMISER_NUMERICAL = "Variable promises cannot have a purely numerical promiser (name)"; static const char *const POLICY_ERROR_VARS_PROMISER_RESERVED = "Variable promise is using a reserved name"; static const char *const POLICY_ERROR_CLASSES_PROMISER_NUMERICAL = "Classes promises cannot have a purely numerical promiser (name)"; static bool ActionCheck(const Body *body, Seq *errors) { bool success = true; if (BodyHasConstraint(body, "log_kept") || BodyHasConstraint(body, "log_repaired") || BodyHasConstraint(body, "log_failed")) { if (!BodyHasConstraint(body, "log_string")) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An action body with log_kept, log_repaired or log_failed is required to have a log_string attribute")); success = false; } } return success; } static const ConstraintSyntax action_constraints[] = { ConstraintSyntaxNewOption("action_policy", "fix,warn,nop", "Whether to repair or report about non-kept promises", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("ifelapsed", CF_VALRANGE, "Number of minutes before next allowed assessment of promise. Default value: control body value", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("expireafter", CF_VALRANGE, "Number of minutes before a repair action is interrupted and retried. Default value: control body value", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("log_string", "", "A message to be written to the log when a promise verification leads to a repair", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("log_level", "inform,verbose,error,log", "The reporting level sent to syslog", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("log_kept", CF_LOGRANGE,"This should be filename of a file to which log_string will be saved, if undefined it goes to the system logger", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("log_priority", "emergency,alert,critical,error,warning,notice,info,debug","The priority level of the log message, as interpreted by a syslog server", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("log_repaired", CF_LOGRANGE,"This should be filename of a file to which log_string will be saved, if undefined it goes to the system logger", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("log_failed", CF_LOGRANGE,"This should be filename of a file to which log_string will be saved, if undefined it goes to the system logger", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewReal("value_kept", CF_REALRANGE, "A real number value attributed to keeping this promise", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewReal("value_repaired", CF_REALRANGE, "A real number value attributed to reparing this promise", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewReal("value_notkept", CF_REALRANGE, "A real number value (possibly negative) attributed to not keeping this promise", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewBool("audit", "true/false switch for detailed audit records of this promise. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("background", "true/false switch for parallelizing the promise repair. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("report_level", "inform,verbose,error,log", "The reporting level for standard output for this promise. Default value: none", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("measurement_class", "", "If set performance will be measured and recorded under this identifier", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax action_body = BodySyntaxNew("action", action_constraints, ActionCheck, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax classes_constraints[] = { ConstraintSyntaxNewOption("scope", "namespace,bundle", "Scope of the contexts set by this body", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("promise_repaired", CF_IDRANGE, "A list of classes to be defined globally", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("repair_failed", CF_IDRANGE, "A list of classes to be defined globally", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("repair_denied", CF_IDRANGE, "A list of classes to be defined globally", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("repair_timeout", CF_IDRANGE, "A list of classes to be defined globally", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("promise_kept", CF_IDRANGE, "A list of classes to be defined globally", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("cancel_kept", CF_IDRANGE, "A list of classes to be cancelled if the promise is kept", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("cancel_repaired", CF_IDRANGE, "A list of classes to be cancelled if the promise is repaired", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("cancel_notkept", CF_IDRANGE, "A list of classes to be cancelled if the promise is not kept for any reason", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("kept_returncodes", CF_INTLISTRANGE, "A list of return codes indicating a kept command-related promise", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("repaired_returncodes", CF_INTLISTRANGE,"A list of return codes indicating a repaired command-related promise", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("failed_returncodes", CF_INTLISTRANGE, "A list of return codes indicating a failed command-related promise", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("persist_time", CF_VALRANGE, "A number of minutes the specified classes should remain active", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("timer_policy", "absolute,reset", "Whether a persistent class restarts its counter when rediscovered. Default value: reset", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax classes_body = BodySyntaxNew("classes", classes_constraints, NULL, SYNTAX_STATUS_NORMAL); const ConstraintSyntax CF_VARBODY[] = { ConstraintSyntaxNewString("string", "", "A scalar string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("int", CF_INTRANGE, "A scalar integer", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewReal("real", CF_REALRANGE, "A scalar real number", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("slist", "", "A list of scalar strings", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewIntList("ilist", "A list of integers", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewRealList("rlist", "A list of real numbers", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContainer("data", "A data container", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("policy", "free,overridable,constant,ifdefined", "The policy for (dis)allowing (re)definition of variables", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static bool CheckIdentifierNotPurelyNumerical(const char *identifier) { if (*identifier == '\0') { return true; } for (const char *check = identifier; *check != '\0' && check - identifier < CF_BUFSIZE; check++) { if (!isdigit(*check)) { return true; } } return false; } static bool VarsParseTreeCheck(const Promise *pp, Seq *errors) { bool success = true; if (!CheckIdentifierNotPurelyNumerical(pp->promiser)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp, POLICY_ERROR_VARS_PROMISER_NUMERICAL)); success = false; } if (!CheckParseVariableName(pp->promiser)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp, POLICY_ERROR_VARS_PROMISER_RESERVED)); success = false; } // ensure variables are declared with only one type. { char *data_type = NULL; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (DataTypeFromString(cp->lval) != CF_DATA_TYPE_NONE) { if (data_type != NULL) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp, POLICY_ERROR_VARS_CONSTRAINT_DUPLICATE_TYPE, data_type, cp->lval)); success = false; } data_type = cp->lval; } } } return success; } const ConstraintSyntax CF_METABODY[] = { ConstraintSyntaxNewString("string", "", "A scalar string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("slist", "", "A list of scalar strings", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContainer("data", "A data container", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CF_DEFAULTSBODY[] = { ConstraintSyntaxNewString("if_match_regex", "", "If this regular expression matches the current value of the variable, replace it with default", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("string", "", "A scalar string", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("slist", "", "A list of scalar strings", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CF_CLASSBODY[] = { ConstraintSyntaxNewOption("scope", "namespace,bundle", "Scope of the class set by this promise", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContextList("and", "Combine class sources with AND", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewRealList("dist", "Generate a probabilistic class distribution (from strategies in cfengine 2)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContext("expression", "Evaluate string expression of classes in normal form", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContextList("or", "Combine class sources with inclusive OR", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("persistence", CF_VALRANGE, "Make the class persistent (cached) to avoid reevaluation, time in minutes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContext("not", "Evaluate the negation of string expression in normal form", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContextList("select_class", "Select one of the named list of classes to define based on host identity. Default value: random_selection", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewContextList("xor", "Combine class sources with XOR", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static bool ClassesParseTreeCheck(const Promise *pp, Seq *errors) { bool success = true; if (!CheckIdentifierNotPurelyNumerical(pp->promiser)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_PROMISE, pp, POLICY_ERROR_CLASSES_PROMISER_NUMERICAL)); success = false; } return success; } const ConstraintSyntax CFG_CONTROLBODY[COMMON_CONTROL_MAX + 1] = { ConstraintSyntaxNewStringList("bundlesequence", ".*", "List of promise bundles to verify in order", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("goal_patterns", "", "A list of regular expressions that match promisees/topics considered to be organizational goals", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("ignore_missing_bundles", "If any bundles in the bundlesequence do not exist, ignore and continue. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("ignore_missing_inputs", "If any input files do not exist, ignore and continue. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("inputs", ".*", "List of additional filenames to parse for promises", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("version", "", "Scalar version string for this configuration", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("lastseenexpireafter", CF_VALRANGE, "Number of minutes after which last-seen entries are purged. Default value: one week", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("output_prefix", "", "The string prefix for standard output", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("domain", ".*", "Specify the domain name for this host", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("require_comments", "Warn about promises that do not have comment documentation. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("host_licenses_paid", CF_VALRANGE, "This promise is deprecated since CFEngine version 3.1 and is ignored. Default value: 25", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewContextList("site_classes", "A list of classes that will represent geographical site locations for hosts. These should be defined elsewhere in the configuration in a classes promise.", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("syslog_host", CF_IPRANGE, "The name or address of a host to which syslog messages should be sent directly by UDP. Default value: 514", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("syslog_port", CF_VALRANGE, "The port number of a UDP syslog service", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("fips_mode", "Activate full FIPS mode restrictions. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("cache_system_functions", "Cache the result of system functions. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("protocol_version", "0,undefined,1,classic,2,latest", "CFEngine protocol version to use when connecting to the server. Default: classic", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFA_CONTROLBODY[] = { ConstraintSyntaxNewStringList("abortclasses", ".*", "A list of classes which if defined lead to termination of cf-agent", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("abortbundleclasses", ".*", "A list of classes which if defined lead to termination of current bundle", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("addclasses", ".*", "A list of classes to be defined always in the current context", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("agentaccess", ".*", "A list of user names allowed to execute cf-agent", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("agentfacility", CF_FACILITY, "The syslog facility for cf-agent. Default value: LOG_USER", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("allclassesreport", "Generate allclasses.txt report", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("alwaysvalidate", "true/false flag to determine whether configurations will always be checked before executing, or only after updates", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("auditing", "This option is deprecated, does nothing and is kept for backward compatibility. Default value: false", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("binarypaddingchar", "", "Character used to pad unequal replacements in binary editing. Default value: space (ASC=32)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("bindtointerface", ".*", "Use this interface for outgoing connections", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("hashupdates", "true/false whether stored hashes are updated when change is detected in source. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("childlibpath", ".*", "LD_LIBRARY_PATH for child processes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("checksum_alert_time", "0,60", "The persistence time for the checksum_alert class. Default value: 10 mins", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("defaultcopytype", "mtime,atime,ctime,digest,hash,binary", "ctime or mtime differ", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("dryrun", "All talk and no action mode. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("editbinaryfilesize", CF_VALRANGE, "Integer limit on maximum binary file size to be edited. Default value: 100000", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("editfilesize", CF_VALRANGE, "Integer limit on maximum text file size to be edited. Default value: 100000", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("environment", "[A-Za-z0-9_]+=.*", "List of environment variables to be inherited by children", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("exclamation", "true/false print exclamation marks during security warnings. Default value: true", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewInt("expireafter", CF_VALRANGE, "Global default for time before on-going promise repairs are interrupted. Default value: 1 min", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("files_single_copy", "", "List of filenames to be watched for multiple-source conflicts", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("files_auto_define", "", "List of filenames to define classes if copied", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("hostnamekeys", "true/false label ppkeys by hostname not IP address. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("ifelapsed", CF_VALRANGE, "Global default for time that must elapse before promise will be rechecked. Default value: 1", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("inform", "true/false set inform level default. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("intermittency", "This option is deprecated, does nothing and is kept for backward compatibility. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("max_children", CF_VALRANGE, "Maximum number of background tasks that should be allowed concurrently. Default value: 1 concurrent agent promise", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("maxconnections", CF_VALRANGE, "Maximum number of outgoing connections to cf-serverd. Default value: 30 remote queries", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("mountfilesystems", "true/false mount any filesystems promised. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("nonalphanumfiles", "true/false warn about filenames with no alphanumeric content. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("repchar", ".", "The character used to canonize pathnames in the file repository. Default value: _", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("refresh_processes", CF_IDRANGE, "Reload the process table before verifying the bundles named in this list (lazy evaluation)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("default_repository", CF_ABSPATHRANGE, "Path to the default file repository. Default value: in situ", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("secureinput", "true/false check whether input files are writable by unauthorized users. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("sensiblecount", CF_VALRANGE, "Minimum number of files a mounted filesystem is expected to have. Default value: 2 files", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("sensiblesize", CF_VALRANGE, "Minimum number of bytes a mounted filesystem is expected to have. Default value: 1000 bytes", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("skipidentify", "Do not send IP/name during server connection because address resolution is broken. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("suspiciousnames", "", "List of names to warn about if found during any file search", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("syslog", "true/false switches on output to syslog at the inform level. Default value: false", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewBool("track_value", "true/false switches on tracking of promise valuation. Default value: false", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("timezone", "", "List of allowed timezones this machine must comply with", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("default_timeout", CF_VALRANGE, "Maximum time a network connection should attempt to connect. Default value: 10 seconds", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("verbose", "true/false switches on verbose standard output. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFS_CONTROLBODY[SERVER_CONTROL_NONE + 1] = { ConstraintSyntaxNewStringList("allowallconnects", "","List of IPs or hostnames that may have more than one connection to the server port", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("allowconnects", "", "List of IPs or hostnames that may connect to the server port", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("allowusers", "", "List of usernames who may execute requests from this server", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("auditing", "true/false activate auditing of server connections. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("bindtointerface", "", "IP of the interface to which the server should bind on multi-homed hosts", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("cfruncommand", CF_PATHRANGE, "Path to the cf-agent command or cf-execd wrapper for remote execution", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("call_collect_interval", CF_VALRANGE, "The interval in minutes in between collect calls to the policy hub offering a tunnel for report collection (Enterprise)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("collect_window", CF_VALRANGE, "A time in seconds that a collect-call tunnel remains open to a hub to attempt a report transfer before it is closed (Enterprise)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("denybadclocks", "true/false accept connections from hosts with clocks that are out of sync. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("denyconnects", "", "List of IPs or hostnames that may NOT connect to the server port", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("dynamicaddresses", "", "List of IPs or hostnames for which the IP/name binding is expected to change", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("hostnamekeys", "true/false store keys using hostname lookup instead of IP addresses. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("keycacheTTL", CF_VALRANGE, "Maximum number of hours to hold public keys in the cache. Default value: 24", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewBool("logallconnections", "true/false causes the server to log all new connections to syslog. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("logencryptedtransfers", "true/false log all successful transfers required to be encrypted. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("maxconnections", CF_VALRANGE, "Maximum number of connections that will be accepted by cf-serverd. Default value: 30 remote queries", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("port", "1,65535", "Default port for cfengine server. Default value: 5308", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("serverfacility", CF_FACILITY, "Menu option for syslog facility level. Default value: LOG_USER", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("skipverify", "", "This option is deprecated, does nothing and is kept for backward compatibility.", SYNTAX_STATUS_DEPRECATED), ConstraintSyntaxNewStringList("trustkeysfrom", "", "List of IPs from whom we accept public keys on trust", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("listen", "true/false enable server daemon to listen on defined port. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("allowciphers", "", "List of ciphers the server accepts. For Syntax help see man page for \"openssl ciphers\". Default is \"AES256-GCM-SHA384:AES256-SHA\"", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("allowlegacyconnects", "", "List of IPs from whom we accept legacy protocol connections", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFM_CONTROLBODY[] = { ConstraintSyntaxNewReal("forgetrate", "0,1", "Decimal fraction [0,1] weighting of new values over old in 2d-average computation. Default value: 0.6", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("monitorfacility", CF_FACILITY, "Menu option for syslog facility. Default value: LOG_USER", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("histograms", "Ignored, kept for backward compatibility. Default value: true", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("tcpdump", "true/false use tcpdump if found. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("tcpdumpcommand", CF_ABSPATHRANGE, "Path to the tcpdump command on this system", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFR_CONTROLBODY[] = { ConstraintSyntaxNewStringList("hosts", "", "List of host or IP addresses to attempt connection with", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("port", "1,65535", "Default port for cfengine server. Default value: 5308", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("force_ipv4", "true/false force use of ipv4 in connection. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("trustkey", "true/false automatically accept all keys on trust from servers. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("encrypt", "true/false encrypt connections with servers. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("background_children", "true/false parallelize connections to servers. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("max_children", CF_VALRANGE, "Maximum number of simultaneous connections to attempt. Default value: 50 runagents", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("output_to_file", "true/false whether to send collected output to file(s). Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("output_directory", CF_ABSPATHRANGE, "Directory where the output is stored", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("timeout", "1,9999", "Connection timeout, sec", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFEX_CONTROLBODY[] = /* enum cfexcontrol */ { ConstraintSyntaxNewInt("splaytime", CF_VALRANGE, "Time in minutes to splay this host based on its name hash. Default value: 0", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("mailfrom", ".*@.*", "Email-address cfengine mail appears to come from", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("mailto", ".*@.*", "Email-address cfengine mail is sent to", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("mailsubject", "", "Define a custom mailsubject for the email message", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("smtpserver", ".*", "Name or IP of a willing smtp server for sending email", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("mailmaxlines", "0,1000", "Maximum number of lines of output to send by email. Default value: 30", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("schedule", "", "The class schedule used by cf-execd for activating cf-agent", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("executorfacility", CF_FACILITY, "Menu option for syslog facility level. Default value: LOG_USER", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("exec_command", CF_ABSPATHRANGE,"The full path and command to the executable run by default (overriding builtin)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("agent_expireafter", "0,10080", "Maximum agent runtime (in minutes). Default value: 10080", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFH_CONTROLBODY[] = /* enum cfh_control */ { ConstraintSyntaxNewString("export_zenoss", CF_PATHRANGE, "Generate report for Zenoss integration", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("exclude_hosts", "", "A list of IP addresses of hosts to exclude from report collection", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("hub_schedule", "", "The class schedule used by cf-hub for report collation", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("port", "1,65535", "Default port for contacting hub nodes. Default value: 5308", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax file_control_constraints[] = /* enum cfh_control */ { ConstraintSyntaxNewString("namespace", CF_IDRANGE, "Switch to a private namespace to protect current file from duplicate definitions", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("inputs", ".*", "List of additional filenames to parse for promises", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFRE_CONTROLBODY[] = /* enum cfrecontrol */ { ConstraintSyntaxNewString("aggregation_point", CF_ABSPATHRANGE, "The root directory of the data cache for CMDB aggregation", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("auto_scaling", CF_BOOL, "true/false whether to auto-scale graph output to optimize use of space. Default value: true", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("build_directory", ".*", "The directory in which to generate output files", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("csv2xml", "", "A list of csv formatted files in the build directory to convert to simple xml", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("error_bars", CF_BOOL, "true/false whether to generate error bars on graph output", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("html_banner", "", "HTML code for a banner to be added to rendered in html after the header", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("html_embed", CF_BOOL, "If true, no header and footer tags will be added to html output", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("html_footer", "", "HTML code for a page footer to be added to rendered in html before the end body tag", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("query_engine", "", "Name of a dynamic web-page used to accept and drive queries in a browser", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOptionList("reports", "all,audit,performance,all_locks,active_locks,hashes,classes,last_seen,monitor_now,monitor_history,monitor_summary,compliance,setuid,file_changes,installed_software,software_patches,value,variables", "A list of reports that may be generated", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("report_output", "csv,html,text,xml", "Menu option for generated output format. Applies only to text reports, graph data remain in xydy format.", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("style_sheet", "", "Name of a style-sheet to be used in rendering html output (added to headers)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("time_stamps", CF_BOOL, "true/false whether to generate timestamps in the output directory name", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; const ConstraintSyntax CFK_CONTROLBODY[] = { ConstraintSyntaxNewString("build_directory", ".*", "The directory in which to generate output files", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("document_root", ".*", "The directory in which the web root resides", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("generate_manual", CF_BOOL, "true/false generate texinfo manual page skeleton for this version", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("graph_directory", CF_ABSPATHRANGE, "Path to directory where rendered .png files will be created", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("graph_output", CF_BOOL, "true/false generate png visualization of topic map if possible (requires lib)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("html_banner", "", "HTML code for a banner to be added to rendered in html after the header", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("html_footer", "", "HTML code for a page footer to be added to rendered in html before the end body tag", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("id_prefix", ".*", "The LTM identifier prefix used to label topic maps (used for disambiguation in merging)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("manual_source_directory", CF_ABSPATHRANGE, "Path to directory where raw text about manual topics is found (defaults to build_directory)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("query_engine", "", "Name of a dynamic web-page used to accept and drive queries in a browser", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("query_output", "html,text", "Menu option for generated output format", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("sql_type", "mysql,postgres", "Menu option for supported database type", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("sql_database", "", "Name of database used for the topic map", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("sql_owner", "", "User id of sql database user", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("sql_passwd", "", "Embedded password for accessing sql database", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("sql_server", "", "Name or IP of database server (or localhost)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("sql_connection_db", "", "The name of an existing database to connect to in order to create/manage other databases", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("style_sheet", "", "Name of a style-sheet to be used in rendering html output (added to headers)", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("view_projections", CF_BOOL, "Perform view-projection analytics in graph generation", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; /* This list is for checking free standing body lval => rval bindings */ const BodySyntax CONTROL_BODIES[] = { BodySyntaxNew(CF_COMMONC, CFG_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew(CF_AGENTC, CFA_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew(CF_SERVERC, CFS_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew(CF_MONITORC, CFM_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew(CF_RUNC, CFR_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew(CF_EXECC, CFEX_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew(CF_HUBC, CFH_CONTROLBODY, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew("file", file_control_constraints, NULL, SYNTAX_STATUS_NORMAL), BodySyntaxNew("reporter", CFRE_CONTROLBODY, NULL, SYNTAX_STATUS_REMOVED), BodySyntaxNew("knowledge", CFK_CONTROLBODY, NULL, SYNTAX_STATUS_REMOVED), // get others from modules e.g. "agent","files",CF_FILES_BODIES, BodySyntaxNewNull() }; /*********************************************************/ /* */ /* Constraint values/types */ /* */ /*********************************************************/ /* This is where we place lval => rval bindings that apply to more than one promise_type, e.g. generic processing behavioural details */ const ConstraintSyntax CF_COMMON_BODIES[] = { ConstraintSyntaxNewBody("action", &action_body, "Output behaviour", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("classes", &classes_body, "Signalling behaviour", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("comment", "", "A comment about this promise's real intention that follows through the program", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("depends_on", "","A list of promise handles that this promise builds on or depends on somehow (for knowledge management)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("handle", "", "A unique id-tag string for referring to this as a promisee elsewhere", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("ifvarclass", "", "Extended classes ANDed with context", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("meta", "", "User-data associated with policy, e.g. key=value strings", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; /* This is where we place promise promise_types that apply to more than one type of bundle, e.g. agent,server.. */ const PromiseTypeSyntax CF_COMMON_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("*", "classes", CF_CLASSBODY, &ClassesParseTreeCheck, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("*", "defaults", CF_DEFAULTSBODY, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("*", "meta", CF_METABODY, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("*", "reports", CF_REPORT_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("*", "vars", CF_VARBODY, &VarsParseTreeCheck, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("*", "*", CF_COMMON_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; /*********************************************************/ /* THIS IS WHERE TO ATTACH SYNTAX MODULES */ /*********************************************************/ /* Read in all parsable Bundle definitions */ /* REMEMBER TO REGISTER THESE IN cf3.extern.h */ const PromiseTypeSyntax *const CF_ALL_PROMISE_TYPES[] = { CF_COMMON_PROMISE_TYPES, /* Add modules after this, mod_report.c is here */ CF_EXEC_PROMISE_TYPES, /* mod_exec.c */ CF_DATABASES_PROMISE_TYPES, /* mod_databases.c */ CF_ENVIRONMENT_PROMISE_TYPES, /* mod_environ.c */ CF_FILES_PROMISE_TYPES, /* mod_files.c */ CF_METHOD_PROMISE_TYPES, /* mod_methods.c */ CF_OUTPUTS_PROMISE_TYPES, /* mod_outputs.c */ CF_PACKAGES_PROMISE_TYPES, /* mod_packages.c */ CF_PROCESS_PROMISE_TYPES, /* mod_process.c */ CF_SERVICES_PROMISE_TYPES, /* mod_services.c */ CF_STORAGE_PROMISE_TYPES, /* mod_storage.c */ CF_REMACCESS_PROMISE_TYPES, /* mod_access.c */ CF_MEASUREMENT_PROMISE_TYPES, /* mod_measurement.c */ CF_KNOWLEDGE_PROMISE_TYPES, /* mod_knowledge.c */ CF_USERS_PROMISE_TYPES, /* mod_users.c */ }; const int CF3_MODULES = (sizeof(CF_ALL_PROMISE_TYPES) / sizeof(CF_ALL_PROMISE_TYPES[0])); CommonControl CommonControlFromString(const char *lval) { int i = 0; for (const ConstraintSyntax *s = CFG_CONTROLBODY; s->lval; s++, i++) { if (strcmp(lval, s->lval) == 0) { return (CommonControl)i; } } return COMMON_CONTROL_MAX; } cfengine-3.6.2/libpromises/mod_users.c0000644000175100017510000000537212352022221017506 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax password_constraints[] = { ConstraintSyntaxNewOption("format", "plaintext,hash", "The format of the given password, either plaintext or hash", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("data", "", "Password", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax password_body = BodySyntaxNew("password", password_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax users_constraints[] = { ConstraintSyntaxNewOption("policy", "present,absent,locked", "The promised state of a given user", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewInt("uid", CF_INTRANGE, "User id", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("password", &password_body, "User password", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("description", "", "User comment", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("group_primary", "", "User primary group", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("groups_secondary", ".*", "User additional groups", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("home_dir", CF_ABSPATHRANGE, "User home directory", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBundle("home_bundle", "Specify the name of a bundle to run when creating a user", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("home_bundle_inherit", "If true this causes the home_bundle to inherit the private classes of its parent", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("shell", CF_ABSPATHRANGE, "User shell", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_USERS_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "users", users_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/class.c0000664000175100017510000001445412411001073016614 0ustar00a10038a1003800000000000000#include #include #include #include /* StringHash,StringConcatenate */ #include /* CompileRegex,StringMatchFullWithPrecompiledRegex */ #include struct ClassTable_ { RBTree *classes; }; struct ClassTableIterator_ { RBTreeIterator *iter; char *ns; bool is_hard; bool is_soft; }; static size_t ClassRefHash(const char *ns, const char *name) { unsigned h = 0; h = StringHash(ns ? ns : "default", h, INT_MAX); size_t len = strlen(name); for (size_t i = 0; i < len; i++) { h += (!isalnum(name[i]) || (name[i] == '.')) ? '_' : name[i]; h += (h << 10); h ^= (h >> 6); } h += (h << 3); h ^= (h >> 11); h += (h << 15); return (h & (INT_MAX - 1)); } void ClassInit(Class *cls, const char *ns, const char *name, bool is_soft, ContextScope scope) { if (ns) { cls->ns = xstrdup(ns); } else { cls->ns = NULL; } cls->name = xstrdup(name); CanonifyNameInPlace(cls->name); cls->is_soft = is_soft; cls->scope = scope; cls->tags = NULL; cls->hash = ClassRefHash(cls->ns, cls->name); } static void ClassDestroySoft(Class *cls) { if (cls) { free(cls->ns); free(cls->name); StringSetDestroy(cls->tags); } } void ClassDestroy(Class *cls) { if (cls) { ClassDestroySoft(cls); free(cls); } } ClassTable *ClassTableNew(void) { ClassTable *table = xmalloc(sizeof(ClassTable)); table->classes = RBTreeNew(NULL, NULL, NULL, NULL, NULL, (RBTreeValueDestroyFn *)ClassDestroy); return table; } void ClassTableDestroy(ClassTable *table) { if (table) { RBTreeDestroy(table->classes); free(table); } } bool ClassTablePut(ClassTable *table, const char *ns, const char *name, bool is_soft, ContextScope scope, const char *tags) { assert(name); assert(is_soft || (!ns || strcmp("default", ns) == 0)); // hard classes should have default namespace assert(is_soft || scope == CONTEXT_SCOPE_NAMESPACE); // hard classes cannot be local if (ns && strcmp("default", ns) == 0) { ns = NULL; } Class *cls = ClassTableGet(table, ns, name); if (cls) { ClassDestroySoft(cls); ClassInit(cls, ns, name, is_soft, scope); return true; } else { cls = xmalloc(sizeof(Class)); ClassInit(cls, ns, name, is_soft, scope); // NULL tags are OK (but you want to give good tags, don't you?) cls->tags = StringSetFromString(tags, ','); if (!is_soft && !StringSetContains(cls->tags, "hardclass")) { StringSetAdd(cls->tags, xstrdup("hardclass")); } return RBTreePut(table->classes, (void *)cls->hash, cls); } } Class *ClassTableGet(const ClassTable *table, const char *ns, const char *name) { size_t hash = ClassRefHash(ns, name); return RBTreeGet(table->classes, (void *)hash); } Class *ClassTableMatch(const ClassTable *table, const char *regex) { ClassTableIterator *it = ClassTableIteratorNew(table, NULL, true, true); Class *cls = NULL; pcre *pattern = CompileRegex(regex); if (pattern == NULL) { // TODO: perhaps pcre has can give more info on this error? Log(LOG_LEVEL_ERR, "Unable to pcre compile regex '%s'", regex); return false; } while ((cls = ClassTableIteratorNext(it))) { bool matched; if (cls->ns) { char *class_expr = ClassRefToString(cls->ns, cls->name); matched = StringMatchFullWithPrecompiledRegex(pattern, class_expr); free(class_expr); } else { matched = StringMatchFullWithPrecompiledRegex(pattern, cls->name); } if (matched) { break; } } pcre_free(pattern); ClassTableIteratorDestroy(it); return cls; } bool ClassTableRemove(ClassTable *table, const char *ns, const char *name) { size_t hash = ClassRefHash(ns, name); return RBTreeRemove(table->classes, (void *)hash); } bool ClassTableClear(ClassTable *table) { bool has_classes = RBTreeSize(table->classes) > 0; RBTreeClear(table->classes); return has_classes; } ClassTableIterator *ClassTableIteratorNew(const ClassTable *table, const char *ns, bool is_hard, bool is_soft) { ClassTableIterator *iter = xmalloc(sizeof(ClassTableIterator)); iter->ns = ns ? xstrdup(ns) : NULL; iter->iter = RBTreeIteratorNew(table->classes); iter->is_soft = is_soft; iter->is_hard = is_hard; return iter; } Class *ClassTableIteratorNext(ClassTableIterator *iter) { void *key_ref = NULL; Class *cls = NULL; while (RBTreeIteratorNext(iter->iter, &key_ref, (void **)&cls)) { const char *key_ns = cls->ns ? cls->ns : "default"; if (iter->ns && strcmp(key_ns, iter->ns) != 0) { continue; } if (iter->is_soft && !iter->is_soft) { continue; } if (iter->is_hard && !iter->is_hard) { continue; } return cls; } return NULL; } void ClassTableIteratorDestroy(ClassTableIterator *iter) { if (iter) { free(iter->ns); RBTreeIteratorDestroy(iter->iter); free(iter); } } ClassRef ClassRefParse(const char *expr) { char *name_start = strchr(expr, ':'); if (!name_start) { return (ClassRef) { .ns = NULL, .name = xstrdup(expr) }; } else { char *ns = NULL; if ((name_start - expr) > 0) { ns = xstrndup(expr, name_start - expr); } else { // this would be invalid syntax ns = xstrdup(""); } char *name = xstrdup(name_start + 1); return (ClassRef) { .ns = ns, .name = name }; } } char *ClassRefToString(const char *ns, const char *name) { if (!ns || strcmp("default", ns) == 0) { return xstrdup(name); } else { return StringConcatenate(3, ns, ":", name); } } bool ClassRefIsQualified(ClassRef ref) { return ref.ns != NULL; } void ClassRefQualify(ClassRef *ref, const char *ns) { free(ref->ns); ref->ns = xstrdup(ns); } void ClassRefDestroy(ClassRef ref) { free(ref.ns); free(ref.name); } cfengine-3.6.2/libpromises/attributes.c0000664000175100017510000016121112411001073017667 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #define CF_DEFINECLASSES "classes" #define CF_TRANSACTION "action" static FilePerms GetPermissionConstraints(const EvalContext *ctx, const Promise *pp); void ClearFilesAttributes(Attributes *whom) { UidListDestroy(whom->perms.owners); GidListDestroy(whom->perms.groups); } Attributes GetFilesAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; // default for file copy attr.havedepthsearch = PromiseGetConstraintAsBoolean(ctx, "depth_search", pp); attr.haveselect = PromiseGetConstraintAsBoolean(ctx, "file_select", pp); attr.haverename = PromiseGetConstraintAsBoolean(ctx, "rename", pp); attr.havedelete = PromiseGetConstraintAsBoolean(ctx, "delete", pp); attr.haveperms = PromiseGetConstraintAsBoolean(ctx, "perms", pp); attr.havechange = PromiseGetConstraintAsBoolean(ctx, "changes", pp); attr.havecopy = PromiseGetConstraintAsBoolean(ctx, "copy_from", pp); attr.havelink = PromiseGetConstraintAsBoolean(ctx, "link_from", pp); attr.edit_template = PromiseGetConstraintAsRval(pp, "edit_template", RVAL_TYPE_SCALAR); attr.template_method = PromiseGetConstraintAsRval(pp, "template_method", RVAL_TYPE_SCALAR); attr.template_data = PromiseGetConstraintAsRval(pp, "template_data", RVAL_TYPE_CONTAINER); attr.haveeditline = PromiseBundleConstraintExists(ctx, "edit_line", pp); attr.haveeditxml = PromiseBundleConstraintExists(ctx, "edit_xml", pp); attr.haveedit = (attr.haveeditline) || (attr.haveeditxml) || (attr.edit_template); /* Files, specialist */ attr.repository = PromiseGetConstraintAsRval(pp, "repository", RVAL_TYPE_SCALAR); attr.create = PromiseGetConstraintAsBoolean(ctx, "create", pp); attr.touch = PromiseGetConstraintAsBoolean(ctx, "touch", pp); attr.transformer = PromiseGetConstraintAsRval(pp, "transformer", RVAL_TYPE_SCALAR); attr.move_obstructions = PromiseGetConstraintAsBoolean(ctx, "move_obstructions", pp); attr.pathtype = PromiseGetConstraintAsRval(pp, "pathtype", RVAL_TYPE_SCALAR); attr.acl = GetAclConstraints(ctx, pp); attr.perms = GetPermissionConstraints(ctx, pp); attr.select = GetSelectConstraints(ctx, pp); attr.delete = GetDeleteConstraints(ctx, pp); attr.rename = GetRenameConstraints(ctx, pp); attr.change = GetChangeMgtConstraints(ctx, pp); attr.copy = GetCopyConstraints(ctx, pp); attr.link = GetLinkConstraints(ctx, pp); attr.edits = GetEditDefaults(ctx, pp); if (attr.edit_template) { attr.edits.empty_before_use = true; attr.edits.inherit = true; } /* Files, multiple use */ attr.recursion = GetRecursionConstraints(ctx, pp); /* Common ("included") */ attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetReportsAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.transaction = GetTransactionConstraints(ctx, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); attr.report = GetReportConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetEnvironmentsAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.transaction = GetTransactionConstraints(ctx, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); attr.env = GetEnvironmentsConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetServicesAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.transaction = GetTransactionConstraints(ctx, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); attr.service = GetServicesConstraints(ctx, pp); attr.havebundle = PromiseBundleConstraintExists(ctx, "service_bundle", pp); return attr; } /*******************************************************************/ Attributes GetPackageAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.transaction = GetTransactionConstraints(ctx, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); attr.packages = GetPackageConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetUserAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.havebundle = PromiseBundleConstraintExists(ctx, "home_bundle", pp); attr.inherit = PromiseGetConstraintAsBoolean(ctx, "home_bundle_inherit", pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); attr.users = GetUserConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetDatabaseAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.transaction = GetTransactionConstraints(ctx, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); attr.database = GetDatabaseConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetClassContextAttributes(const EvalContext *ctx, const Promise *pp) { Attributes a = { {0} }; a.transaction = GetTransactionConstraints(ctx, pp); a.classes = GetClassDefinitionConstraints(ctx, pp); a.context = GetContextConstraints(ctx, pp); return a; } /*******************************************************************/ Attributes GetExecAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.contain = GetExecContainConstraints(ctx, pp); attr.havecontain = PromiseGetConstraintAsBoolean(ctx, "contain", pp); attr.args = PromiseGetConstraintAsRval(pp, "args", RVAL_TYPE_SCALAR); attr.module = PromiseGetConstraintAsBoolean(ctx, "module", pp); /* Common ("included") */ attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetProcessAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.signals = PromiseGetConstraintAsList(ctx, "signals", pp); attr.process_stop = PromiseGetConstraintAsRval(pp, "process_stop", RVAL_TYPE_SCALAR); attr.haveprocess_count = PromiseGetConstraintAsBoolean(ctx, "process_count", pp); attr.haveselect = PromiseGetConstraintAsBoolean(ctx, "process_select", pp); attr.restart_class = PromiseGetConstraintAsRval(pp, "restart_class", RVAL_TYPE_SCALAR); attr.process_count = GetMatchesConstraints(ctx, pp); attr.process_select = GetProcessFilterConstraints(ctx, pp); /* Common ("included") */ attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetStorageAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.mount = GetMountConstraints(ctx, pp); attr.volume = GetVolumeConstraints(ctx, pp); attr.havevolume = PromiseGetConstraintAsBoolean(ctx, "volume", pp); attr.havemount = PromiseGetConstraintAsBoolean(ctx, "mount", pp); /* Common ("included") */ if (attr.edits.maxfilesize <= 0) { attr.edits.maxfilesize = EDITFILESIZE; } attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetMethodAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.havebundle = PromiseBundleConstraintExists(ctx, "usebundle", pp); attr.inherit = PromiseGetConstraintAsBoolean(ctx, "inherit", pp); /* Common ("included") */ attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } Attributes GetMeasurementAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.measure = GetMeasurementConstraint(ctx, pp); /* Common ("included") */ attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ /* Level */ /*******************************************************************/ Services GetServicesConstraints(const EvalContext *ctx, const Promise *pp) { Services s; s.service_type = PromiseGetConstraintAsRval(pp, "service_type", RVAL_TYPE_SCALAR); s.service_policy = ServicePolicyFromString(PromiseGetConstraintAsRval(pp, "service_policy", RVAL_TYPE_SCALAR)); s.service_autostart_policy = PromiseGetConstraintAsRval(pp, "service_autostart_policy", RVAL_TYPE_SCALAR); s.service_args = PromiseGetConstraintAsRval(pp, "service_args", RVAL_TYPE_SCALAR); s.service_depend = PromiseGetConstraintAsList(ctx, "service_dependencies", pp); s.service_depend_chain = PromiseGetConstraintAsRval(pp, "service_dependence_chain", RVAL_TYPE_SCALAR); return s; } /*******************************************************************/ Environments GetEnvironmentsConstraints(const EvalContext *ctx, const Promise *pp) { Environments e; e.cpus = PromiseGetConstraintAsInt(ctx, "env_cpus", pp); e.memory = PromiseGetConstraintAsInt(ctx, "env_memory", pp); e.disk = PromiseGetConstraintAsInt(ctx, "env_disk", pp); e.baseline = PromiseGetConstraintAsRval(pp, "env_baseline", RVAL_TYPE_SCALAR); e.spec = PromiseGetConstraintAsRval(pp, "env_spec", RVAL_TYPE_SCALAR); e.host = PromiseGetConstraintAsRval(pp, "environment_host", RVAL_TYPE_SCALAR); e.addresses = PromiseGetConstraintAsList(ctx, "env_addresses", pp); e.name = PromiseGetConstraintAsRval(pp, "env_name", RVAL_TYPE_SCALAR); e.type = PromiseGetConstraintAsRval(pp, "environment_type", RVAL_TYPE_SCALAR); e.state = EnvironmentStateFromString(PromiseGetConstraintAsRval(pp, "environment_state", RVAL_TYPE_SCALAR)); return e; } /*******************************************************************/ ExecContain GetExecContainConstraints(const EvalContext *ctx, const Promise *pp) { ExecContain e; e.shelltype = ShellTypeFromString(PromiseGetConstraintAsRval(pp, "useshell", RVAL_TYPE_SCALAR)); e.umask = PromiseGetConstraintAsOctal(ctx, "umask", pp); e.owner = PromiseGetConstraintAsUid(ctx, "exec_owner", pp); e.group = PromiseGetConstraintAsGid(ctx, "exec_group", pp); e.preview = PromiseGetConstraintAsBoolean(ctx, "preview", pp); e.nooutput = PromiseGetConstraintAsBoolean(ctx, "no_output", pp); e.timeout = PromiseGetConstraintAsInt(ctx, "exec_timeout", pp); e.chroot = PromiseGetConstraintAsRval(pp, "chroot", RVAL_TYPE_SCALAR); e.chdir = PromiseGetConstraintAsRval(pp, "chdir", RVAL_TYPE_SCALAR); return e; } /*******************************************************************/ DirectoryRecursion GetRecursionConstraints(const EvalContext *ctx, const Promise *pp) { DirectoryRecursion r; r.travlinks = PromiseGetConstraintAsBoolean(ctx, "traverse_links", pp); r.rmdeadlinks = PromiseGetConstraintAsBoolean(ctx, "rmdeadlinks", pp); r.depth = PromiseGetConstraintAsInt(ctx, "depth", pp); if (r.depth == CF_NOINT) { r.depth = 0; } r.xdev = PromiseGetConstraintAsBoolean(ctx, "xdev", pp); r.include_dirs = PromiseGetConstraintAsList(ctx, "include_dirs", pp); r.exclude_dirs = PromiseGetConstraintAsList(ctx, "exclude_dirs", pp); r.include_basedir = PromiseGetConstraintAsBoolean(ctx, "include_basedir", pp); return r; } /*******************************************************************/ Acl GetAclConstraints(const EvalContext *ctx, const Promise *pp) { Acl ac; ac.acl_method = AclMethodFromString(PromiseGetConstraintAsRval(pp, "acl_method", RVAL_TYPE_SCALAR)); ac.acl_type = AclTypeFromString(PromiseGetConstraintAsRval(pp, "acl_type", RVAL_TYPE_SCALAR)); ac.acl_default = AclDefaultFromString(PromiseGetConstraintAsRval(pp, "acl_default", RVAL_TYPE_SCALAR)); if (ac.acl_default == ACL_DEFAULT_NONE) { /* Deprecated attribute. */ ac.acl_default = AclDefaultFromString(PromiseGetConstraintAsRval(pp, "acl_directory_inherit", RVAL_TYPE_SCALAR)); } ac.acl_entries = PromiseGetConstraintAsList(ctx, "aces", pp); ac.acl_default_entries = PromiseGetConstraintAsList(ctx, "specify_default_aces", pp); if (ac.acl_default_entries == NULL) { /* Deprecated attribute. */ ac.acl_default_entries = PromiseGetConstraintAsList(ctx, "specify_inherit_aces", pp); } ac.acl_inherit = AclInheritFromString(PromiseGetConstraintAsRval(pp, "acl_inherit", RVAL_TYPE_SCALAR)); return ac; } /*******************************************************************/ static FilePerms GetPermissionConstraints(const EvalContext *ctx, const Promise *pp) { FilePerms p; char *value; Rlist *list; value = PromiseGetConstraintAsRval(pp, "mode", RVAL_TYPE_SCALAR); p.plus = CF_SAMEMODE; p.minus = CF_SAMEMODE; if (!ParseModeString(value, &p.plus, &p.minus)) { Log(LOG_LEVEL_ERR, "Problem validating a mode string"); PromiseRef(LOG_LEVEL_ERR, pp); } list = PromiseGetConstraintAsList(ctx, "bsdflags", pp); p.plus_flags = 0; p.minus_flags = 0; if (list && (!ParseFlagString(list, &p.plus_flags, &p.minus_flags))) { Log(LOG_LEVEL_ERR, "Problem validating a BSD flag string"); PromiseRef(LOG_LEVEL_ERR, pp); } p.owners = Rlist2UidList((Rlist *) PromiseGetConstraintAsRval(pp, "owners", RVAL_TYPE_LIST), pp); p.groups = Rlist2GidList((Rlist *) PromiseGetConstraintAsRval(pp, "groups", RVAL_TYPE_LIST), pp); p.findertype = PromiseGetConstraintAsRval(pp, "findertype", RVAL_TYPE_SCALAR); p.rxdirs = PromiseGetConstraintAsBoolean(ctx, "rxdirs", pp); // The default should be true if (!PromiseGetConstraintAsRval(pp, "rxdirs", RVAL_TYPE_SCALAR)) { p.rxdirs = true; } return p; } /*******************************************************************/ FileSelect GetSelectConstraints(const EvalContext *ctx, const Promise *pp) { FileSelect s; char *value; Rlist *rp; mode_t plus, minus; u_long fplus, fminus; int entries = false; s.name = (Rlist *) PromiseGetConstraintAsRval(pp, "leaf_name", RVAL_TYPE_LIST); s.path = (Rlist *) PromiseGetConstraintAsRval(pp, "path_name", RVAL_TYPE_LIST); s.filetypes = (Rlist *) PromiseGetConstraintAsRval(pp, "file_types", RVAL_TYPE_LIST); s.issymlinkto = (Rlist *) PromiseGetConstraintAsRval(pp, "issymlinkto", RVAL_TYPE_LIST); s.perms = PromiseGetConstraintAsList(ctx, "search_mode", pp); for (rp = s.perms; rp != NULL; rp = rp->next) { plus = 0; minus = 0; value = RlistScalarValue(rp); if (!ParseModeString(value, &plus, &minus)) { Log(LOG_LEVEL_ERR, "Problem validating a mode string"); PromiseRef(LOG_LEVEL_ERR, pp); } } s.bsdflags = PromiseGetConstraintAsList(ctx, "search_bsdflags", pp); fplus = 0; fminus = 0; if (!ParseFlagString(s.bsdflags, &fplus, &fminus)) { Log(LOG_LEVEL_ERR, "Problem validating a BSD flag string"); PromiseRef(LOG_LEVEL_ERR, pp); } if ((s.name) || (s.path) || (s.filetypes) || (s.issymlinkto) || (s.perms) || (s.bsdflags)) { entries = true; } s.owners = (Rlist *) PromiseGetConstraintAsRval(pp, "search_owners", RVAL_TYPE_LIST); s.groups = (Rlist *) PromiseGetConstraintAsRval(pp, "search_groups", RVAL_TYPE_LIST); value = PromiseGetConstraintAsRval(pp, "search_size", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, (long *) &s.min_size, (long *) &s.max_size)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "ctime", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, (long *) &s.min_ctime, (long *) &s.max_ctime)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "atime", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, (long *) &s.min_atime, (long *) &s.max_atime)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "mtime", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, (long *) &s.min_mtime, (long *) &s.max_mtime)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } s.exec_regex = PromiseGetConstraintAsRval(pp, "exec_regex", RVAL_TYPE_SCALAR); s.exec_program = PromiseGetConstraintAsRval(pp, "exec_program", RVAL_TYPE_SCALAR); if ((s.owners) || (s.min_size) || (s.exec_regex) || (s.exec_program)) { entries = true; } if ((s.result = PromiseGetConstraintAsRval(pp, "file_result", RVAL_TYPE_SCALAR)) == NULL) { if (!entries) { Log(LOG_LEVEL_ERR, "file_select body missing its a file_result return value"); } } return s; } /*******************************************************************/ LogLevel ActionAttributeLogLevelFromString(const char *log_level) { if (!log_level) { return LOG_LEVEL_ERR; } if (strcmp("inform", log_level) == 0) { return LOG_LEVEL_INFO; } else if (strcmp("verbose", log_level) == 0) { return LOG_LEVEL_VERBOSE; } else { return LOG_LEVEL_ERR; } } TransactionContext GetTransactionConstraints(const EvalContext *ctx, const Promise *pp) { TransactionContext t; char *value; value = PromiseGetConstraintAsRval(pp, "action_policy", RVAL_TYPE_SCALAR); if (value && ((strcmp(value, "warn") == 0) || (strcmp(value, "nop") == 0))) { t.action = cfa_warn; } else { t.action = cfa_fix; // default } t.background = PromiseGetConstraintAsBoolean(ctx, "background", pp); t.ifelapsed = PromiseGetConstraintAsInt(ctx, "ifelapsed", pp); if (t.ifelapsed == CF_NOINT) { t.ifelapsed = VIFELAPSED; } t.expireafter = PromiseGetConstraintAsInt(ctx, "expireafter", pp); if (t.expireafter == CF_NOINT) { t.expireafter = VEXPIREAFTER; } t.audit = PromiseGetConstraintAsBoolean(ctx, "audit", pp); t.log_string = PromiseGetConstraintAsRval(pp, "log_string", RVAL_TYPE_SCALAR); t.log_priority = SyslogPriorityFromString(PromiseGetConstraintAsRval(pp, "log_priority", RVAL_TYPE_SCALAR)); t.log_kept = PromiseGetConstraintAsRval(pp, "log_kept", RVAL_TYPE_SCALAR); t.log_repaired = PromiseGetConstraintAsRval(pp, "log_repaired", RVAL_TYPE_SCALAR); t.log_failed = PromiseGetConstraintAsRval(pp, "log_failed", RVAL_TYPE_SCALAR); value = PromiseGetConstraintAsRval(pp, "log_level", RVAL_TYPE_SCALAR); t.log_level = ActionAttributeLogLevelFromString(value); value = PromiseGetConstraintAsRval(pp, "report_level", RVAL_TYPE_SCALAR); t.report_level = ActionAttributeLogLevelFromString(value); t.measure_id = PromiseGetConstraintAsRval(pp, "measurement_class", RVAL_TYPE_SCALAR); return t; } /*******************************************************************/ DefineClasses GetClassDefinitionConstraints(const EvalContext *ctx, const Promise *pp) { DefineClasses c; char *pt = NULL; { const char *context_scope = PromiseGetConstraintAsRval(pp, "scope", RVAL_TYPE_SCALAR); c.scope = ContextScopeFromString(context_scope); } c.change = (Rlist *) PromiseGetConstraintAsList(ctx, "promise_repaired", pp); c.failure = (Rlist *) PromiseGetConstraintAsList(ctx, "repair_failed", pp); c.denied = (Rlist *) PromiseGetConstraintAsList(ctx, "repair_denied", pp); c.timeout = (Rlist *) PromiseGetConstraintAsList(ctx, "repair_timeout", pp); c.kept = (Rlist *) PromiseGetConstraintAsList(ctx, "promise_kept", pp); c.del_change = (Rlist *) PromiseGetConstraintAsList(ctx, "cancel_repaired", pp); c.del_kept = (Rlist *) PromiseGetConstraintAsList(ctx, "cancel_kept", pp); c.del_notkept = (Rlist *) PromiseGetConstraintAsList(ctx, "cancel_notkept", pp); c.retcode_kept = (Rlist *) PromiseGetConstraintAsList(ctx, "kept_returncodes", pp); c.retcode_repaired = (Rlist *) PromiseGetConstraintAsList(ctx, "repaired_returncodes", pp); c.retcode_failed = (Rlist *) PromiseGetConstraintAsList(ctx, "failed_returncodes", pp); c.persist = PromiseGetConstraintAsInt(ctx, "persist_time", pp); if (c.persist == CF_NOINT) { c.persist = 0; } pt = PromiseGetConstraintAsRval(pp, "timer_policy", RVAL_TYPE_SCALAR); if (pt && (strncmp(pt, "abs", 3) == 0)) { c.timer = CONTEXT_STATE_POLICY_PRESERVE; } else { c.timer = CONTEXT_STATE_POLICY_RESET; } return c; } /*******************************************************************/ FileDelete GetDeleteConstraints(const EvalContext *ctx, const Promise *pp) { FileDelete f; char *value; value = PromiseGetConstraintAsRval(pp, "dirlinks", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "keep") == 0)) { f.dirlinks = TIDY_LINK_KEEP; } else { f.dirlinks = TIDY_LINK_DELETE; } f.rmdirs = PromiseGetConstraintAsBoolean(ctx, "rmdirs", pp); return f; } /*******************************************************************/ FileRename GetRenameConstraints(const EvalContext *ctx, const Promise *pp) { FileRename r; char *value; value = PromiseGetConstraintAsRval(pp, "disable_mode", RVAL_TYPE_SCALAR); if (!ParseModeString(value, &r.plus, &r.minus)) { Log(LOG_LEVEL_ERR, "Problem validating a mode string"); PromiseRef(LOG_LEVEL_ERR, pp); } r.disable = PromiseGetConstraintAsBoolean(ctx, "disable", pp); r.disable_suffix = PromiseGetConstraintAsRval(pp, "disable_suffix", RVAL_TYPE_SCALAR); r.newname = PromiseGetConstraintAsRval(pp, "newname", RVAL_TYPE_SCALAR); r.rotate = PromiseGetConstraintAsInt(ctx, "rotate", pp); return r; } /*******************************************************************/ ENTERPRISE_FUNC_0ARG_DEFINE_STUB(HashMethod, GetBestFileChangeHashMethod) { return HASH_METHOD_BEST; } FileChange GetChangeMgtConstraints(const EvalContext *ctx, const Promise *pp) { FileChange c; char *value; value = PromiseGetConstraintAsRval(pp, "hash", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "best") == 0)) { c.hash = GetBestFileChangeHashMethod(); } else if (value && (strcmp(value, "md5") == 0)) { c.hash = HASH_METHOD_MD5; } else if (value && (strcmp(value, "sha1") == 0)) { c.hash = HASH_METHOD_SHA1; } else if (value && (strcmp(value, "sha256") == 0)) { c.hash = HASH_METHOD_SHA256; } else if (value && (strcmp(value, "sha384") == 0)) { c.hash = HASH_METHOD_SHA384; } else if (value && (strcmp(value, "sha512") == 0)) { c.hash = HASH_METHOD_SHA512; } else { c.hash = CF_DEFAULT_DIGEST; } if (FIPS_MODE && (c.hash == HASH_METHOD_MD5)) { Log(LOG_LEVEL_ERR, "FIPS mode is enabled, and md5 is not an approved algorithm"); PromiseRef(LOG_LEVEL_ERR, pp); } value = PromiseGetConstraintAsRval(pp, "report_changes", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "content") == 0)) { c.report_changes = FILE_CHANGE_REPORT_CONTENT_CHANGE; } else if (value && (strcmp(value, "stats") == 0)) { c.report_changes = FILE_CHANGE_REPORT_STATS_CHANGE; } else if (value && (strcmp(value, "all") == 0)) { c.report_changes = FILE_CHANGE_REPORT_ALL; } else { c.report_changes = FILE_CHANGE_REPORT_NONE; } if (PromiseGetConstraintAsRval(pp, "update_hashes", RVAL_TYPE_SCALAR)) { c.update = PromiseGetConstraintAsBoolean(ctx, "update_hashes", pp); } else { c.update = GetChecksumUpdatesDefault(ctx); } c.report_diffs = PromiseGetConstraintAsBoolean(ctx, "report_diffs", pp); return c; } /*******************************************************************/ FileCopy GetCopyConstraints(const EvalContext *ctx, const Promise *pp) { FileCopy f; long min, max; const char *value; f.source = PromiseGetConstraintAsRval(pp, "source", RVAL_TYPE_SCALAR); f.servers = PromiseGetConstraintAsList(ctx, "servers", pp); value = PromiseGetConstraintAsRval(pp, "compare", RVAL_TYPE_SCALAR); if (value == NULL) { value = DEFAULT_COPYTYPE; } f.compare = FileComparatorFromString(value); value = PromiseGetConstraintAsRval(pp, "link_type", RVAL_TYPE_SCALAR); f.link_type = FileLinkTypeFromString(value); char *protocol_version = PromiseGetConstraintAsRval(pp, "protocol_version", RVAL_TYPE_SCALAR); /* Default is undefined, which leaves the choice to body common. */ f.protocol_version = CF_PROTOCOL_UNDEFINED; if (protocol_version != NULL) { if (strcmp(protocol_version, "1") == 0 || strcmp(protocol_version, "classic") == 0) { f.protocol_version = CF_PROTOCOL_CLASSIC; } else if (strcmp(protocol_version, "2") == 0 || strcmp(protocol_version, "latest") == 0) { f.protocol_version = CF_PROTOCOL_TLS; } } f.port = PromiseGetConstraintAsRval(pp, "portnumber", RVAL_TYPE_SCALAR); f.timeout = (short) PromiseGetConstraintAsInt(ctx, "timeout", pp); f.link_instead = PromiseGetConstraintAsList(ctx, "linkcopy_patterns", pp); f.copy_links = PromiseGetConstraintAsList(ctx, "copylink_patterns", pp); value = PromiseGetConstraintAsRval(pp, "copy_backup", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "false") == 0)) { f.backup = BACKUP_OPTION_NO_BACKUP; } else if (value && (strcmp(value, "timestamp") == 0)) { f.backup = BACKUP_OPTION_TIMESTAMP; } else { f.backup = BACKUP_OPTION_BACKUP; } f.stealth = PromiseGetConstraintAsBoolean(ctx, "stealth", pp); f.collapse = PromiseGetConstraintAsBoolean(ctx, "collapse_destination_dir", pp); f.preserve = PromiseGetConstraintAsBoolean(ctx, "preserve", pp); f.type_check = PromiseGetConstraintAsBoolean(ctx, "type_check", pp); f.force_update = PromiseGetConstraintAsBoolean(ctx, "force_update", pp); f.force_ipv4 = PromiseGetConstraintAsBoolean(ctx, "force_ipv4", pp); f.check_root = PromiseGetConstraintAsBoolean(ctx, "check_root", pp); value = PromiseGetConstraintAsRval(pp, "copy_size", RVAL_TYPE_SCALAR); if (!IntegerRangeFromString(value, &min, &max)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } f.min_size = (size_t) min; f.max_size = (size_t) max; f.trustkey = PromiseGetConstraintAsBoolean(ctx, "trustkey", pp); f.encrypt = PromiseGetConstraintAsBoolean(ctx, "encrypt", pp); f.verify = PromiseGetConstraintAsBoolean(ctx, "verify", pp); f.purge = PromiseGetConstraintAsBoolean(ctx, "purge", pp); f.destination = NULL; return f; } /*******************************************************************/ FileLink GetLinkConstraints(const EvalContext *ctx, const Promise *pp) { FileLink f; char *value; f.source = PromiseGetConstraintAsRval(pp, "source", RVAL_TYPE_SCALAR); value = PromiseGetConstraintAsRval(pp, "link_type", RVAL_TYPE_SCALAR); f.link_type = FileLinkTypeFromString(value); f.copy_patterns = PromiseGetConstraintAsList(ctx, "copy_patterns", pp); value = PromiseGetConstraintAsRval(pp, "when_no_source", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "force") == 0)) { f.when_no_file = cfa_force; } else if (value && (strcmp(value, "delete") == 0)) { f.when_no_file = cfa_delete; } else { f.when_no_file = cfa_skip; } value = PromiseGetConstraintAsRval(pp, "when_linking_children", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "override_file") == 0)) { f.when_linking_children = cfa_override; } else { f.when_linking_children = cfa_onlynonexisting; } f.link_children = PromiseGetConstraintAsBoolean(ctx, "link_children", pp); return f; } /*******************************************************************/ EditDefaults GetEditDefaults(const EvalContext *ctx, const Promise *pp) { EditDefaults e = { 0 }; char *value; e.maxfilesize = PromiseGetConstraintAsInt(ctx, "max_file_size", pp); if ((e.maxfilesize == CF_NOINT) || (e.maxfilesize == 0)) { e.maxfilesize = EDITFILESIZE; } value = PromiseGetConstraintAsRval(pp, "edit_backup", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "false") == 0)) { e.backup = BACKUP_OPTION_NO_BACKUP; } else if (value && (strcmp(value, "timestamp") == 0)) { e.backup = BACKUP_OPTION_TIMESTAMP; } else if (value && (strcmp(value, "rotate") == 0)) { e.backup = BACKUP_OPTION_ROTATE; e.rotate = PromiseGetConstraintAsInt(ctx, "rotate", pp); } else { e.backup = BACKUP_OPTION_BACKUP; } e.empty_before_use = PromiseGetConstraintAsBoolean(ctx, "empty_file_before_editing", pp); e.joinlines = PromiseGetConstraintAsBoolean(ctx, "recognize_join", pp); e.inherit = PromiseGetConstraintAsBoolean(ctx, "inherit", pp); return e; } /*******************************************************************/ ContextConstraint GetContextConstraints(const EvalContext *ctx, const Promise *pp) { ContextConstraint a; a.nconstraints = 0; a.expression = NULL; a.persistent = PromiseGetConstraintAsInt(ctx, "persistence", pp); { const char *context_scope = PromiseGetConstraintAsRval(pp, "scope", RVAL_TYPE_SCALAR); a.scope = ContextScopeFromString(context_scope); } for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); for (int k = 0; CF_CLASSBODY[k].lval != NULL; k++) { if (strcmp(cp->lval, "persistence") == 0 || strcmp(cp->lval, "scope") == 0) { continue; } if (strcmp(cp->lval, CF_CLASSBODY[k].lval) == 0) { a.expression = cp; a.nconstraints++; } } } return a; } /*******************************************************************/ Packages GetPackageConstraints(const EvalContext *ctx, const Promise *pp) { Packages p; PackageAction action; PackageVersionComparator operator; PackageActionPolicy change_policy; p.have_package_methods = PromiseGetConstraintAsBoolean(ctx, "havepackage_method", pp); p.package_version = PromiseGetConstraintAsRval(pp, "package_version", RVAL_TYPE_SCALAR); p.package_architectures = PromiseGetConstraintAsList(ctx, "package_architectures", pp); action = PackageActionFromString(PromiseGetConstraintAsRval(pp, "package_policy", RVAL_TYPE_SCALAR)); p.package_policy = action; if (p.package_policy == PACKAGE_ACTION_NONE) // Default action => package add { p.package_policy = PACKAGE_ACTION_ADD; } operator = PackageVersionComparatorFromString(PromiseGetConstraintAsRval(pp, "package_select", RVAL_TYPE_SCALAR)); p.package_select = operator; change_policy = PackageActionPolicyFromString(PromiseGetConstraintAsRval(pp, "package_changes", RVAL_TYPE_SCALAR)); p.package_changes = change_policy; p.package_file_repositories = PromiseGetConstraintAsList(ctx, "package_file_repositories", pp); p.package_default_arch_command = PromiseGetConstraintAsRval(pp, "package_default_arch_command", RVAL_TYPE_SCALAR); p.package_patch_list_command = PromiseGetConstraintAsRval(pp, "package_patch_list_command", RVAL_TYPE_SCALAR); p.package_patch_name_regex = PromiseGetConstraintAsRval(pp, "package_patch_name_regex", RVAL_TYPE_SCALAR); p.package_patch_arch_regex = PromiseGetConstraintAsRval(pp, "package_patch_arch_regex", RVAL_TYPE_SCALAR); p.package_patch_version_regex = PromiseGetConstraintAsRval(pp, "package_patch_version_regex", RVAL_TYPE_SCALAR); p.package_patch_installed_regex = PromiseGetConstraintAsRval(pp, "package_patch_installed_regex", RVAL_TYPE_SCALAR); p.package_list_update_command = PromiseGetConstraintAsRval(pp, "package_list_update_command", RVAL_TYPE_SCALAR); p.package_list_update_ifelapsed = PromiseGetConstraintAsInt(ctx, "package_list_update_ifelapsed", pp); p.package_list_command = PromiseGetConstraintAsRval(pp, "package_list_command", RVAL_TYPE_SCALAR); p.package_list_version_regex = PromiseGetConstraintAsRval(pp, "package_list_version_regex", RVAL_TYPE_SCALAR); p.package_list_name_regex = PromiseGetConstraintAsRval(pp, "package_list_name_regex", RVAL_TYPE_SCALAR); p.package_list_arch_regex = PromiseGetConstraintAsRval(pp, "package_list_arch_regex", RVAL_TYPE_SCALAR); p.package_installed_regex = PromiseGetConstraintAsRval(pp, "package_installed_regex", RVAL_TYPE_SCALAR); p.package_version_regex = PromiseGetConstraintAsRval(pp, "package_version_regex", RVAL_TYPE_SCALAR); p.package_name_regex = PromiseGetConstraintAsRval(pp, "package_name_regex", RVAL_TYPE_SCALAR); p.package_arch_regex = PromiseGetConstraintAsRval(pp, "package_arch_regex", RVAL_TYPE_SCALAR); p.package_add_command = PromiseGetConstraintAsRval(pp, "package_add_command", RVAL_TYPE_SCALAR); p.package_delete_command = PromiseGetConstraintAsRval(pp, "package_delete_command", RVAL_TYPE_SCALAR); p.package_update_command = PromiseGetConstraintAsRval(pp, "package_update_command", RVAL_TYPE_SCALAR); p.package_patch_command = PromiseGetConstraintAsRval(pp, "package_patch_command", RVAL_TYPE_SCALAR); p.package_verify_command = PromiseGetConstraintAsRval(pp, "package_verify_command", RVAL_TYPE_SCALAR); p.package_noverify_regex = PromiseGetConstraintAsRval(pp, "package_noverify_regex", RVAL_TYPE_SCALAR); p.package_noverify_returncode = PromiseGetConstraintAsInt(ctx, "package_noverify_returncode", pp); if (PromiseGetConstraint(pp, "package_commands_useshell") == NULL) { p.package_commands_useshell = true; } else { p.package_commands_useshell = PromiseGetConstraintAsBoolean(ctx, "package_commands_useshell", pp); } p.package_name_convention = PromiseGetConstraintAsRval(pp, "package_name_convention", RVAL_TYPE_SCALAR); p.package_delete_convention = PromiseGetConstraintAsRval(pp, "package_delete_convention", RVAL_TYPE_SCALAR); p.package_multiline_start = PromiseGetConstraintAsRval(pp, "package_multiline_start", RVAL_TYPE_SCALAR); p.package_version_equal_command = PromiseGetConstraintAsRval(pp, "package_version_equal_command", RVAL_TYPE_SCALAR); p.package_version_less_command = PromiseGetConstraintAsRval(pp, "package_version_less_command", RVAL_TYPE_SCALAR); return p; } /*******************************************************************/ ProcessSelect GetProcessFilterConstraints(const EvalContext *ctx, const Promise *pp) { ProcessSelect p; char *value; int entries = 0; p.owner = PromiseGetConstraintAsList(ctx, "process_owner", pp); value = PromiseGetConstraintAsRval(pp, "pid", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_pid, &p.max_pid)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "ppid", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_ppid, &p.max_ppid)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "pgid", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_pgid, &p.max_pgid)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "rsize", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_rsize, &p.max_rsize)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "vsize", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_vsize, &p.max_vsize)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "ttime_range", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, (long *) &p.min_ttime, (long *) &p.max_ttime)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "stime_range", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, (long *) &p.min_stime, (long *) &p.max_stime)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } p.status = PromiseGetConstraintAsRval(pp, "status", RVAL_TYPE_SCALAR); p.command = PromiseGetConstraintAsRval(pp, "command", RVAL_TYPE_SCALAR); p.tty = PromiseGetConstraintAsRval(pp, "tty", RVAL_TYPE_SCALAR); value = PromiseGetConstraintAsRval(pp, "priority", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_pri, &p.max_pri)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } value = PromiseGetConstraintAsRval(pp, "threads", RVAL_TYPE_SCALAR); if (value) { entries++; } if (!IntegerRangeFromString(value, &p.min_thread, &p.max_thread)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } if ((p.owner) || (p.status) || (p.command) || (p.tty)) { entries = true; } if ((p.process_result = PromiseGetConstraintAsRval(pp, "process_result", RVAL_TYPE_SCALAR)) == NULL) { if (entries) { Log(LOG_LEVEL_ERR, "process_select body missing its a process_result return value"); } } return p; } /*******************************************************************/ ProcessCount GetMatchesConstraints(const EvalContext *ctx, const Promise *pp) { ProcessCount p; char *value; value = PromiseGetConstraintAsRval(pp, "match_range", RVAL_TYPE_SCALAR); if (!IntegerRangeFromString(value, &p.min_range, &p.max_range)) { PromiseRef(LOG_LEVEL_ERR, pp); FatalError(ctx, "Could not make sense of integer range [%s]", value); } p.in_range_define = PromiseGetConstraintAsList(ctx, "in_range_define", pp); p.out_of_range_define = PromiseGetConstraintAsList(ctx, "out_of_range_define", pp); return p; } Attributes GetInsertionAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.havelocation = PromiseGetConstraintAsBoolean(ctx, "location", pp); attr.location = GetLocationAttributes(pp); attr.sourcetype = PromiseGetConstraintAsRval(pp, "insert_type", RVAL_TYPE_SCALAR); attr.expandvars = PromiseGetConstraintAsBoolean(ctx, "expand_scalars", pp); attr.haveinsertselect = PromiseGetConstraintAsBoolean(ctx, "insert_select", pp); attr.line_select = GetInsertSelectConstraints(ctx, pp); attr.insert_match = PromiseGetConstraintAsList(ctx, "whitespace_policy", pp); /* Common ("included") */ attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp); attr.region = GetRegionConstraints(ctx, pp); attr.xml = GetXmlConstraints(pp); attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ EditLocation GetLocationAttributes(const Promise *pp) { EditLocation e; char *value; e.line_matching = PromiseGetConstraintAsRval(pp, "select_line_matching", RVAL_TYPE_SCALAR); value = PromiseGetConstraintAsRval(pp, "before_after", RVAL_TYPE_SCALAR); if (value && (strcmp(value, "before") == 0)) { e.before_after = EDIT_ORDER_BEFORE; } else { e.before_after = EDIT_ORDER_AFTER; } e.first_last = PromiseGetConstraintAsRval(pp, "first_last", RVAL_TYPE_SCALAR); return e; } /*******************************************************************/ Attributes GetDeletionAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.not_matching = PromiseGetConstraintAsBoolean(ctx, "not_matching", pp); attr.havedeleteselect = PromiseGetConstraintAsBoolean(ctx, "delete_select", pp); attr.line_select = GetDeleteSelectConstraints(ctx, pp); /* common */ attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp); attr.region = GetRegionConstraints(ctx, pp); attr.xml = GetXmlConstraints(pp); attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetColumnAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.havecolumn = PromiseGetConstraintAsBoolean(ctx, "edit_field", pp); attr.column = GetColumnConstraints(ctx, pp); /* common */ attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp); attr.region = GetRegionConstraints(ctx, pp); attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ Attributes GetReplaceAttributes(const EvalContext *ctx, const Promise *pp) { Attributes attr = { {0} }; attr.havereplace = PromiseGetConstraintAsBoolean(ctx, "replace_patterns", pp); attr.replace = GetReplaceConstraints(pp); attr.havecolumn = PromiseGetConstraintAsBoolean(ctx, "replace_with", pp); /* common */ attr.haveregion = PromiseGetConstraintAsBoolean(ctx, "select_region", pp); attr.region = GetRegionConstraints(ctx, pp); attr.xml = GetXmlConstraints(pp); attr.havetrans = PromiseGetConstraintAsBoolean(ctx, CF_TRANSACTION, pp); attr.transaction = GetTransactionConstraints(ctx, pp); attr.haveclasses = PromiseGetConstraintAsBoolean(ctx, CF_DEFINECLASSES, pp); attr.classes = GetClassDefinitionConstraints(ctx, pp); return attr; } /*******************************************************************/ EditXml GetXmlConstraints(const Promise *pp) { EditXml x; x.havebuildxpath = ((x.build_xpath = PromiseGetConstraintAsRval(pp, "build_xpath", RVAL_TYPE_SCALAR)) != NULL); x.haveselectxpath = ((x.select_xpath = PromiseGetConstraintAsRval(pp, "select_xpath", RVAL_TYPE_SCALAR)) != NULL); x.haveattributevalue = ((x.attribute_value = PromiseGetConstraintAsRval(pp, "attribute_value", RVAL_TYPE_SCALAR)) != NULL); return x; } /*******************************************************************/ EditRegion GetRegionConstraints(const EvalContext *ctx, const Promise *pp) { EditRegion e; e.select_start = PromiseGetConstraintAsRval(pp, "select_start", RVAL_TYPE_SCALAR); e.select_end = PromiseGetConstraintAsRval(pp, "select_end", RVAL_TYPE_SCALAR); e.include_start = PromiseGetConstraintAsBoolean(ctx, "include_start_delimiter", pp); e.include_end = PromiseGetConstraintAsBoolean(ctx, "include_end_delimiter", pp); return e; } /*******************************************************************/ EditReplace GetReplaceConstraints(const Promise *pp) { EditReplace r; r.replace_value = PromiseGetConstraintAsRval(pp, "replace_value", RVAL_TYPE_SCALAR); r.occurrences = PromiseGetConstraintAsRval(pp, "occurrences", RVAL_TYPE_SCALAR); return r; } /*******************************************************************/ EditColumn GetColumnConstraints(const EvalContext *ctx, const Promise *pp) { EditColumn c; char *value; c.column_separator = PromiseGetConstraintAsRval(pp, "field_separator", RVAL_TYPE_SCALAR); c.select_column = PromiseGetConstraintAsInt(ctx, "select_field", pp); if (((c.select_column) != CF_NOINT) && (PromiseGetConstraintAsBoolean(ctx, "start_fields_from_zero", pp))) { c.select_column++; } value = PromiseGetConstraintAsRval(pp, "value_separator", RVAL_TYPE_SCALAR); if (value) { c.value_separator = *value; } else { c.value_separator = '\0'; } c.column_value = PromiseGetConstraintAsRval(pp, "field_value", RVAL_TYPE_SCALAR); c.column_operation = PromiseGetConstraintAsRval(pp, "field_operation", RVAL_TYPE_SCALAR); c.extend_columns = PromiseGetConstraintAsBoolean(ctx, "extend_fields", pp); c.blanks_ok = PromiseGetConstraintAsBoolean(ctx, "allow_blank_fields", pp); return c; } /*******************************************************************/ /* Storage */ /*******************************************************************/ StorageMount GetMountConstraints(const EvalContext *ctx, const Promise *pp) { StorageMount m; m.mount_type = PromiseGetConstraintAsRval(pp, "mount_type", RVAL_TYPE_SCALAR); m.mount_source = PromiseGetConstraintAsRval(pp, "mount_source", RVAL_TYPE_SCALAR); m.mount_server = PromiseGetConstraintAsRval(pp, "mount_server", RVAL_TYPE_SCALAR); m.mount_options = PromiseGetConstraintAsList(ctx, "mount_options", pp); m.editfstab = PromiseGetConstraintAsBoolean(ctx, "edit_fstab", pp); m.unmount = PromiseGetConstraintAsBoolean(ctx, "unmount", pp); return m; } /*******************************************************************/ StorageVolume GetVolumeConstraints(const EvalContext *ctx, const Promise *pp) { StorageVolume v; char *value; v.check_foreign = PromiseGetConstraintAsBoolean(ctx, "check_foreign", pp); value = PromiseGetConstraintAsRval(pp, "freespace", RVAL_TYPE_SCALAR); v.freespace = (long) IntFromString(value); value = PromiseGetConstraintAsRval(pp, "sensible_size", RVAL_TYPE_SCALAR); v.sensible_size = (int) IntFromString(value); value = PromiseGetConstraintAsRval(pp, "sensible_count", RVAL_TYPE_SCALAR); v.sensible_count = (int) IntFromString(value); v.scan_arrivals = PromiseGetConstraintAsBoolean(ctx, "scan_arrivals", pp); // defaults if (v.sensible_size == CF_NOINT) { v.sensible_size = 1000; } if (v.sensible_count == CF_NOINT) { v.sensible_count = 2; } return v; } Report GetReportConstraints(const EvalContext *ctx, const Promise *pp) { Report r = {0}; r.result = PromiseGetConstraintAsRval(pp, "bundle_return_value_index", RVAL_TYPE_SCALAR); if (PromiseGetConstraintAsRval(pp, "lastseen", RVAL_TYPE_SCALAR)) { r.havelastseen = true; r.lastseen = PromiseGetConstraintAsInt(ctx, "lastseen", pp); if (r.lastseen == CF_NOINT) { r.lastseen = 0; } } else { r.havelastseen = false; r.lastseen = 0; } if (!PromiseGetConstraintAsReal(ctx, "intermittency", pp, &r.intermittency)) { r.intermittency = 0; } r.haveprintfile = PromiseGetConstraintAsBoolean(ctx, "printfile", pp); r.filename = PromiseGetConstraintAsRval(pp, "file_to_print", RVAL_TYPE_SCALAR); r.numlines = PromiseGetConstraintAsInt(ctx, "number_of_lines", pp); if (r.numlines == CF_NOINT) { r.numlines = 5; } r.showstate = PromiseGetConstraintAsList(ctx, "showstate", pp); r.friend_pattern = PromiseGetConstraintAsRval(pp, "friend_pattern", RVAL_TYPE_SCALAR); r.to_file = PromiseGetConstraintAsRval(pp, "report_to_file", RVAL_TYPE_SCALAR); if ((r.result) && ((r.haveprintfile) || (r.filename) || (r.showstate) || (r.to_file) || (r.lastseen))) { Log(LOG_LEVEL_ERR, "bundle_return_value promise for '%s' in bundle '%s' with too many constraints (ignored)", pp->promiser, PromiseGetBundle(pp)->name); } return r; } /*******************************************************************/ LineSelect GetInsertSelectConstraints(const EvalContext *ctx, const Promise *pp) { LineSelect s; s.startwith_from_list = PromiseGetConstraintAsList(ctx, "insert_if_startwith_from_list", pp); s.not_startwith_from_list = PromiseGetConstraintAsList(ctx, "insert_if_not_startwith_from_list", pp); s.match_from_list = PromiseGetConstraintAsList(ctx, "insert_if_match_from_list", pp); s.not_match_from_list = PromiseGetConstraintAsList(ctx, "insert_if_not_match_from_list", pp); s.contains_from_list = PromiseGetConstraintAsList(ctx, "insert_if_contains_from_list", pp); s.not_contains_from_list = PromiseGetConstraintAsList(ctx, "insert_if_not_contains_from_list", pp); return s; } /*******************************************************************/ LineSelect GetDeleteSelectConstraints(const EvalContext *ctx, const Promise *pp) { LineSelect s; s.startwith_from_list = PromiseGetConstraintAsList(ctx, "delete_if_startwith_from_list", pp); s.not_startwith_from_list = PromiseGetConstraintAsList(ctx, "delete_if_not_startwith_from_list", pp); s.match_from_list = PromiseGetConstraintAsList(ctx, "delete_if_match_from_list", pp); s.not_match_from_list = PromiseGetConstraintAsList(ctx, "delete_if_not_match_from_list", pp); s.contains_from_list = PromiseGetConstraintAsList(ctx, "delete_if_contains_from_list", pp); s.not_contains_from_list = PromiseGetConstraintAsList(ctx, "delete_if_not_contains_from_list", pp); return s; } /*******************************************************************/ Measurement GetMeasurementConstraint(const EvalContext *ctx, const Promise *pp) { Measurement m; char *value; m.stream_type = PromiseGetConstraintAsRval(pp, "stream_type", RVAL_TYPE_SCALAR); value = PromiseGetConstraintAsRval(pp, "data_type", RVAL_TYPE_SCALAR); m.data_type = DataTypeFromString(value); if (m.data_type == CF_DATA_TYPE_NONE) { m.data_type = CF_DATA_TYPE_STRING; } m.history_type = PromiseGetConstraintAsRval(pp, "history_type", RVAL_TYPE_SCALAR); m.select_line_matching = PromiseGetConstraintAsRval(pp, "select_line_matching", RVAL_TYPE_SCALAR); m.select_line_number = PromiseGetConstraintAsInt(ctx, "select_line_number", pp); m.policy = MeasurePolicyFromString(PromiseGetConstraintAsRval(pp, "select_multiline_policy", RVAL_TYPE_SCALAR)); m.extraction_regex = PromiseGetConstraintAsRval(pp, "extraction_regex", RVAL_TYPE_SCALAR); m.units = PromiseGetConstraintAsRval(pp, "units", RVAL_TYPE_SCALAR); m.growing = PromiseGetConstraintAsBoolean(ctx, "track_growing_file", pp); return m; } /*******************************************************************/ Database GetDatabaseConstraints(const EvalContext *ctx, const Promise *pp) { Database d; char *value; d.db_server_owner = PromiseGetConstraintAsRval(pp, "db_server_owner", RVAL_TYPE_SCALAR); d.db_server_password = PromiseGetConstraintAsRval(pp, "db_server_password", RVAL_TYPE_SCALAR); d.db_server_host = PromiseGetConstraintAsRval(pp, "db_server_host", RVAL_TYPE_SCALAR); d.db_connect_db = PromiseGetConstraintAsRval(pp, "db_server_connection_db", RVAL_TYPE_SCALAR); d.type = PromiseGetConstraintAsRval(pp, "database_type", RVAL_TYPE_SCALAR); d.server = PromiseGetConstraintAsRval(pp, "database_server", RVAL_TYPE_SCALAR); d.columns = PromiseGetConstraintAsList(ctx, "database_columns", pp); d.rows = PromiseGetConstraintAsList(ctx, "database_rows", pp); d.operation = PromiseGetConstraintAsRval(pp, "database_operation", RVAL_TYPE_SCALAR); d.exclude = PromiseGetConstraintAsList(ctx, "registry_exclude", pp); value = PromiseGetConstraintAsRval(pp, "db_server_type", RVAL_TYPE_SCALAR); d.db_server_type = DatabaseTypeFromString(value); if (value && ((d.db_server_type) == DATABASE_TYPE_NONE)) { Log(LOG_LEVEL_ERR, "Unsupported database type '%s' in databases promise", value); PromiseRef(LOG_LEVEL_ERR, pp); } return d; } /*******************************************************************/ User GetUserConstraints(const EvalContext *ctx, const Promise *pp) { User u; char *value; value = PromiseGetConstraintAsRval(pp, "policy", RVAL_TYPE_SCALAR); u.policy = UserStateFromString(value); u.uid = PromiseGetConstraintAsRval(pp, "uid", RVAL_TYPE_SCALAR); value = PromiseGetConstraintAsRval(pp, "format", RVAL_TYPE_SCALAR); u.password_format = PasswordFormatFromString(value); u.password = PromiseGetConstraintAsRval(pp, "data", RVAL_TYPE_SCALAR); u.description = PromiseGetConstraintAsRval(pp, "description", RVAL_TYPE_SCALAR); u.group_primary = PromiseGetConstraintAsRval(pp, "group_primary", RVAL_TYPE_SCALAR); u.groups_secondary = PromiseGetConstraintAsList(ctx, "groups_secondary", pp); u.home_dir = PromiseGetConstraintAsRval(pp, "home_dir", RVAL_TYPE_SCALAR); u.shell = PromiseGetConstraintAsRval(pp, "shell", RVAL_TYPE_SCALAR); if (value && ((u.policy) == USER_STATE_NONE)) { Log(LOG_LEVEL_ERR, "Unsupported user policy '%s' in users promise", value); PromiseRef(LOG_LEVEL_ERR, pp); } return u; } cfengine-3.6.2/libpromises/syslog_client.c0000664000175100017510000000775112400110761020372 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* * Set by cf-agent/cf-serverd from body agent/server control. */ static char SYSLOG_HOST[MAXHOSTNAMELEN] = "localhost"; /* * Set by cf-agent/cf-serverd from body agent/server control. */ static uint16_t SYSLOG_PORT = 514; /* * Set by cf-agent/cf-serverd/cf-execd from body agent/exec/server control. */ static int SYSLOG_FACILITY = LOG_USER; void SetSyslogFacility(int facility) { SYSLOG_FACILITY = facility; } bool SetSyslogHost(const char *host) { if (strlen(host) < sizeof(SYSLOG_HOST)) { strcpy(SYSLOG_HOST, host); return true; } else { return false; } } void SetSyslogPort(uint16_t port) { SYSLOG_PORT = port; } void RemoteSysLog(int log_priority, const char *log_string) { time_t now = time(NULL); struct addrinfo query = { 0 }, *response = NULL; char strport[PRINTSIZE(unsigned)]; xsnprintf(strport, sizeof(strport), "%u", (unsigned) SYSLOG_PORT); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_DGRAM; int err = getaddrinfo(SYSLOG_HOST, strport, &query, &response); if (err != 0) { Log(LOG_LEVEL_INFO, "Unable to find syslog_host or service: (%s/%s) %s", SYSLOG_HOST, strport, gai_strerror(err)); if (response != NULL) { freeaddrinfo(response); } return; } for (const struct addrinfo *ap = response; ap != NULL; ap = ap->ai_next) { /* No DNS lookup, just convert IP address to string. */ char txtaddr[CF_MAX_IP_LEN] = ""; getnameinfo(ap->ai_addr, ap->ai_addrlen, txtaddr, sizeof(txtaddr), NULL, 0, NI_NUMERICHOST); Log(LOG_LEVEL_VERBOSE, "Connect to syslog '%s' = '%s' on port '%s'", SYSLOG_HOST, txtaddr, strport); int sd = socket(ap->ai_family, ap->ai_socktype, IPPROTO_UDP); if (sd == -1) { Log(LOG_LEVEL_INFO, "Couldn't open a socket. (socket: %s)", GetErrorStr()); continue; } else { const size_t rfc3164_len = 1024; char message[rfc3164_len]; char timebuffer[26]; pid_t pid = getpid(); snprintf(message, sizeof(message), "<%i>%.15s %s %s[%d]: %s", log_priority | SYSLOG_FACILITY, cf_strtimestamp_local(now, timebuffer) + 4, VFQNAME, VPREFIX, pid, log_string); err = sendto(sd, message, strlen(message), 0, ap->ai_addr, ap->ai_addrlen); if (err == -1) { Log(LOG_LEVEL_VERBOSE, "Couldn't send '%s' to syslog server '%s'. (sendto: %s)", message, SYSLOG_HOST, GetErrorStr()); } else { Log(LOG_LEVEL_VERBOSE, "Syslog message: '%s' to server '%s'", message, SYSLOG_HOST); } close(sd); } } freeaddrinfo(response); } cfengine-3.6.2/libpromises/evalfunction.c0000664000175100017510000102527612411001073020211 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* CompileRegex,StringMatchWithPrecompiledRegex */ #include /* SocketConnect */ #include #include /* SendSocketStream */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __MINGW32__ #include #endif #include static FnCallResult FilterInternal(EvalContext *ctx, const FnCall *fp, const char *regex, const char *name, bool do_regex, bool invert, long max); static char* JsonPrimitiveToString(const JsonElement *el); static char *StripPatterns(char *file_buffer, const char *pattern, const char *filename); static void CloseStringHole(char *s, int start, int end); static int BuildLineArray(EvalContext *ctx, const Bundle *bundle, const char *array_lval, const char *file_buffer, const char *split, int maxent, DataType type, bool int_index); static JsonElement* BuildData(EvalContext *ctx, const char *file_buffer, const char *split, int maxent, bool make_array); static int ExecModule(EvalContext *ctx, char *command); static bool CheckID(const char *id); static const Rlist *GetListReferenceArgument(const EvalContext *ctx, const const FnCall *fp, const char *lval_str, DataType *datatype_out); static void *CfReadFile(const char *filename, int maxsize); /*******************************************************************/ int FnNumArgs(const FnCallType *call_type) { for (int i = 0;; i++) { if (call_type->args[i].pattern == NULL) { return i; } } } /*******************************************************************/ /* assume args are all scalar literals by the time we get here and each handler allocates the memory it returns. There is a protocol to be followed here: Set args, Eval Content, Set rtype, ErrorFlags returnval = FnCallXXXResult(fp) */ /* * Return succesful FnCallResult with copy of str retained. */ static FnCallResult FnReturn(const char *str) { return (FnCallResult) { FNCALL_SUCCESS, { xstrdup(str), RVAL_TYPE_SCALAR } }; } /* * Return succesful FnCallResult with str as is. */ static FnCallResult FnReturnNoCopy(char *str) { return (FnCallResult) { FNCALL_SUCCESS, { str, RVAL_TYPE_SCALAR } }; } static FnCallResult FnReturnBuffer(Buffer *buf) { return (FnCallResult) { FNCALL_SUCCESS, { BufferClose(buf), RVAL_TYPE_SCALAR } }; } static FnCallResult FnReturnF(const char *fmt, ...) FUNC_ATTR_PRINTF(1, 2); static FnCallResult FnReturnF(const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *buffer; xvasprintf(&buffer, fmt, ap); va_end(ap); return (FnCallResult) { FNCALL_SUCCESS, { buffer, RVAL_TYPE_SCALAR } }; } static FnCallResult FnReturnContext(bool result) { return FnReturn(result ? "any" : "!any"); } static FnCallResult FnFailure(void) { return (FnCallResult) { FNCALL_FAILURE }; } static VarRef* ResolveAndQualifyVarName(const FnCall *fp, const char *varname) { VarRef *ref = VarRefParse(varname); if (!VarRefIsQualified(ref)) { if (fp->caller) { const Bundle *caller_bundle = PromiseGetBundle(fp->caller); VarRefQualify(ref, caller_bundle->ns, caller_bundle->name); } else { Log(LOG_LEVEL_WARNING, "Function '%s' was not called from a promise; " "the unqualified variable reference %s cannot be qualified automatically.", fp->name, varname); VarRefDestroy(ref); return NULL; } } return ref; } static JsonElement* VarRefValueToJson(EvalContext *ctx, const FnCall *fp, const VarRef *ref, const DataType disallowed_datatypes[], size_t disallowed_count) { assert(ref); DataType value_type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &value_type); bool want_type = true; for (int di = 0; di < disallowed_count; di++) { if (disallowed_datatypes[di] == value_type) { want_type = false; break; } } JsonElement *convert = NULL; if (want_type) { switch (DataTypeToRvalType(value_type)) { case RVAL_TYPE_LIST: convert = JsonArrayCreate(RlistLen(value)); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR && strcmp(RlistScalarValue(value), CF_NULL_VALUE) != 0) { JsonArrayAppendString(convert, RlistScalarValue(rp)); } } break; case RVAL_TYPE_CONTAINER: convert = JsonCopy(value); break; default: { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, ref->ns, ref->scope, ref->lval); convert = JsonObjectCreate(10); Variable *var; while ((var = VariableTableIteratorNext(iter))) { // TODO: explain array iteration if (var->ref->num_indices != 1) { continue; } switch (var->rval.type) { case RVAL_TYPE_SCALAR: JsonObjectAppendString(convert, var->ref->indices[0], var->rval.item); break; case RVAL_TYPE_LIST: { JsonElement *array = JsonArrayCreate(10); for (const Rlist *rp = RvalRlistValue(var->rval); rp != NULL; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR && strcmp(RlistScalarValue(rp), CF_NULL_VALUE) != 0) { JsonArrayAppendString(array, RlistScalarValue(rp)); } } JsonObjectAppendArray(convert, var->ref->indices[0], array); } break; default: break; } } VariableTableIteratorDestroy(iter); if (JsonLength(convert) < 1) { char *varname = VarRefToString(ref, true); Log(LOG_LEVEL_VERBOSE, "%s: argument '%s' does not resolve to a container or a list or a CFEngine array", fp->name, varname); free(varname); JsonDestroy(convert); return NULL; } break; } // end of default case } // end of data type switch } else // !wanted_type { char *varname = VarRefToString(ref, true); Log(LOG_LEVEL_DEBUG, "%s: argument '%s' resolved to an undesired data type", fp->name, varname); free(varname); } return convert; } static Rlist *GetHostsFromLastseenDB(Item *addresses, time_t horizon, bool return_address, bool return_recent) { Rlist *recent = NULL, *aged = NULL; Item *ip; time_t now = time(NULL); double entrytime; char address[CF_MAXVARSIZE]; for (ip = addresses; ip != NULL; ip = ip->next) { if (sscanf(ip->classes, "%lf", &entrytime) != 1) { Log(LOG_LEVEL_ERR, "Could not get host entry age"); continue; } if (return_address) { snprintf(address, sizeof(address), "%s", ip->name); } else { char hostname[MAXHOSTNAMELEN]; if (IPString2Hostname(hostname, ip->name, sizeof(hostname)) != -1) { snprintf(address, sizeof(address), "%s", hostname); } else { /* Not numeric address was requested, but IP was unresolvable. */ snprintf(address, sizeof(address), "%s", ip->name); } } if (entrytime < now - horizon) { Log(LOG_LEVEL_DEBUG, "Old entry"); if (RlistKeyIn(recent, address)) { Log(LOG_LEVEL_DEBUG, "There is recent entry for this address. Do nothing."); } else { Log(LOG_LEVEL_DEBUG, "Adding to list of aged hosts."); RlistPrependScalarIdemp(&aged, address); } } else { Rlist *r; Log(LOG_LEVEL_DEBUG, "Recent entry"); if ((r = RlistKeyIn(aged, address))) { Log(LOG_LEVEL_DEBUG, "Purging from list of aged hosts."); RlistDestroyEntry(&aged, r); } Log(LOG_LEVEL_DEBUG, "Adding to list of recent hosts."); RlistPrependScalarIdemp(&recent, address); } } if (return_recent) { RlistDestroy(aged); if (recent == NULL) { RlistAppendScalarIdemp(&recent, CF_NULL_VALUE); } return recent; } else { RlistDestroy(recent); if (aged == NULL) { RlistAppendScalarIdemp(&aged, CF_NULL_VALUE); } return aged; } } /*********************************************************************/ static FnCallResult FnCallAnd(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(fp->name, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "Function '%s', %s", fp->name, SyntaxTypeMatchToString(err)); } } for (const Rlist *arg = finalargs; arg; arg = arg->next) { if (!IsDefinedClass(ctx, RlistScalarValue(arg))) { return FnReturnContext(false); } } return FnReturnContext(true); } /*******************************************************************/ static bool CallHostsSeenCallback(const char *hostkey, const char *address, ARG_UNUSED bool incoming, const KeyHostSeen *quality, void *ctx) { Item **addresses = ctx; if (HostKeyAddressUnknown(hostkey)) { return true; } char buf[PRINTSIZE(uintmax_t)]; xsnprintf(buf, sizeof(buf), "%ju", (uintmax_t) quality->lastseen); PrependItem(addresses, address, buf); return true; } /*******************************************************************/ static FnCallResult FnCallHostsSeen(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Item *addresses = NULL; int horizon = IntFromString(RlistScalarValue(finalargs)) * 3600; char *hostseen_policy = RlistScalarValue(finalargs->next); char *format = RlistScalarValue(finalargs->next->next); Log(LOG_LEVEL_DEBUG, "Calling hostsseen(%d,%s,%s)", horizon, hostseen_policy, format); if (!ScanLastSeenQuality(&CallHostsSeenCallback, &addresses)) { return FnFailure(); } Rlist *returnlist = GetHostsFromLastseenDB(addresses, horizon, strcmp(format, "address") == 0, strcmp(hostseen_policy, "lastseen") == 0); DeleteItemList(addresses); { Writer *w = StringWriter(); WriterWrite(w, "hostsseen return values:"); for (Rlist *rp = returnlist; rp; rp = rp->next) { WriterWriteF(w, " '%s'", RlistScalarValue(rp)); } Log(LOG_LEVEL_DEBUG, "%s", StringWriterData(w)); WriterClose(w); } if (returnlist == NULL) { return FnFailure(); } else { return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } } /*********************************************************************/ static FnCallResult FnCallHostsWithClass(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *returnlist = NULL; char *class_name = RlistScalarValue(finalargs); char *return_format = RlistScalarValue(finalargs->next); if(!ListHostsWithClass(ctx, &returnlist, class_name, return_format)) { return FnFailure(); } return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallRandomInt(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { int tmp, range, result; int from = IntFromString(RlistScalarValue(finalargs)); int to = IntFromString(RlistScalarValue(finalargs->next)); if (from == CF_NOINT || to == CF_NOINT) { return FnFailure(); } if (from > to) { tmp = to; to = from; from = tmp; } range = fabs(to - from); result = from + (int) (drand48() * (double) range); return FnReturnF("%d", result); } /*********************************************************************/ static FnCallResult FnCallGetEnv(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE] = "", ctrlstr[CF_SMALLBUF]; char *name = RlistScalarValue(finalargs); int limit = IntFromString(RlistScalarValue(finalargs->next)); snprintf(ctrlstr, CF_SMALLBUF, "%%.%ds", limit); // -> %45s if (getenv(name)) { snprintf(buffer, CF_BUFSIZE - 1, ctrlstr, getenv(name)); } return FnReturn(buffer); } /*********************************************************************/ #if defined(HAVE_GETPWENT) static FnCallResult FnCallGetUsers(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *except_name = RlistScalarValue(finalargs); const char *except_uid = RlistScalarValue(finalargs->next); Rlist *except_names = RlistFromSplitString(except_name, ','); Rlist *except_uids = RlistFromSplitString(except_uid, ','); setpwent(); Rlist *newlist = NULL; struct passwd *pw; while ((pw = getpwent())) { char *pw_uid_str = StringFromLong((int)pw->pw_uid); if (!RlistKeyIn(except_names, pw->pw_name) && !RlistKeyIn(except_uids, pw_uid_str)) { RlistAppendScalarIdemp(&newlist, pw->pw_name); } free(pw_uid_str); } endpwent(); RlistDestroy(except_names); RlistDestroy(except_uids); return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } #else static FnCallResult FnCallGetUsers(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, ARG_UNUSED const Rlist *finalargs) { Log(LOG_LEVEL_ERR, "getusers is not implemented"); return FnFailure(); } #endif /*********************************************************************/ static FnCallResult FnCallEscape(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; buffer[0] = '\0'; char *name = RlistScalarValue(finalargs); EscapeSpecialChars(name, buffer, CF_BUFSIZE - 1, "", ""); return FnReturn(buffer); } /*********************************************************************/ static FnCallResult FnCallHost2IP(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char *name = RlistScalarValue(finalargs); char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, name, sizeof(ipaddr)) != -1) { return FnReturn(ipaddr); } else { /* Retain legacy behaviour, return hostname in case resolution fails. */ return FnReturn(name); } } /*********************************************************************/ static FnCallResult FnCallIP2Host(ARG_UNUSED EvalContext *ctx, ARG_UNUSED ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char hostname[MAXHOSTNAMELEN]; char *ip = RlistScalarValue(finalargs); if (IPString2Hostname(hostname, ip, sizeof(hostname)) != -1) { return FnReturn(hostname); } else { /* Retain legacy behaviour, return ip address in case resolution fails. */ return FnReturn(ip); } } /*********************************************************************/ #ifdef __MINGW32__ static FnCallResult FnCallGetUid(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, ARG_UNUSED const Rlist *finalargs) { return FnFailure(); } #else /* !__MINGW32__ */ static FnCallResult FnCallGetUid(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct passwd *pw; /* begin fn specific content */ if ((pw = getpwnam(RlistScalarValue(finalargs))) == NULL) { return FnFailure(); } else { return FnReturnF("%ju", (uintmax_t)pw->pw_uid); } } #endif /* !__MINGW32__ */ /*********************************************************************/ #ifdef __MINGW32__ static FnCallResult FnCallGetGid(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, ARG_UNUSED const Rlist *finalargs) { return FnFailure(); } #else /* !__MINGW32__ */ static FnCallResult FnCallGetGid(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct group *gr; /* begin fn specific content */ if ((gr = getgrnam(RlistScalarValue(finalargs))) == NULL) { return FnFailure(); } else { return FnReturnF("%ju", (uintmax_t)gr->gr_gid); } } #endif /* __MINGW32__ */ /*********************************************************************/ static FnCallResult FnCallHandlerHash(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) /* Hash(string,md5|sha1|crypt) */ { char buffer[CF_BUFSIZE]; unsigned char digest[EVP_MAX_MD_SIZE + 1]; HashMethod type; buffer[0] = '\0'; /* begin fn specific content */ char *string = RlistScalarValue(finalargs); char *typestring = RlistScalarValue(finalargs->next); type = HashIdFromName(typestring); if (FIPS_MODE && type == HASH_METHOD_MD5) { Log(LOG_LEVEL_ERR, "FIPS mode is enabled, and md5 is not an approved algorithm in call to hash()"); } HashString(string, strlen(string), digest, type); char hashbuffer[CF_HOSTKEY_STRING_SIZE]; snprintf(buffer, CF_BUFSIZE - 1, "%s", HashPrintSafe(hashbuffer, sizeof(hashbuffer), digest, type, true)); return FnReturn(SkipHashType(buffer)); } /*********************************************************************/ static FnCallResult FnCallHashMatch(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) /* HashMatch(string,md5|sha1|crypt,"abdxy98edj") */ { char buffer[CF_BUFSIZE]; unsigned char digest[EVP_MAX_MD_SIZE + 1]; HashMethod type; buffer[0] = '\0'; /* begin fn specific content */ char *string = RlistScalarValue(finalargs); char *typestring = RlistScalarValue(finalargs->next); char *compare = RlistScalarValue(finalargs->next->next); type = HashIdFromName(typestring); HashFile(string, digest, type); char hashbuffer[CF_HOSTKEY_STRING_SIZE]; snprintf(buffer, CF_BUFSIZE - 1, "%s", HashPrintSafe(hashbuffer, sizeof(hashbuffer), digest, type, true)); Log(LOG_LEVEL_VERBOSE, "File '%s' hashes to '%s', compare to '%s'", string, buffer, compare); return FnReturnContext(strcmp(buffer + 4, compare) == 0); } /*********************************************************************/ static FnCallResult FnCallConcat(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char id[CF_BUFSIZE]; char result[CF_BUFSIZE] = ""; snprintf(id, CF_BUFSIZE, "built-in FnCall concat-arg"); /* We need to check all the arguments, ArgTemplate does not check varadic functions */ for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err)); } } for (const Rlist *arg = finalargs; arg; arg = arg->next) { if (strlcat(result, RlistScalarValue(arg), CF_BUFSIZE) >= CF_BUFSIZE) { /* Complain */ Log(LOG_LEVEL_ERR, "Unable to evaluate concat() function, arguments are too long"); return FnFailure(); } } return FnReturn(result); } /*********************************************************************/ static FnCallResult FnCallClassMatch(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *regex = RlistScalarValue(finalargs); pcre *rx = CompileRegex(regex); { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(regex, expr) || (rx && StringMatchFullWithPrecompiledRegex(rx, expr))) { free(expr); ClassTableIteratorDestroy(iter); if (rx) { pcre_free(rx); } return FnReturnContext(true); } free(expr); } ClassTableIteratorDestroy(iter); } { ClassTableIterator *iter = EvalContextClassTableIteratorNewLocal(ctx); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(regex,expr) || (rx && StringMatchFullWithPrecompiledRegex(rx, expr))) { free(expr); ClassTableIteratorDestroy(iter); if (rx) { pcre_free(rx); } return FnReturnContext(true); } free(expr); } ClassTableIteratorDestroy(iter); } if (rx) { pcre_free(rx); } return FnReturnContext(false); } /*********************************************************************/ static FnCallResult FnCallIfElse(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { int argcount = 0; char id[CF_BUFSIZE]; snprintf(id, CF_BUFSIZE, "built-in FnCall ifelse-arg"); /* We need to check all the arguments, ArgTemplate does not check varadic functions */ for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err)); } argcount++; } /* Require an odd number of arguments. We will always return something. */ if (argcount%2 != 1) { FatalError(ctx, "in built-in FnCall ifelse: even number of arguments"); } const Rlist *arg; for (arg = finalargs; /* Start with arg set to finalargs. */ arg && arg->next; /* We must have arg and arg->next to proceed. */ arg = arg->next->next) /* arg steps forward *twice* every time. */ { /* Similar to classmatch(), we evaluate the first of the two * arguments as a class. */ if (IsDefinedClass(ctx, RlistScalarValue(arg))) { /* If the evaluation returned true in the current context, * return the second of the two arguments. */ return FnReturn(RlistScalarValue(arg->next)); } } /* If we get here, we've reached the last argument (arg->next is NULL). */ return FnReturn(RlistScalarValue(arg)); } /*********************************************************************/ static FnCallResult FnCallCountClassesMatching(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { unsigned count = 0; const char *regex = RlistScalarValue(finalargs); pcre *rx = CompileRegex(regex); { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(regex, expr) || (rx && StringMatchFullWithPrecompiledRegex(rx, expr))) { count++; } free(expr); } ClassTableIteratorDestroy(iter); } { ClassTableIterator *iter = EvalContextClassTableIteratorNewLocal(ctx); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(regex, expr) || (rx && StringMatchFullWithPrecompiledRegex(rx, expr))) { count++; } free(expr); } ClassTableIteratorDestroy(iter); } if (rx) { pcre_free(rx); } return FnReturnF("%u", count); } /*********************************************************************/ static StringSet *ClassesMatching(const EvalContext *ctx, ClassTableIterator *iter, const Rlist *args) { StringSet *matching = StringSetNew(); const char *regex = RlistScalarValue(args); pcre *rx = CompileRegex(regex); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(regex, expr) || (rx && StringMatchFullWithPrecompiledRegex(rx, expr))) { bool pass = false; StringSet *tagset = EvalContextClassTags(ctx, cls->ns, cls->name); if (args->next) { for (const Rlist *arg = args->next; arg; arg = arg->next) { const char *tag_regex = RlistScalarValue(arg); const char *element; StringSetIterator it = StringSetIteratorInit(tagset); while ((element = StringSetIteratorNext(&it))) { /* FIXME: review this strcmp. Moved out from StringMatch */ if (strcmp(tag_regex, element) == 0 || StringMatchFull(tag_regex, element)) { pass = true; break; } } } } else // without any tags queried, accept class { pass = true; } if (pass) { StringSetAdd(matching, expr); } else { free(expr); } } else { free(expr); } } if (rx) { pcre_free(rx); } return matching; } static FnCallResult FnCallClassesMatching(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { if (!finalargs) { FatalError(ctx, "Function '%s' requires at least one argument", fp->name); } for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(fp->name, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "in function '%s', '%s'", fp->name, SyntaxTypeMatchToString(err)); } } Rlist *matches = NULL; { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); StringSet *global_matches = ClassesMatching(ctx, iter, finalargs); StringSetIterator it = StringSetIteratorInit(global_matches); const char *element = NULL; while ((element = StringSetIteratorNext(&it))) { RlistPrepend(&matches, element, RVAL_TYPE_SCALAR); } StringSetDestroy(global_matches); ClassTableIteratorDestroy(iter); } { ClassTableIterator *iter = EvalContextClassTableIteratorNewLocal(ctx); StringSet *local_matches = ClassesMatching(ctx, iter, finalargs); StringSetIterator it = StringSetIteratorInit(local_matches); const char *element = NULL; while ((element = StringSetIteratorNext(&it))) { RlistPrepend(&matches, element, RVAL_TYPE_SCALAR); } StringSetDestroy(local_matches); ClassTableIteratorDestroy(iter); } if (!matches) { RlistAppendScalarIdemp(&matches, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { matches, RVAL_TYPE_LIST } }; } static StringSet *VariablesMatching(const EvalContext *ctx, VariableTableIterator *iter, const Rlist *args) { StringSet *matching = StringSetNew(); const char *regex = RlistScalarValue(args); pcre *rx = CompileRegex(regex); Variable *v = NULL; while ((v = VariableTableIteratorNext(iter))) { char *expr = VarRefToString(v->ref, true); /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(regex, expr) || (rx && StringMatchFullWithPrecompiledRegex(rx, expr))) { StringSet *tagset = EvalContextVariableTags(ctx, v->ref); bool pass = false; if (args->next) { for (const Rlist *arg = args->next; arg; arg = arg->next) { const char* tag_regex = RlistScalarValue(arg); const char *element = NULL; StringSetIterator it = StringSetIteratorInit(tagset); while ((element = SetIteratorNext(&it))) { /* FIXME: review this strcmp. Moved out from StringMatch */ if (strcmp(tag_regex, element) == 0 || StringMatchFull(tag_regex, element)) { pass = true; break; } } } } else // without any tags queried, accept variable { pass = true; } if (pass) { StringSetAdd(matching, expr); } else { free(expr); } } else { free(expr); } } if (rx) { pcre_free(rx); } return matching; } static FnCallResult FnCallVariablesMatching(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { if (!finalargs) { FatalError(ctx, "Function '%s' requires at least one argument", fp->name); } for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(fp->name, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "In function '%s', %s", fp->name, SyntaxTypeMatchToString(err)); } } Rlist *matches = NULL; { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, NULL, NULL, NULL); StringSet *global_matches = VariablesMatching(ctx, iter, finalargs); StringSetIterator it = StringSetIteratorInit(global_matches); const char *element = NULL; while ((element = StringSetIteratorNext(&it))) { RlistPrepend(&matches, element, RVAL_TYPE_SCALAR); } StringSetDestroy(global_matches); VariableTableIteratorDestroy(iter); } if (!matches) { RlistAppendScalarIdemp(&matches, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { matches, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallGetMetaTags(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { Rlist *tags = NULL; StringSet *tagset = NULL; if (0 == strcmp(fp->name, "getvariablemetatags")) { VarRef *ref = VarRefParse(RlistScalarValue(finalargs)); tagset = EvalContextVariableTags(ctx, ref); VarRefDestroy(ref); } else if (0 == strcmp(fp->name, "getclassmetatags")) { ClassRef ref = ClassRefParse(RlistScalarValue(finalargs)); tagset = EvalContextClassTags(ctx, ref.ns, ref.name); ClassRefDestroy(ref); } else { FatalError(ctx, "FnCallGetMetaTags: got unknown function name '%s', aborting", fp->name); } if (NULL == tagset) { Log(LOG_LEVEL_VERBOSE, "%s found variable or class %s without a tagset", fp->name, RlistScalarValue(finalargs)); return (FnCallResult) { FNCALL_FAILURE }; } char* element; StringSetIterator it = StringSetIteratorInit(tagset); while ((element = SetIteratorNext(&it))) { RlistAppendScalar(&tags, element); } if (!tags) { RlistAppendScalar(&tags, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { tags, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallBundlesMatching(EvalContext *ctx, const Policy *policy, const FnCall *fp, const Rlist *finalargs) { if (!finalargs) { return FnFailure(); } const char *regex = RlistScalarValue(finalargs); pcre *rx = CompileRegex(regex); if (!rx) { return FnFailure(); } const Rlist *tag_args = finalargs->next; Rlist *matches = NULL; for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *bp = SeqAt(policy->bundles, i); char *bundle_name = BundleQualifiedName(bp); if (StringMatchFullWithPrecompiledRegex(rx, bundle_name)) { VarRef *ref = VarRefParseFromBundle("tags", bp); VarRefSetMeta(ref, true); DataType type = CF_DATA_TYPE_NONE; const void *bundle_tags = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); bool found = false; // case where tag_args are given and the bundle has no tags if (NULL == tag_args) { // we declare it found if no tags were requested found = true; } else if (NULL != bundle_tags) { switch (DataTypeToRvalType(type)) { case RVAL_TYPE_SCALAR: { Rlist *searched = RlistFromSplitString(bundle_tags, ','); found = RlistMatchesRegexRlist(searched, tag_args); RlistDestroy(searched); } break; case RVAL_TYPE_LIST: found = RlistMatchesRegexRlist(bundle_tags, tag_args); break; default: Log(LOG_LEVEL_WARNING, "Function '%s' only matches tags defined as a scalar or a list. " "Bundle '%s' had meta defined as '%s'", fp->name, bundle_name, DataTypeToString(type)); found = false; break; } } if (found) { RlistPrepend(&matches, bundle_name, RVAL_TYPE_SCALAR); } } free(bundle_name); } pcre_free(rx); if (!matches) { RlistAppendScalarIdemp(&matches, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { matches, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallPackagesMatching(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const bool installed_mode = (0 == strcmp(fp->name, "packagesmatching")); pcre *matcher; { const char *regex_package = RlistScalarValue(finalargs); const char *regex_version = RlistScalarValue(finalargs->next); const char *regex_arch = RlistScalarValue(finalargs->next->next); const char *regex_method = RlistScalarValue(finalargs->next->next->next); char regex[CF_BUFSIZE]; // Here we will truncate the regex if the parameters add up to over CF_BUFSIZE snprintf(regex, sizeof(regex), "^%s,%s,%s,%s$", regex_package, regex_version, regex_arch, regex_method); matcher = CompileRegex(regex); if (matcher == NULL) { return FnFailure(); } } char filename[CF_MAXVARSIZE]; if (installed_mode) { GetSoftwareCacheFilename(filename); } else { GetSoftwarePatchesFilename(filename); } Log(LOG_LEVEL_DEBUG, "%s: reading inventory from '%s'", fp->name, filename); FILE *const fin = fopen(filename, "r"); if (fin == NULL) { Log(LOG_LEVEL_VERBOSE, "%s cannot open the %s packages inventory '%s' - " "This is not necessarily an error. " "Either the inventory policy has not been included, " "or it has not had time to have an effect yet. " "A future call may still succeed. (fopen: %s)", fp->name, installed_mode ? "installed" : "available", filename, GetErrorStr()); pcre_free(matcher); return FnFailure(); } JsonElement *json = JsonArrayCreate(50); int linenumber = 0; char *line; while (NULL != (line = GetCsvLineNext(fin))) { if (strlen(line) > CF_BUFSIZE - 80) { Log(LOG_LEVEL_ERR, "Line %d from package inventory '%s' is too long (%zd) to be sensible", linenumber, filename, strlen(line)); free(line); break; /* or continue ? */ } if (StringMatchFullWithPrecompiledRegex(matcher, line)) { Seq *list = SeqParseCsvString(line); if (SeqLength(list) != 4) { Log(LOG_LEVEL_ERR, "Line %d from package inventory '%s' did not yield 4 elements: %s", linenumber, filename, line); ++linenumber; SeqDestroy(list); free(line); continue; } JsonElement *line_obj = JsonObjectCreate(4); JsonObjectAppendString(line_obj, "name", SeqAt(list, 0)); JsonObjectAppendString(line_obj, "version", SeqAt(list, 1)); JsonObjectAppendString(line_obj, "arch", SeqAt(list, 2)); JsonObjectAppendString(line_obj, "method", SeqAt(list, 3)); SeqDestroy(list); JsonArrayAppendObject(json, line_obj); } ++linenumber; free(line); } const char *errstr = GetErrorStr(); /* Only relevant if fail */ bool fail = !feof(fin); fclose(fin); pcre_free(matcher); if (fail) { Log(LOG_LEVEL_ERR, "Unable to read (%s) package inventory from '%s'.", errstr, filename); JsonDestroy(json); return FnFailure(); } return (FnCallResult) { FNCALL_SUCCESS, (Rval) { json, RVAL_TYPE_CONTAINER } }; } /*********************************************************************/ static FnCallResult FnCallCanonify(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char buf[CF_BUFSIZE]; char *string = RlistScalarValue(finalargs); buf[0] = '\0'; if (!strcmp(fp->name, "canonifyuniquely")) { char hashbuffer[CF_HOSTKEY_STRING_SIZE]; unsigned char digest[EVP_MAX_MD_SIZE + 1]; HashMethod type; type = HashIdFromName("sha1"); HashString(string, strlen(string), digest, type); snprintf(buf, CF_BUFSIZE, "%s_%s", string, SkipHashType(HashPrintSafe(hashbuffer, sizeof(hashbuffer), digest, type, true))); } else { snprintf(buf, CF_BUFSIZE, "%s", string); } return FnReturn(CanonifyName(buf)); } /*********************************************************************/ static FnCallResult FnCallTextXform(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char buf[CF_BUFSIZE]; char *string = RlistScalarValue(finalargs); int len = 0; memset(buf, 0, sizeof(buf)); strlcpy(buf, string, sizeof(buf)); len = strlen(buf); if (!strcmp(fp->name, "string_downcase")) { int pos = 0; for (pos = 0; pos < len; pos++) { buf[pos] = tolower(buf[pos]); } } else if (!strcmp(fp->name, "string_upcase")) { int pos = 0; for (pos = 0; pos < len; pos++) { buf[pos] = toupper(buf[pos]); } } else if (!strcmp(fp->name, "string_reverse")) { int c, i, j; for (i = 0, j = len - 1; i < j; i++, j--) { c = buf[i]; buf[i] = buf[j]; buf[j] = c; } } else if (!strcmp(fp->name, "string_length")) { xsnprintf(buf, sizeof(buf), "%d", len); } else if (!strcmp(fp->name, "string_head")) { const long max = IntFromString(RlistScalarValue(finalargs->next)); if (max < sizeof(buf)) { buf[max] = '\0'; } } else if (!strcmp(fp->name, "string_tail")) { const long max = IntFromString(RlistScalarValue(finalargs->next)); if (max < len) { strncpy(buf, string + len - max, sizeof(buf) - 1); } } else { Log(LOG_LEVEL_ERR, "text xform with unknown call function %s, aborting", fp->name); return FnFailure(); } return FnReturn(buf); } /*********************************************************************/ static FnCallResult FnCallLastNode(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *rp, *newlist; /* begin fn specific content */ char *name = RlistScalarValue(finalargs); char *split = RlistScalarValue(finalargs->next); newlist = RlistFromSplitRegex(name, split, 100, true); for (rp = newlist; rp != NULL; rp = rp->next) { if (rp->next == NULL) { break; } } if (rp && rp->val.item) { char *res = xstrdup(RlistScalarValue(rp)); RlistDestroy(newlist); return (FnCallResult) { FNCALL_SUCCESS, { res, RVAL_TYPE_SCALAR } }; } else { RlistDestroy(newlist); return FnFailure(); } } /*******************************************************************/ static FnCallResult FnCallDirname(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char dir[PATH_MAX] = ""; strlcpy(dir, RlistScalarValue(finalargs), PATH_MAX); DeleteSlash(dir); ChopLastNode(dir); return FnReturn(dir); } /*********************************************************************/ static FnCallResult FnCallClassify(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { bool is_defined = IsDefinedClass(ctx, CanonifyName(RlistScalarValue(finalargs))); return FnReturnContext(is_defined); } /*********************************************************************/ /* Executions */ /*********************************************************************/ static FnCallResult FnCallReturnsZero(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char comm[CF_BUFSIZE]; const char *shell_option = RlistScalarValue(finalargs->next); ShellType shelltype = SHELL_TYPE_NONE; bool need_executable_check = false; if (strcmp(shell_option, "useshell") == 0) { shelltype = SHELL_TYPE_USE; } else if (strcmp(shell_option, "powershell") == 0) { shelltype = SHELL_TYPE_POWERSHELL; } if (IsAbsoluteFileName(RlistScalarValue(finalargs))) { need_executable_check = true; } else if (shelltype == SHELL_TYPE_NONE) { Log(LOG_LEVEL_ERR, "returnszero '%s' does not have an absolute path", RlistScalarValue(finalargs)); return FnReturnContext(false); } if (need_executable_check && !IsExecutable(CommandArg0(RlistScalarValue(finalargs)))) { Log(LOG_LEVEL_ERR, "returnszero '%s' is assumed to be executable but isn't", RlistScalarValue(finalargs)); return FnReturnContext(false); } snprintf(comm, CF_BUFSIZE, "%s", RlistScalarValue(finalargs)); if (ShellCommandReturnsZero(comm, shelltype)) { Log(LOG_LEVEL_VERBOSE, "%s ran '%s' successfully and it returned zero", fp->name, RlistScalarValue(finalargs)); return FnReturnContext(true); } else { Log(LOG_LEVEL_VERBOSE, "%s ran '%s' successfully and it did not return zero", fp->name, RlistScalarValue(finalargs)); return FnReturnContext(false); } } /*********************************************************************/ static FnCallResult FnCallExecResult(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *shell_option = RlistScalarValue(finalargs->next); ShellType shelltype = SHELL_TYPE_NONE; bool need_executable_check = false; if (strcmp(shell_option, "useshell") == 0) { shelltype = SHELL_TYPE_USE; } else if (strcmp(shell_option, "powershell") == 0) { shelltype = SHELL_TYPE_POWERSHELL; } if (IsAbsoluteFileName(RlistScalarValue(finalargs))) { need_executable_check = true; } else if (shelltype == SHELL_TYPE_NONE) { Log(LOG_LEVEL_ERR, "%s '%s' does not have an absolute path", fp->name, RlistScalarValue(finalargs)); return FnFailure(); } if (need_executable_check && !IsExecutable(CommandArg0(RlistScalarValue(finalargs)))) { Log(LOG_LEVEL_ERR, "%s '%s' is assumed to be executable but isn't", fp->name, RlistScalarValue(finalargs)); return FnFailure(); } char buffer[CF_EXPANDSIZE]; if (GetExecOutput(RlistScalarValue(finalargs), buffer, shelltype)) { Log(LOG_LEVEL_VERBOSE, "%s ran '%s' successfully", fp->name, RlistScalarValue(finalargs)); return FnReturn(buffer); } else { Log(LOG_LEVEL_VERBOSE, "%s could not run '%s' successfully", fp->name, RlistScalarValue(finalargs)); return FnFailure(); } } /*********************************************************************/ static FnCallResult FnCallUseModule(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) /* usemodule("/programpath",varargs) */ { char modulecmd[CF_BUFSIZE]; struct stat statbuf; /* begin fn specific content */ char *command = RlistScalarValue(finalargs); char *args = RlistScalarValue(finalargs->next); snprintf(modulecmd, CF_BUFSIZE, "\"%s%cmodules%c%s\"", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, command); if (stat(CommandArg0(modulecmd), &statbuf) == -1) { Log(LOG_LEVEL_ERR, "Plug-in module '%s' not found", modulecmd); return FnFailure(); } if ((statbuf.st_uid != 0) && (statbuf.st_uid != getuid())) { Log(LOG_LEVEL_ERR, "Module '%s' was not owned by uid %ju who is executing agent", modulecmd, (uintmax_t)getuid()); return FnFailure(); } if (!JoinPath(modulecmd, args)) { Log(LOG_LEVEL_ERR, "Culprit: class list for module (shouldn't happen)"); return FnFailure(); } snprintf(modulecmd, CF_BUFSIZE, "\"%s%cmodules%c%s\" %s", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, command, args); Log(LOG_LEVEL_VERBOSE, "Executing and using module [%s]", modulecmd); if (!ExecModule(ctx, modulecmd)) { return FnFailure(); } return FnReturnContext(true); } /*********************************************************************/ /* Misc */ /*********************************************************************/ static FnCallResult FnCallSplayClass(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char class_name[CF_MAXVARSIZE]; Interval splay_policy = IntervalFromString(RlistScalarValue(finalargs->next)); if (splay_policy == INTERVAL_HOURLY) { /* 12 5-minute slots in hour */ int slot = StringHash(RlistScalarValue(finalargs), 0, CF_HASHTABLESIZE) * 12 / CF_HASHTABLESIZE; snprintf(class_name, CF_MAXVARSIZE, "Min%02d_%02d", slot * 5, ((slot + 1) * 5) % 60); } else { /* 12*24 5-minute slots in day */ int dayslot = StringHash(RlistScalarValue(finalargs), 0, CF_HASHTABLESIZE) * 12 * 24 / CF_HASHTABLESIZE; int hour = dayslot / 12; int slot = dayslot % 12; snprintf(class_name, CF_MAXVARSIZE, "Min%02d_%02d.Hr%02d", slot * 5, ((slot + 1) * 5) % 60, hour); } return FnReturnContext(IsDefinedClass(ctx, class_name)); } /*********************************************************************/ /* ReadTCP(localhost,80,'GET index.html',1000) */ static FnCallResult FnCallReadTcp(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char *hostnameip = RlistScalarValue(finalargs); char *port = RlistScalarValue(finalargs->next); char *sendstring = RlistScalarValue(finalargs->next->next); ssize_t maxbytes = IntFromString(RlistScalarValue(finalargs->next->next->next)); if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON) { return FnFailure(); } if (maxbytes < 0 || maxbytes > CF_BUFSIZE - 1) { Log(LOG_LEVEL_VERBOSE, "readtcp: invalid number of bytes %zd to read, defaulting to %d", maxbytes, CF_BUFSIZE - 1); maxbytes = CF_BUFSIZE - 1; } char txtaddr[CF_MAX_IP_LEN] = ""; int sd = SocketConnect(hostnameip, port, CONNTIMEOUT, false, txtaddr, sizeof(txtaddr)); if (sd == -1) { Log(LOG_LEVEL_INFO, "readtcp: Couldn't connect. (socket: %s)", GetErrorStr()); return FnFailure(); } if (strlen(sendstring) > 0) { int sent = 0; int result = 0; size_t length = strlen(sendstring); do { result = send(sd, sendstring, length, 0); if (result < 0) { cf_closesocket(sd); return FnFailure(); } else { sent += result; } } while (sent < length); } char recvbuf[CF_BUFSIZE]; ssize_t n_read = recv(sd, recvbuf, maxbytes, 0); cf_closesocket(sd); if (n_read == -1) { Log(LOG_LEVEL_INFO, "readtcp: Error while receiving (%s)", GetErrorStr()); return FnFailure(); } assert(n_read < sizeof(recvbuf)); recvbuf[n_read] = '\0'; Log(LOG_LEVEL_VERBOSE, "readtcp: requested %zd maxbytes, got %zd bytes from %s", maxbytes, n_read, txtaddr); return FnReturn(recvbuf); } /*********************************************************************/ static FnCallResult FnCallRegList(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *listvar = RlistScalarValue(finalargs); if (!IsVarList(listvar)) { Log(LOG_LEVEL_VERBOSE, "Function reglist was promised a list called '%s' but this was not found", listvar); return FnFailure(); } char naked[CF_MAXVARSIZE] = ""; GetNaked(naked, listvar); VarRef *ref = VarRefParse(naked); DataType value_type = CF_DATA_TYPE_NONE; const Rlist *value = EvalContextVariableGet(ctx, ref, &value_type); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_VERBOSE, "Function REGLIST was promised a list called '%s' but this was not found", listvar); return FnFailure(); } if (DataTypeToRvalType(value_type) != RVAL_TYPE_LIST) { Log(LOG_LEVEL_VERBOSE, "Function reglist was promised a list called '%s' but this variable is not a list", listvar); return FnFailure(); } pcre *rx = CompileRegex(RlistScalarValue(finalargs->next)); if (!rx) { return FnFailure(); } for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (strcmp(RlistScalarValue(rp), CF_NULL_VALUE) == 0) { continue; } if (StringMatchFullWithPrecompiledRegex(rx, RlistScalarValue(rp))) { pcre_free(rx); return FnReturnContext(true); } } pcre_free(rx); return FnReturnContext(false); } /*********************************************************************/ static FnCallResult FnCallRegArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char *arrayname = RlistScalarValue(finalargs); pcre *rx = CompileRegex(RlistScalarValue(finalargs->next)); if (!rx) { return FnFailure(); } VarRef *ref = VarRefParse(arrayname); bool found = false; VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, ref->ns, ref->scope, ref->lval); VarRefDestroy(ref); Variable *var = NULL; while ((var = VariableTableIteratorNext(iter))) { if (StringMatchFullWithPrecompiledRegex(rx, RvalScalarValue(var->rval))) { found = true; break; } } VariableTableIteratorDestroy(iter); pcre_free(rx); return FnReturnContext(found); } static FnCallResult FnCallGetIndices(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { VarRef *ref = VarRefParse(RlistScalarValue(finalargs)); if (!VarRefIsQualified(ref)) { if (fp->caller) { const Bundle *caller_bundle = PromiseGetBundle(fp->caller); VarRefQualify(ref, caller_bundle->ns, caller_bundle->name); } else { Log(LOG_LEVEL_WARNING, "Function '%s' was given an unqualified variable reference, " "and it was not called from a promise. No way to automatically qualify the reference '%s'.", fp->name, RlistScalarValue(finalargs)); VarRefDestroy(ref); return FnFailure(); } } DataType type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &type); Rlist *keys = NULL; if (type == CF_DATA_TYPE_CONTAINER) { if (JsonGetElementType(value) == JSON_ELEMENT_TYPE_CONTAINER) { if (JsonGetContainerType(value) == JSON_CONTAINER_TYPE_OBJECT) { JsonIterator iter = JsonIteratorInit(value); const char *key = NULL; while ((key = JsonIteratorNextKey(&iter))) { RlistAppendScalar(&keys, key); } } else { for (size_t i = 0; i < JsonLength(value); i++) { Rval key = (Rval) { StringFromLong(i), RVAL_TYPE_SCALAR }; RlistAppendRval(&keys, key); } } } } else { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, ref->ns, ref->scope, ref->lval); const Variable *var = NULL; while ((var = VariableTableIteratorNext(iter))) { if (ref->num_indices < var->ref->num_indices) { RlistAppendScalarIdemp(&keys, var->ref->indices[ref->num_indices]); } } VariableTableIteratorDestroy(iter); } VarRefDestroy(ref); if (RlistLen(keys) == 0) { RlistAppendScalarIdemp(&keys, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { keys, RVAL_TYPE_LIST } }; } /*********************************************************************/ static char* JsonPrimitiveToString(const JsonElement *el) { if (JsonGetElementType(el) != JSON_ELEMENT_TYPE_PRIMITIVE) { return NULL; } switch (JsonGetPrimitiveType(el)) { case JSON_PRIMITIVE_TYPE_BOOL: return xstrdup(JsonPrimitiveGetAsBool(el) ? "true" : "false"); break; case JSON_PRIMITIVE_TYPE_INTEGER: return StringFromLong(JsonPrimitiveGetAsInteger(el)); break; case JSON_PRIMITIVE_TYPE_REAL: return StringFromDouble(JsonPrimitiveGetAsReal(el)); break; case JSON_PRIMITIVE_TYPE_STRING: return xstrdup(JsonPrimitiveGetAsString(el)); break; case JSON_PRIMITIVE_TYPE_NULL: // redundant break; } return NULL; } static FnCallResult FnCallGetValues(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { VarRef *ref = VarRefParse(RlistScalarValue(finalargs)); if (!VarRefIsQualified(ref)) { if (fp->caller) { const Bundle *caller_bundle = PromiseGetBundle(fp->caller); VarRefQualify(ref, caller_bundle->ns, caller_bundle->name); } else { Log(LOG_LEVEL_WARNING, "Function '%s' was given an unqualified variable reference, " "and it was not called from a promise. No way to automatically qualify the reference '%s'.", fp->name, RlistScalarValue(finalargs)); VarRefDestroy(ref); return FnFailure(); } } DataType type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &type); Rlist *values = NULL; if (type == CF_DATA_TYPE_CONTAINER) { if (JsonGetElementType(value) == JSON_ELEMENT_TYPE_CONTAINER) { JsonIterator iter = JsonIteratorInit(value); const JsonElement *el = NULL; while ((el = JsonIteratorNextValue(&iter))) { char *value = JsonPrimitiveToString(el); if (NULL != value) { RlistAppendScalar(&values, value); free(value); } } } } else { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, ref->ns, ref->scope, ref->lval); Variable *var = NULL; while ((var = VariableTableIteratorNext(iter))) { if (var->ref->num_indices != 1) { continue; } switch (var->rval.type) { case RVAL_TYPE_SCALAR: RlistAppendScalarIdemp(&values, var->rval.item); break; case RVAL_TYPE_LIST: for (const Rlist *rp = var->rval.item; rp != NULL; rp = rp->next) { RlistAppendScalarIdemp(&values, RlistScalarValue(rp)); } break; default: break; } } VariableTableIteratorDestroy(iter); } VarRefDestroy(ref); if (RlistLen(values) == 0) { RlistAppendScalarIdemp(&values, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { values, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallGrep(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { return FilterInternal(ctx, fp, RlistScalarValue(finalargs), // regex RlistScalarValue(finalargs->next), // list identifier 1, // regex match = TRUE 0, // invert matches = FALSE LONG_MAX); // max results = max int } /*********************************************************************/ static FnCallResult FnCallSum(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { double sum = 0; const Rlist *input_list = GetListReferenceArgument(ctx, fp, RlistScalarValue(finalargs), NULL); if (!input_list) { return FnFailure(); } for (const Rlist *rp = input_list; rp; rp = rp->next) { double x; if (!DoubleFromString(RlistScalarValue(rp), &x)) { return FnFailure(); } else { sum += x; } } return FnReturnF("%lf", sum); } /*********************************************************************/ static FnCallResult FnCallProduct(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { double product = 1.0; const Rlist *input_list = GetListReferenceArgument(ctx, fp, RlistScalarValue(finalargs), NULL); if (!input_list) { return FnFailure(); } for (const Rlist *rp = input_list; rp; rp = rp->next) { double x; if (!DoubleFromString(RlistScalarValue(rp), &x)) { return FnFailure(); } else { product *= x; } } return FnReturnF("%lf", product); } /*********************************************************************/ static FnCallResult JoinRlist(const Rlist *input_list, const char *delimiter) { if (RlistIsNullList(input_list)) { return FnReturn(""); } bool more = false; Buffer *result = BufferNew(); for (const Rlist *rp = input_list; rp; rp = rp->next) { if (!more && strcmp(RlistScalarValue(rp), CF_NULL_VALUE) == 0) { continue; } BufferAppendString(result, RlistScalarValue(rp)); more = false; // skip all following cf_null values while (rp->next) { if (strcmp(RlistScalarValue(rp->next), CF_NULL_VALUE) == 0) { rp = rp->next; } else { more = true; break; } } if (more) { BufferAppendString(result, delimiter); } } return FnReturnBuffer(result); } static FnCallResult JoinContainer(const JsonElement *container, const char *delimiter) { if (JsonGetElementType(container) != JSON_ELEMENT_TYPE_CONTAINER) { return FnReturn(""); } JsonIterator iter = JsonIteratorInit(container); const JsonElement *e = JsonIteratorNextValueByType(&iter, JSON_ELEMENT_TYPE_PRIMITIVE, true); if (!e) { return FnReturn(""); } Buffer *result = BufferNew(); BufferAppendString(result, JsonPrimitiveGetAsString(e)); while ((e = JsonIteratorNextValueByType(&iter, JSON_ELEMENT_TYPE_PRIMITIVE, true))) { BufferAppendString(result, delimiter); BufferAppendString(result, JsonPrimitiveGetAsString(e)); } return FnReturnBuffer(result); } static FnCallResult FnCallJoin(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *delimiter = RlistScalarValue(finalargs); const char *name = RlistScalarValue(finalargs->next); DataType type = CF_DATA_TYPE_NONE; VarRef *ref = VarRefParse(name); const void *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_VERBOSE, "Function '%s', argument '%s' did not resolve to a variable", fp->name, name); return FnFailure(); } switch (DataTypeToRvalType(type)) { case RVAL_TYPE_LIST: return JoinRlist(value, delimiter); case RVAL_TYPE_CONTAINER: return JoinContainer(value, delimiter); default: Log(LOG_LEVEL_ERR, "Function '%s', argument '%s' resolved to unsupported datatype '%s'", fp->name, name, DataTypeToString(type)); return FnFailure(); } assert(false && "never reach"); } /*********************************************************************/ static FnCallResult FnCallGetFields(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { pcre *rx = CompileRegex(RlistScalarValue(finalargs)); if (!rx) { return FnFailure(); } const char *filename = RlistScalarValue(finalargs->next); const char *split = RlistScalarValue(finalargs->next->next); const char *array_lval = RlistScalarValue(finalargs->next->next->next); FILE *fin = safe_fopen(filename, "rt"); if (!fin) { Log(LOG_LEVEL_ERR, "File '%s' could not be read in getfields(). (fopen: %s)", filename, GetErrorStr()); pcre_free(rx); return FnFailure(); } size_t line_size = CF_BUFSIZE; char *line = xmalloc(CF_BUFSIZE); int line_count = 0; while (CfReadLine(&line, &line_size, fin) != -1) { if (!StringMatchFullWithPrecompiledRegex(rx, line)) { continue; } if (line_count == 0) { Rlist *newlist = RlistFromSplitRegex(line, split, 31, true); int vcount = 1; for (const Rlist *rp = newlist; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE]; snprintf(name, CF_MAXVARSIZE - 1, "%s[%d]", array_lval, vcount); VarRef *ref = VarRefParse(name); if (!VarRefIsQualified(ref)) { if (fp->caller) { const Bundle *caller_bundle = PromiseGetBundle(fp->caller); VarRefQualify(ref, caller_bundle->ns, caller_bundle->name); } else { Log(LOG_LEVEL_WARNING, "Function '%s' was given an unqualified variable reference, " "and it was not called from a promise. No way to automatically qualify the reference '%s'.", fp->name, RlistScalarValue(finalargs)); VarRefDestroy(ref); free(line); RlistDestroy(newlist); pcre_free(rx); return FnFailure(); } } EvalContextVariablePut(ctx, ref, RlistScalarValue(rp), CF_DATA_TYPE_STRING, "source=function,function=getfields"); VarRefDestroy(ref); Log(LOG_LEVEL_VERBOSE, "getfields: defining '%s' => '%s'", name, RlistScalarValue(rp)); vcount++; } RlistDestroy(newlist); } line_count++; } pcre_free(rx); free(line); if (!feof(fin)) { Log(LOG_LEVEL_ERR, "Unable to read data from file '%s'. (fgets: %s)", filename, GetErrorStr()); fclose(fin); return FnFailure(); } fclose(fin); return FnReturnF("%d", line_count); } /*********************************************************************/ static FnCallResult FnCallCountLinesMatching(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { pcre *rx = CompileRegex(RlistScalarValue(finalargs)); if (!rx) { return FnFailure(); } char *filename = RlistScalarValue(finalargs->next); FILE *fin = safe_fopen(filename, "rt"); if (!fin) { Log(LOG_LEVEL_VERBOSE, "File '%s' could not be read in countlinesmatching(). (fopen: %s)", filename, GetErrorStr()); pcre_free(rx); return FnReturn("0"); } int lcount = 0; { size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); while (CfReadLine(&line, &line_size, fin) != -1) { if (StringMatchFullWithPrecompiledRegex(rx, line)) { lcount++; Log(LOG_LEVEL_VERBOSE, "countlinesmatching: matched '%s'", line); continue; } } free(line); } pcre_free(rx); if (!feof(fin)) { Log(LOG_LEVEL_ERR, "Unable to read data from file '%s'. (fgets: %s)", filename, GetErrorStr()); fclose(fin); return FnFailure(); } fclose(fin); return FnReturnF("%d", lcount); } /*********************************************************************/ static FnCallResult FnCallLsDir(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char line[CF_BUFSIZE]; Dir *dirh = NULL; const struct dirent *dirp; Rlist *newlist = NULL; /* begin fn specific content */ char *dirname = RlistScalarValue(finalargs); char *regex = RlistScalarValue(finalargs->next); int includepath = BooleanFromString(RlistScalarValue(finalargs->next->next)); dirh = DirOpen(dirname); if (dirh == NULL) { Log(LOG_LEVEL_ERR, "Directory '%s' could not be accessed in lsdir(), (opendir: %s)", dirname, GetErrorStr()); RlistPrepend(&newlist, CF_NULL_VALUE, RVAL_TYPE_SCALAR); return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (strlen(regex) == 0 || StringMatchFull(regex, dirp->d_name)) { if (includepath) { snprintf(line, CF_BUFSIZE, "%s/%s", dirname, dirp->d_name); MapName(line); RlistPrepend(&newlist, line, RVAL_TYPE_SCALAR); } else { RlistPrepend(&newlist, dirp->d_name, RVAL_TYPE_SCALAR); } } } DirClose(dirh); if (newlist == NULL) { RlistPrepend(&newlist, CF_NULL_VALUE, RVAL_TYPE_SCALAR); } return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallMapArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { if (!fp->caller) { Log(LOG_LEVEL_ERR, "Function '%s' must be called from a promise", fp->name); return FnFailure(); } const char *arg_map = RlistScalarValue(finalargs); const char *arg_array = RlistScalarValue(finalargs->next); VariableTableIterator *iter; size_t selected_index = 0; { VarRef *ref = VarRefParse(arg_array); if (!VarRefIsQualified(ref)) { const Bundle *caller_bundle = PromiseGetBundle(fp->caller); VarRefQualify(ref, caller_bundle->ns, caller_bundle->name); } iter = EvalContextVariableTableIteratorNew(ctx, ref->ns, ref->scope, ref->lval); selected_index = ref->num_indices; VarRefDestroy(ref); } Rlist *returnlist = NULL; Variable *var; Buffer *expbuf = BufferNew(); while ((var = VariableTableIteratorNext(iter))) { if (var->ref->num_indices <= selected_index) { continue; } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "k", var->ref->indices[selected_index], CF_DATA_TYPE_STRING, "source=function,function=maparray"); switch (var->rval.type) { case RVAL_TYPE_SCALAR: { BufferClear(expbuf); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "v", var->rval.item, CF_DATA_TYPE_STRING, "source=function,function=maparray"); ExpandScalar(ctx, PromiseGetBundle(fp->caller)->ns, PromiseGetBundle(fp->caller)->name, arg_map, expbuf); if (strstr(BufferData(expbuf), "$(this.k)") || strstr(BufferData(expbuf), "${this.k}") || strstr(BufferData(expbuf), "$(this.v)") || strstr(BufferData(expbuf), "${this.v}")) { RlistDestroy(returnlist); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "k"); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "v"); BufferDestroy(expbuf); VariableTableIteratorDestroy(iter); return FnFailure(); } RlistAppendScalar(&returnlist, BufferData(expbuf)); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "v"); } break; case RVAL_TYPE_LIST: { for (const Rlist *rp = RvalRlistValue(var->rval); rp != NULL; rp = rp->next) { BufferClear(expbuf); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "v", RlistScalarValue(rp), CF_DATA_TYPE_STRING, "source=function,function=maparray"); ExpandScalar(ctx, PromiseGetBundle(fp->caller)->ns, PromiseGetBundle(fp->caller)->name, arg_map, expbuf); if (strstr(BufferData(expbuf), "$(this.k)") || strstr(BufferData(expbuf), "${this.k}") || strstr(BufferData(expbuf), "$(this.v)") || strstr(BufferData(expbuf), "${this.v}")) { RlistDestroy(returnlist); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "k"); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "v"); BufferDestroy(expbuf); VariableTableIteratorDestroy(iter); return FnFailure(); } RlistAppendScalarIdemp(&returnlist, BufferData(expbuf)); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "v"); } } break; default: break; } EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "k"); } BufferDestroy(expbuf); VariableTableIteratorDestroy(iter); if (returnlist == NULL) { RlistAppendScalarIdemp(&returnlist, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } static FnCallResult FnCallMapList(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *newlist = NULL; DataType retype; const char *arg_map = RlistScalarValue(finalargs); char *listvar = RlistScalarValue(finalargs->next); char naked[CF_MAXVARSIZE] = ""; if (IsVarList(listvar)) { GetNaked(naked, listvar); } else { strlcpy(naked, listvar, CF_MAXVARSIZE); } VarRef *ref = VarRefParse(naked); retype = CF_DATA_TYPE_NONE; const Rlist *list = EvalContextVariableGet(ctx, ref, &retype); if (!list) { VarRefDestroy(ref); return FnFailure(); } VarRefDestroy(ref); if (retype != CF_DATA_TYPE_STRING_LIST && retype != CF_DATA_TYPE_INT_LIST && retype != CF_DATA_TYPE_REAL_LIST) { return FnFailure(); } Buffer *expbuf = BufferNew(); for (const Rlist *rp = list; rp != NULL; rp = rp->next) { BufferClear(expbuf); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "this", RlistScalarValue(rp), CF_DATA_TYPE_STRING, "source=function,function=maplist"); ExpandScalar(ctx, NULL, "this", arg_map, expbuf); if (strstr(BufferData(expbuf), "$(this)") || strstr(BufferData(expbuf), "${this}")) { RlistDestroy(newlist); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "this"); BufferDestroy(expbuf); return FnFailure(); } RlistAppendScalar(&newlist, BufferData(expbuf)); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "this"); } BufferDestroy(expbuf); return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } static FnCallResult FnCallMergeData(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { if (RlistLen(args) == 0) { Log(LOG_LEVEL_ERR, "%s needs at least one argument, a reference to a container variable", fp->name); return FnFailure(); } for (const Rlist *arg = args; arg; arg = arg->next) { if (args->val.type != RVAL_TYPE_SCALAR) { Log(LOG_LEVEL_ERR, "%s: argument '%s' is not a variable reference", fp->name, RlistScalarValue(arg)); return FnFailure(); } } Seq *containers = SeqNew(10, &JsonDestroy); for (const Rlist *arg = args; arg; arg = arg->next) { VarRef *ref = ResolveAndQualifyVarName(fp, RlistScalarValue(arg)); if (!ref) { SeqDestroy(containers); return FnFailure(); } JsonElement *json = VarRefValueToJson(ctx, fp, ref, NULL, 0); VarRefDestroy(ref); if (!json) { SeqDestroy(containers); return FnFailure(); } SeqAppend(containers, json); } // end of args loop if (SeqLength(containers) == 1) { JsonElement *first = JsonCopy(SeqAt(containers, 0)); SeqDestroy(containers); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { first, RVAL_TYPE_CONTAINER } }; } else { JsonElement *first = SeqAt(containers, 0); JsonElement *second = SeqAt(containers, 1); JsonElement *result = JsonMerge(first, second); for (size_t i = 2; i < SeqLength(containers); i++) { JsonElement *cur = SeqAt(containers, i); JsonElement *tmp = JsonMerge(result, cur); JsonDestroy(result); result = tmp; } SeqDestroy(containers); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { result, RVAL_TYPE_CONTAINER } }; } assert(false); } JsonElement *DefaultTemplateData(const EvalContext *ctx) { JsonElement *hash = JsonObjectCreate(30); JsonElement *classes = JsonObjectCreate(50); JsonElement *bundles = JsonObjectCreate(50); JsonObjectAppendObject(hash, "classes", classes); JsonObjectAppendObject(hash, "vars", bundles); { ClassTableIterator *it = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(it))) { char *key = ClassRefToString(cls->ns, cls->name); JsonObjectAppendBool(classes, key, true); free(key); } ClassTableIteratorDestroy(it); } { ClassTableIterator *it = EvalContextClassTableIteratorNewLocal(ctx); Class *cls = NULL; while ((cls = ClassTableIteratorNext(it))) { char *key = ClassRefToString(cls->ns, cls->name); JsonObjectAppendBool(classes, key, true); free(key); } ClassTableIteratorDestroy(it); } { VariableTableIterator *it = EvalContextVariableTableIteratorNew(ctx, NULL, NULL, NULL); Variable *var = NULL; while ((var = VariableTableIteratorNext(it))) { // TODO: need to get a CallRef, this is bad char *scope_key = ClassRefToString(var->ref->ns, var->ref->scope); JsonElement *scope_obj = JsonObjectGetAsObject(bundles, scope_key); if (!scope_obj) { scope_obj = JsonObjectCreate(50); JsonObjectAppendObject(bundles, scope_key, scope_obj); } free(scope_key); char *lval_key = VarRefToString(var->ref, false); JsonObjectAppendElement(scope_obj, lval_key, RvalToJson(var->rval)); free(lval_key); } VariableTableIteratorDestroy(it); } Writer *w = StringWriter(); JsonWrite(w, hash, 0); Log(LOG_LEVEL_DEBUG, "Generated DefaultTemplateData '%s'", StringWriterData(w)); WriterClose(w); return hash; } static FnCallResult FnCallDatastate(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, ARG_UNUSED const Rlist *args) { JsonElement *state = DefaultTemplateData(ctx); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { state, RVAL_TYPE_CONTAINER } }; } static FnCallResult FnCallSelectServers(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *listvar = RlistScalarValue(finalargs); const char *port = RlistScalarValue(finalargs->next); const char *sendstring = RlistScalarValue(finalargs->next->next); const char *regex = RlistScalarValue(finalargs->next->next->next); ssize_t maxbytes = IntFromString(RlistScalarValue(finalargs->next->next->next->next)); char *array_lval = xstrdup(RlistScalarValue(finalargs->next->next->next->next->next)); if (!IsQualifiedVariable(array_lval)) { if (fp->caller) { VarRef *ref = VarRefParseFromBundle(array_lval, PromiseGetBundle(fp->caller)); free(array_lval); array_lval = VarRefToString(ref, true); VarRefDestroy(ref); } else { Log(LOG_LEVEL_ERR, "Function '%s' called with an unqualifed array reference '%s', " "and the reference could not be automatically qualified as the function was not called from a promise.", fp->name, array_lval); free(array_lval); return FnFailure(); } } char naked[CF_MAXVARSIZE] = ""; if (IsVarList(listvar)) { GetNaked(naked, listvar); } else { Log(LOG_LEVEL_VERBOSE, "Function selectservers was promised a list called '%s' but this was not found", listvar); return FnFailure(); } VarRef *ref = VarRefParse(naked); DataType value_type; const Rlist *hostnameip = EvalContextVariableGet(ctx, ref, &value_type); if (!hostnameip) { Log(LOG_LEVEL_VERBOSE, "Function selectservers was promised a list called '%s' but this was not found from context '%s.%s'", listvar, ref->scope, naked); VarRefDestroy(ref); free(array_lval); return FnFailure(); } VarRefDestroy(ref); if (DataTypeToRvalType(value_type) != RVAL_TYPE_LIST) { Log(LOG_LEVEL_VERBOSE, "Function selectservers was promised a list called '%s' but this variable is not a list", listvar); free(array_lval); return FnFailure(); } if (maxbytes < 0 || maxbytes > CF_BUFSIZE - 1) { Log(LOG_LEVEL_VERBOSE, "selectservers: invalid number of bytes %zd to read, defaulting to %d", maxbytes, CF_BUFSIZE - 1); maxbytes = CF_BUFSIZE - 1; } if (THIS_AGENT_TYPE != AGENT_TYPE_AGENT) { free(array_lval); return FnReturnF("%d", 0); } Policy *select_server_policy = PolicyNew(); { Bundle *bp = PolicyAppendBundle(select_server_policy, NamespaceDefault(), "select_server_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "select_server"); PromiseTypeAppendPromise(tp, "function", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } size_t count = 0; for (const Rlist *rp = hostnameip; rp != NULL; rp = rp->next) { const char *host = RlistScalarValue(rp); Log(LOG_LEVEL_DEBUG, "Want to read %zd bytes from %s port %s", maxbytes, host, port); char txtaddr[CF_MAX_IP_LEN] = ""; int sd = SocketConnect(host, port, CONNTIMEOUT, false, txtaddr, sizeof(txtaddr)); if (sd == -1) { continue; } if (strlen(sendstring) > 0) { if (SendSocketStream(sd, sendstring, strlen(sendstring)) != -1) { char recvbuf[CF_BUFSIZE]; ssize_t n_read = recv(sd, recvbuf, maxbytes, 0); if (n_read != -1) { /* maxbytes was checked earlier, but just make sure... */ assert(n_read < sizeof(recvbuf)); recvbuf[n_read] = '\0'; if (strlen(regex) == 0 || StringMatchFull(regex, recvbuf)) { Log(LOG_LEVEL_VERBOSE, "selectservers: Got matching reply from host %s address %s", host, txtaddr); char buffer[CF_MAXVARSIZE] = ""; snprintf(buffer, sizeof(buffer), "%s[%zu]", array_lval, count); VarRef *ref = VarRefParse(buffer); EvalContextVariablePut(ctx, ref, host, CF_DATA_TYPE_STRING, "source=function,function=selectservers"); VarRefDestroy(ref); count++; } } } } else /* If query is empty, all hosts are added */ { Log(LOG_LEVEL_VERBOSE, "selectservers: Got reply from host %s address %s", host, txtaddr); char buffer[CF_MAXVARSIZE] = ""; snprintf(buffer, sizeof(buffer), "%s[%zu]", array_lval, count); VarRef *ref = VarRefParse(buffer); EvalContextVariablePut(ctx, ref, host, CF_DATA_TYPE_STRING, "source=function,function=selectservers"); VarRefDestroy(ref); count++; } cf_closesocket(sd); } PolicyDestroy(select_server_policy); free(array_lval); Log(LOG_LEVEL_VERBOSE, "selectservers: found %zu servers", count); return FnReturnF("%zu", count); } static FnCallResult FnCallShuffle(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *seed_str = RlistScalarValue(finalargs->next); DataType list_dtype = CF_DATA_TYPE_NONE; const Rlist *list = GetListReferenceArgument(ctx, fp, RlistScalarValue(finalargs), &list_dtype); if (!list) { return FnFailure(); } if (list_dtype != CF_DATA_TYPE_STRING_LIST) { Log(LOG_LEVEL_ERR, "Function '%s' expected a variable that resolves to a string list, got '%s'", fp->name, DataTypeToString(list_dtype)); return FnFailure(); } Seq *seq = SeqNew(1000, NULL); for (const Rlist *rp = list; rp; rp = rp->next) { SeqAppend(seq, RlistScalarValue(rp)); } SeqShuffle(seq, StringHash(seed_str, 0, RAND_MAX)); Rlist *shuffled = NULL; for (size_t i = 0; i < SeqLength(seq); i++) { RlistPrepend(&shuffled, SeqAt(seq, i), RVAL_TYPE_SCALAR); } SeqDestroy(seq); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { shuffled, RVAL_TYPE_LIST } }; } static FnCallResult FnCallIsNewerThan(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct stat frombuf, tobuf; /* begin fn specific content */ if (stat(RlistScalarValue(finalargs), &frombuf) == -1) { return FnFailure(); } if (stat(RlistScalarValue(finalargs->next), &tobuf) == -1) { return FnFailure(); } return FnReturnContext(frombuf.st_mtime > tobuf.st_mtime); } /*********************************************************************/ static FnCallResult FnCallIsAccessedBefore(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct stat frombuf, tobuf; /* begin fn specific content */ if (stat(RlistScalarValue(finalargs), &frombuf) == -1) { return FnFailure(); } if (stat(RlistScalarValue(finalargs->next), &tobuf) == -1) { return FnFailure(); } return FnReturnContext(frombuf.st_atime < tobuf.st_atime); } /*********************************************************************/ static FnCallResult FnCallIsChangedBefore(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct stat frombuf, tobuf; /* begin fn specific content */ if (stat(RlistScalarValue(finalargs), &frombuf) == -1) { return FnFailure(); } else if (stat(RlistScalarValue(finalargs->next), &tobuf) == -1) { return FnFailure(); } return FnReturnContext(frombuf.st_ctime > tobuf.st_ctime); } /*********************************************************************/ static FnCallResult FnCallFileStat(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char *path = RlistScalarValue(finalargs); struct stat statbuf; /* begin fn specific content */ if (lstat(path, &statbuf) == -1) { if (!strcmp(fp->name, "filesize")) { return FnFailure(); } return FnReturnContext(false); } if (!strcmp(fp->name, "isexecutable")) { return FnReturnContext(IsExecutable(path)); } if (!strcmp(fp->name, "isdir")) { return FnReturnContext(S_ISDIR(statbuf.st_mode)); } if (!strcmp(fp->name, "islink")) { return FnReturnContext(S_ISLNK(statbuf.st_mode)); } if (!strcmp(fp->name, "isplain")) { return FnReturnContext(S_ISREG(statbuf.st_mode)); } if (!strcmp(fp->name, "fileexists")) { return FnReturnContext(true); } if (!strcmp(fp->name, "filesize")) { return FnReturnF("%jd", (uintmax_t) statbuf.st_size); } ProgrammingError("Unexpected function name in FnCallFileStat: %s", fp->name); } /*********************************************************************/ static FnCallResult FnCallFileStatDetails(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE], *path = RlistScalarValue(finalargs); char *detail = RlistScalarValue(finalargs->next); struct stat statbuf; buffer[0] = '\0'; /* begin fn specific content */ if (lstat(path, &statbuf) == -1) { return FnFailure(); } else { if (!strcmp(detail, "size")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_size); } else if (!strcmp(detail, "gid")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_gid); } else if (!strcmp(detail, "uid")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_uid); } else if (!strcmp(detail, "ino")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_ino); } else if (!strcmp(detail, "nlink")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_nlink); } else if (!strcmp(detail, "ctime")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_ctime); } else if (!strcmp(detail, "mtime")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_mtime); } else if (!strcmp(detail, "atime")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_atime); } else if (!strcmp(detail, "permstr")) { snprintf(buffer, CF_MAXVARSIZE, "%c%c%c%c%c%c%c%c%c%c", S_ISDIR(statbuf.st_mode) ? 'd' : '-', (statbuf.st_mode & S_IRUSR) ? 'r' : '-', (statbuf.st_mode & S_IWUSR) ? 'w' : '-', (statbuf.st_mode & S_IXUSR) ? 'x' : '-', (statbuf.st_mode & S_IRGRP) ? 'r' : '-', (statbuf.st_mode & S_IWGRP) ? 'w' : '-', (statbuf.st_mode & S_IXGRP) ? 'x' : '-', (statbuf.st_mode & S_IROTH) ? 'r' : '-', (statbuf.st_mode & S_IWOTH) ? 'w' : '-', (statbuf.st_mode & S_IXOTH) ? 'x' : '-'); } else if (!strcmp(detail, "permoct")) { snprintf(buffer, CF_MAXVARSIZE, "%jo", (uintmax_t) (statbuf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))); } else if (!strcmp(detail, "modeoct")) { snprintf(buffer, CF_MAXVARSIZE, "%jo", (uintmax_t) statbuf.st_mode); } else if (!strcmp(detail, "mode")) { snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_mode); } else if (!strcmp(detail, "type")) { switch (statbuf.st_mode & S_IFMT) { case S_IFBLK: snprintf(buffer, CF_MAXVARSIZE, "%s", "block device"); break; case S_IFCHR: snprintf(buffer, CF_MAXVARSIZE, "%s", "character device"); break; case S_IFDIR: snprintf(buffer, CF_MAXVARSIZE, "%s", "directory"); break; case S_IFIFO: snprintf(buffer, CF_MAXVARSIZE, "%s", "FIFO/pipe"); break; case S_IFLNK: snprintf(buffer, CF_MAXVARSIZE, "%s", "symlink"); break; case S_IFREG: snprintf(buffer, CF_MAXVARSIZE, "%s", "regular file"); break; case S_IFSOCK: snprintf(buffer, CF_MAXVARSIZE, "%s", "socket"); break; default: snprintf(buffer, CF_MAXVARSIZE, "%s", "unknown"); break; } } else if (!strcmp(detail, "dev_minor")) { #if !defined(__MINGW32__) snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) minor(statbuf.st_dev) ); #else snprintf(buffer, CF_MAXVARSIZE, "Not available on Windows"); #endif } else if (!strcmp(detail, "dev_major")) { #if !defined(__MINGW32__) snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) major(statbuf.st_dev) ); #else snprintf(buffer, CF_MAXVARSIZE, "Not available on Windows"); #endif } else if (!strcmp(detail, "devno")) { #if !defined(__MINGW32__) snprintf(buffer, CF_MAXVARSIZE, "%jd", (uintmax_t) statbuf.st_dev ); #else snprintf(buffer, CF_MAXVARSIZE, "%c:", statbuf.st_dev + 'A'); #endif } else if (!strcmp(detail, "dirname")) { snprintf(buffer, CF_MAXVARSIZE, "%s", path); ChopLastNode(buffer); MapName(buffer); } else if (!strcmp(detail, "basename")) { snprintf(buffer, CF_MAXVARSIZE, "%s", ReadLastNode(path)); } else if (!strcmp(detail, "linktarget") || !strcmp(detail, "linktarget_shallow")) { #if !defined(__MINGW32__) char path_buffer[CF_BUFSIZE]; bool recurse = !strcmp(detail, "linktarget"); int cycles = 0; int max_cycles = 30; // This allows for up to 31 levels of indirection. snprintf(path_buffer, CF_MAXVARSIZE, "%s", path); // Iterate while we're looking at a link. while (S_ISLNK(statbuf.st_mode)) { if (cycles > max_cycles) { Log(LOG_LEVEL_INFO, "%s bailing on link '%s' (original '%s') because %d cycles were chased", fp->name, path_buffer, path, cycles+1); break; } Log(LOG_LEVEL_VERBOSE, "%s resolving link '%s', cycle %d", fp->name, path_buffer, cycles+1); // Prep buffer because readlink() doesn't terminate the path. memset(buffer, 0, CF_BUFSIZE); /* Note we subtract 1 since we may need an extra char for NULL. */ if (readlink(path_buffer, buffer, CF_BUFSIZE-1) < 0) { // An error happened. Empty the buffer (don't keep the last target). Log(LOG_LEVEL_ERR, "%s could not readlink '%s'", fp->name, path_buffer); path_buffer[0] = '\0'; break; } Log(LOG_LEVEL_VERBOSE, "%s resolved link '%s' to %s", fp->name, path_buffer, buffer); // We got a good link target into buffer. Copy it to path_buffer. snprintf(path_buffer, CF_MAXVARSIZE, "%s", buffer); if (!recurse || lstat(path_buffer, &statbuf) == -1) { if (!recurse) { Log(LOG_LEVEL_VERBOSE, "%s bailing on link '%s' (original '%s') because linktarget_shallow was requested", fp->name, path_buffer, path); } else // error from lstat { Log(LOG_LEVEL_INFO, "%s bailing on link '%s' (original '%s') because it could not be read", fp->name, path_buffer, path); } break; } // At this point we haven't bailed, path_buffer has the link target cycles++; } // Get the path_buffer back into buffer. snprintf(buffer, CF_MAXVARSIZE, "%s", path_buffer); #else // Always return the original path on W32. snprintf(buffer, CF_MAXVARSIZE, "%s", path); #endif } } return FnReturn(buffer); } /*********************************************************************/ static FnCallResult FnCallFindfiles(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { Rlist *returnlist = NULL; int argcount = 0; char id[CF_BUFSIZE]; snprintf(id, CF_BUFSIZE, "built-in FnCall %s-arg", fp->name); /* We need to check all the arguments, ArgTemplate does not check varadic functions */ for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err)); } argcount++; } for (const Rlist *arg = finalargs; /* Start with arg set to finalargs. */ arg; /* We must have arg to proceed. */ arg = arg->next) /* arg steps forward every time. */ { const char *pattern = RlistScalarValue(arg); glob_t globbuf; int globflags = 0; // TODO: maybe add GLOB_BRACE later const char* r_candidates[] = { "*", "*/*", "*/*/*", "*/*/*/*", "*/*/*/*/*", "*/*/*/*/*/*" }; bool starstar = strstr(pattern, "**"); const char** candidates = starstar ? r_candidates : NULL; const int candidate_count = strstr(pattern, "**") ? 6 : 1; for (int pi = 0; pi < candidate_count; pi++) { char* expanded = starstar ? SearchAndReplace(pattern, "**", candidates[pi]) : (char*) pattern; #ifdef _WIN32 if (strchr(expanded, '\\')) { Log(LOG_LEVEL_VERBOSE, "Found backslash escape character in glob pattern '%s'. " "Was forward slash intended?", expanded); } #endif if (0 == glob(expanded, globflags, NULL, &globbuf)) { for (int i = 0; i < globbuf.gl_pathc; i++) { char* found = globbuf.gl_pathv[i]; char fname[CF_BUFSIZE]; // TODO: this truncates the filename and may be removed // if Rlist and the core are OK with that possibility strlcpy(fname, found, CF_BUFSIZE); Log(LOG_LEVEL_VERBOSE, "%s pattern '%s' found match '%s'", fp->name, pattern, fname); RlistAppendScalarIdemp(&returnlist, fname); } globfree(&globbuf); } if (starstar) { free(expanded); } } } // When no entries were found, mark the empty list if (NULL == returnlist) { RlistAppendScalar(&returnlist, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallFilter(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { return FilterInternal(ctx, fp, RlistScalarValue(finalargs), // regex or string RlistScalarValue(finalargs->next), // list identifier BooleanFromString(RlistScalarValue(finalargs->next->next)), // match as regex or exactly BooleanFromString(RlistScalarValue(finalargs->next->next->next)), // invert matches IntFromString(RlistScalarValue(finalargs->next->next->next->next))); // max results } /*********************************************************************/ static const Rlist *GetListReferenceArgument(const EvalContext *ctx, const const FnCall *fp, const char *lval_str, DataType *datatype_out) { VarRef *ref = VarRefParse(lval_str); DataType value_type = CF_DATA_TYPE_NONE; const Rlist *value = EvalContextVariableGet(ctx, ref, &value_type); if (!value) { Log(LOG_LEVEL_VERBOSE, "Could not resolve expected list variable '%s' in function '%s'", lval_str, fp->name); VarRefDestroy(ref); if (datatype_out) { *datatype_out = CF_DATA_TYPE_NONE; } return NULL; } VarRefDestroy(ref); if (DataTypeToRvalType(value_type) != RVAL_TYPE_LIST) { Log(LOG_LEVEL_ERR, "Function '%s' expected a list variable reference, got variable of type '%s'", fp->name, DataTypeToString(value_type)); if (datatype_out) { *datatype_out = CF_DATA_TYPE_NONE; } return NULL; } if (datatype_out) { *datatype_out = value_type; } return value; } /*********************************************************************/ static FnCallResult FilterInternal(EvalContext *ctx, const FnCall *fp, const char *regex, const char *name, bool do_regex, bool invert, long max) { pcre *rx = NULL; if (do_regex) { rx = CompileRegex(regex); if (!rx) { return FnFailure(); } } DataType type = CF_DATA_TYPE_NONE; VarRef *ref = VarRefParse(name); const void *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_VERBOSE, "Function '%s', argument '%s' did not resolve to a variable", fp->name, name); pcre_free(rx); return FnFailure(); } Rlist *returnlist = NULL; Rlist *input_list = NULL; JsonElement *json = NULL; switch (DataTypeToRvalType(type)) { case RVAL_TYPE_LIST: input_list = (Rlist *)value; if (NULL != input_list && NULL == input_list->next && input_list->val.type == RVAL_TYPE_SCALAR && strcmp(RlistScalarValue(input_list), CF_NULL_VALUE) == 0) // TODO: This... bullshit { input_list = NULL; } break; case RVAL_TYPE_CONTAINER: json = (JsonElement *)value; break; default: Log(LOG_LEVEL_ERR, "Function '%s', argument '%s' resolved to unsupported datatype '%s'", fp->name, name, DataTypeToString(type)); pcre_free(rx); return FnFailure(); } long match_count = 0; long total = 0; if (NULL != input_list) { for (const Rlist *rp = input_list; rp != NULL && match_count < max; rp = rp->next) { bool found; if (do_regex) { found = StringMatchFullWithPrecompiledRegex(rx, RlistScalarValue(rp)); } else { found = (0 == strcmp(regex, RlistScalarValue(rp))); } if (invert ? !found : found) { RlistAppendScalar(&returnlist, RlistScalarValue(rp)); match_count++; if (0 == strcmp(fp->name, "some")) { break; } } else if (0 == strcmp(fp->name, "every")) { total++; break; } total++; } } else if (NULL != json) { if (JsonGetElementType(json) == JSON_ELEMENT_TYPE_CONTAINER) { JsonIterator iter = JsonIteratorInit(json); const JsonElement *el = NULL; while ((el = JsonIteratorNextValue(&iter)) && match_count < max) { char *val = JsonPrimitiveToString(el); if (NULL != val) { bool found; if (do_regex) { found = StringMatchFullWithPrecompiledRegex(rx, val); } else { found = (0==strcmp(regex, val)); } if (invert ? !found : found) { RlistAppendScalar(&returnlist, val); match_count++; if (0 == strcmp(fp->name, "some")) { free(val); break; } } else if (0 == strcmp(fp->name, "every")) { total++; free(val); break; } total++; free(val); } } } } if (rx) { pcre_free(rx); } bool contextmode = 0; bool ret; if (0 == strcmp(fp->name, "every")) { contextmode = 1; ret = (match_count == total && total > 0); } else if (0 == strcmp(fp->name, "none")) { contextmode = 1; ret = (match_count == 0); } else if (0 == strcmp(fp->name, "some")) { contextmode = 1; ret = (match_count > 0); } else if (0 != strcmp(fp->name, "grep") && 0 != strcmp(fp->name, "filter")) { ProgrammingError("built-in FnCall %s: unhandled FilterInternal() contextmode", fp->name); } if (contextmode) { RlistDestroy(returnlist); return FnReturnContext(ret); } // else, return the list itself if (NULL == returnlist) { RlistAppendScalar(&returnlist, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallSublist(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *name = RlistScalarValue(finalargs); // list identifier bool head = 0 == strcmp(RlistScalarValue(finalargs->next), "head"); // heads or tails long max = IntFromString(RlistScalarValue(finalargs->next->next)); // max results Rlist *returnlist = NULL; const Rlist *input_list = GetListReferenceArgument(ctx, fp, name, NULL); if (!input_list) { return FnFailure(); } if (head) { long count = 0; for (const Rlist *rp = input_list; rp != NULL && count < max; rp = rp->next) { RlistAppendScalar(&returnlist, RlistScalarValue(rp)); count++; } } else if (max > 0) // tail mode { const Rlist *rp = input_list; int length = RlistLen((const Rlist *) rp); int offset = max >= length ? 0 : length-max; for (; rp != NULL && offset--; rp = rp->next) { /* skip to offset */ } for (; rp != NULL; rp = rp->next) { RlistAppendScalar(&returnlist, RlistScalarValue(rp)); } } if (NULL == returnlist) { RlistAppendScalar(&returnlist, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallSetop(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { bool difference = (0 == strcmp(fp->name, "difference")); const char *name_a = RlistScalarValue(finalargs); const char *name_b = RlistScalarValue(finalargs->next); const Rlist *input_list_a = GetListReferenceArgument(ctx, fp, name_a, NULL); if (!input_list_a) { return FnFailure(); } const Rlist *input_list_b = GetListReferenceArgument(ctx, fp, name_b, NULL); if (!input_list_b) { return FnFailure(); } Rlist *returnlist = NULL; RlistAppendScalar(&returnlist, CF_NULL_VALUE); StringSet *set_b = StringSetNew(); for (const Rlist *rp_b = input_list_b; rp_b != NULL; rp_b = rp_b->next) { StringSetAdd(set_b, xstrdup(RlistScalarValue(rp_b))); } for (const Rlist *rp_a = input_list_a; rp_a != NULL; rp_a = rp_a->next) { if (strcmp(RlistScalarValue(rp_a), CF_NULL_VALUE) == 0) { continue; } // Yes, this is an XOR. But it's more legible this way. if (difference && StringSetContains(set_b, RlistScalarValue(rp_a))) { continue; } if (!difference && !StringSetContains(set_b, RlistScalarValue(rp_a))) { continue; } RlistAppendScalarIdemp(&returnlist, RlistScalarValue(rp_a)); } StringSetDestroy(set_b); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { returnlist, RVAL_TYPE_LIST } }; } static FnCallResult FnCallLength(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *name = RlistScalarValue(finalargs); DataType type = CF_DATA_TYPE_NONE; VarRef *ref = VarRefParse(name); const void *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_VERBOSE, "Function '%s', argument '%s' did not resolve to a variable", fp->name, name); return FnFailure(); } switch (DataTypeToRvalType(type)) { case RVAL_TYPE_LIST: { int len = RlistLen(value); if (len == 1 && ((Rlist *)value)->val.type == RVAL_TYPE_SCALAR && strcmp(RlistScalarValue(value), CF_NULL_VALUE) == 0) // TODO: This... bullshit { return FnReturn("0"); } else { return FnReturnF("%d", len); } } case RVAL_TYPE_CONTAINER: return FnReturnF("%zd", JsonLength(value)); default: Log(LOG_LEVEL_ERR, "Function '%s', argument '%s' resolved to unsupported datatype '%s'", fp->name, name, DataTypeToString(type)); return FnFailure(); } } static FnCallResult FnCallFold(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *name = RlistScalarValue(finalargs); const char *sort_type = finalargs->next ? RlistScalarValue(finalargs->next) : NULL; size_t count = 0; double mean = 0; double M2 = 0; char* min = NULL; char* max = NULL; bool variance_mode = strcmp(fp->name, "variance") == 0; bool mean_mode = strcmp(fp->name, "mean") == 0; bool max_mode = strcmp(fp->name, "max") == 0; bool min_mode = strcmp(fp->name, "min") == 0; VarRef *ref = ResolveAndQualifyVarName(fp, name); if (!ref) { return FnFailure(); } JsonElement *json = VarRefValueToJson(ctx, fp, ref, NULL, 0); VarRefDestroy(ref); if (!json) { return FnFailure(); } JsonIterator iter = JsonIteratorInit(json); const JsonElement *el = NULL; while ((el = JsonIteratorNextValueByType(&iter, JSON_ELEMENT_TYPE_PRIMITIVE, true))) { char *value = JsonPrimitiveToString(el); if (NULL != value) { if (sort_type) { if (min_mode && (NULL == min || !GenericStringItemLess(sort_type, min, value))) { free(min); min = xstrdup(value); } if (max_mode && (NULL == max || GenericStringItemLess(sort_type, max, value))) { free(max); max = xstrdup(value); } } count++; if (mean_mode || variance_mode) { double x; if (1 != sscanf(value, "%lf", &x)) { x = 0; /* treat non-numeric entries as zero */ } // Welford's algorithm double delta = x - mean; mean += delta/count; M2 += delta * (x - mean); } free(value); } } JsonDestroy(json); if (mean_mode) { return count == 0 ? FnFailure() : FnReturnF("%lf", mean); } else if (variance_mode) { double variance = 0; if (count == 0) { return FnFailure(); } // if count is 1, variance is 0 if (count > 1) { variance = M2/(count - 1); } return FnReturnF("%lf", variance); } else if (max_mode) { return NULL == max ? FnFailure() : FnReturnNoCopy(max); } else if (min_mode) { return NULL == min ? FnFailure() : FnReturnNoCopy(min); } // else, we don't know this fp->name ProgrammingError("Unknown function call %s to FnCallFold", fp->name); return FnFailure(); } /*********************************************************************/ static FnCallResult FnCallUnique(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *name = RlistScalarValue(finalargs); Rlist *returnlist = NULL; const Rlist *input_list = GetListReferenceArgument(ctx, fp, name, NULL); if (!input_list) { return FnFailure(); } for (const Rlist *rp = input_list; rp != NULL; rp = rp->next) { RlistAppendScalarIdemp(&returnlist, RlistScalarValue(rp)); } if (NULL == returnlist) { RlistAppendScalar(&returnlist, CF_NULL_VALUE); } return (FnCallResult) { FNCALL_SUCCESS, { returnlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ /* This function has been removed from the function list for now */ /*********************************************************************/ #ifdef SUPPORT_FNCALL_DATATYPE static FnCallResult FnCallDatatype(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char* const varname = RlistScalarValue(finalargs); VarRef* const ref = VarRefParse(varname); DataType type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); Writer* const typestring = StringWriter(); if (type == CF_DATA_TYPE_CONTAINER) { const JsonElement* const jelement = value; if (JsonGetElementType(jelement) == JSON_ELEMENT_TYPE_CONTAINER) { switch (JsonGetContainerType(jelement)) { case JSON_CONTAINER_TYPE_OBJECT: WriterWrite(typestring, "json_object"); break; case JSON_CONTAINER_TYPE_ARRAY: WriterWrite(typestring, "json_array"); break; } } else if (JsonGetElementType(jelement) == JSON_ELEMENT_TYPE_PRIMITIVE) { switch (JsonGetPrimitiveType(jelement)) { case JSON_PRIMITIVE_TYPE_STRING: WriterWrite(typestring, "json_string"); break; case JSON_PRIMITIVE_TYPE_INTEGER: WriterWrite(typestring, "json_integer"); break; case JSON_PRIMITIVE_TYPE_REAL: WriterWrite(typestring, "json_real"); break; case JSON_PRIMITIVE_TYPE_BOOL: WriterWrite(typestring, "json_bool"); break; case JSON_PRIMITIVE_TYPE_NULL: WriterWrite(typestring, "json_null"); break; } } } else { Log(LOG_LEVEL_VERBOSE, "%s: variable '%s' is not a data container", fp->name, varname); return FnFailure(); } return (FnCallResult) { FNCALL_SUCCESS, { StringWriterClose(typestring), RVAL_TYPE_SCALAR } }; } #endif /* unused code */ /*********************************************************************/ static FnCallResult FnCallNth(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char* const varname = RlistScalarValue(finalargs); const char* const key = RlistScalarValue(finalargs->next); VarRef *ref = VarRefParse(varname); DataType type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); if (type == CF_DATA_TYPE_CONTAINER) { Rlist *return_list = NULL; const char *jstring = NULL; if (JsonGetElementType(value) == JSON_ELEMENT_TYPE_CONTAINER) { JsonElement* jholder = (JsonElement*) value; JsonContainerType ct = JsonGetContainerType(value); JsonElement* jelement = NULL; if (JSON_CONTAINER_TYPE_OBJECT == ct) { jelement = JsonObjectGet(jholder, key); } else if (JSON_CONTAINER_TYPE_ARRAY == ct) { long index = IntFromString(key); if (index >= 0 && index < JsonLength(value)) { jelement = JsonAt(jholder, index); } } else { ProgrammingError("JSON Container is neither array nor object but type %d", (int) ct); } if (NULL != jelement && JsonGetElementType(jelement) == JSON_ELEMENT_TYPE_PRIMITIVE) { jstring = JsonPrimitiveGetAsString(jelement); } } if (NULL != jstring) { Log(LOG_LEVEL_DEBUG, "%s: from data container %s, got JSON data '%s'", fp->name, varname, jstring); RlistAppendScalar(&return_list, jstring); } if (!return_list) { return FnFailure(); } FnCallResult result = FnReturn(RlistScalarValue(return_list)); RlistDestroy(return_list); return result; } else { const Rlist *input_list = GetListReferenceArgument(ctx, fp, varname, NULL); if (!input_list) { return FnFailure(); } const Rlist *return_list = NULL; long index = IntFromString(key); for (return_list = input_list; return_list && index--; return_list = return_list->next); if (!return_list) { return FnFailure(); } return FnReturn(RlistScalarValue(return_list)); } } /*********************************************************************/ static FnCallResult FnCallEverySomeNone(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { return FilterInternal(ctx, fp, RlistScalarValue(finalargs), // regex or string RlistScalarValue(finalargs->next), // list identifier 1, 0, LONG_MAX); } static FnCallResult FnCallSort(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *sort_type = RlistScalarValue(finalargs->next); // list identifier DataType list_var_dtype = CF_DATA_TYPE_NONE; const Rlist *input_list = GetListReferenceArgument(ctx, fp, RlistScalarValue(finalargs), &list_var_dtype); if (!input_list) { return FnFailure(); } if (list_var_dtype != CF_DATA_TYPE_STRING_LIST) { return FnFailure(); } Rlist *sorted; if (strcmp(sort_type, "int") == 0) { sorted = IntSortRListNames(RlistCopy(input_list)); } else if (strcmp(sort_type, "real") == 0) { sorted = RealSortRListNames(RlistCopy(input_list)); } else if (strcmp(sort_type, "IP") == 0 || strcmp(sort_type, "ip") == 0) { sorted = IPSortRListNames(RlistCopy(input_list)); } else if (strcmp(sort_type, "MAC") == 0 || strcmp(sort_type, "mac") == 0) { sorted = MACSortRListNames(RlistCopy(input_list)); } else // "lex" { sorted = AlphaSortRListNames(RlistCopy(input_list)); } return (FnCallResult) { FNCALL_SUCCESS, (Rval) { sorted, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallFormat(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char id[CF_BUFSIZE]; snprintf(id, CF_BUFSIZE, "built-in FnCall %s-arg", fp->name); /* We need to check all the arguments, ArgTemplate does not check varadic functions */ for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err)); } } /* begin fn specific content */ if (!finalargs) { return FnFailure(); } char *format = RlistScalarValue(finalargs); if (!format) { return FnFailure(); } const Rlist *rp = finalargs->next; char *check = strchr(format, '%'); char check_buffer[CF_BUFSIZE]; Buffer *buf = BufferNew(); if (check) { BufferAppend(buf, format, (check - format)); Seq *s = NULL; while (check && (s = StringMatchCaptures("^(%%|%[^diouxXeEfFgGaAcsCSpnm%]*?[diouxXeEfFgGaAcsCSpnm])([^%]*)(.*)$", check))) { { if (SeqLength(s) >= 2) { const char *format_piece = SeqAt(s, 1); bool percent = (0 == strncmp(format_piece, "%%", 2)); char *data = NULL; if (percent) { } else if (rp) { data = RlistScalarValue(rp); rp = rp->next; } else // not %% and no data { Log(LOG_LEVEL_ERR, "format() didn't have enough parameters"); BufferDestroy(buf); SeqDestroy(s); return FnFailure(); } char piece[CF_BUFSIZE]; memset(piece, 0, CF_BUFSIZE); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: processing format piece = '%s' with data '%s'", format_piece, percent ? "%" : data); char bad_modifiers[] = "hLqjzt"; for (int b = 0; b < strlen(bad_modifiers); b++) { if (NULL != strchr(format_piece, bad_modifiers[b])) { Log(LOG_LEVEL_ERR, "format() does not allow modifier character '%c' in format specifier '%s'.", bad_modifiers[b], format_piece); BufferDestroy(buf); SeqDestroy(s); return FnFailure(); } } if (strrchr(format_piece, 'd') || strrchr(format_piece, 'o') || strrchr(format_piece, 'x')) { long x = 0; sscanf(data, "%ld%s", &x, piece); // we don't care about the remainder and will overwrite it snprintf(piece, CF_BUFSIZE, format_piece, x); BufferAppend(buf, piece, strlen(piece)); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending int format piece = '%s' with data '%s'", format_piece, data); } else if (percent) { BufferAppend(buf, "%", 1); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending int format piece = '%s' with data '%s'", format_piece, data); } else if (strrchr(format_piece, 'f')) { double x = 0; sscanf(data, "%lf%s", &x, piece); // we don't care about the remainder and will overwrite it snprintf(piece, CF_BUFSIZE, format_piece, x); BufferAppend(buf, piece, strlen(piece)); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending float format piece = '%s' with data '%s'", format_piece, data); } else if (strrchr(format_piece, 's')) { snprintf(piece, CF_BUFSIZE, format_piece, data); BufferAppend(buf, piece, strlen(piece)); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending string format piece = '%s' with data '%s'", format_piece, data); } else if (strrchr(format_piece, 'S')) { char *found_format_spec = NULL; char format_rewrite[CF_BUFSIZE]; strlcpy(format_rewrite, format_piece, CF_BUFSIZE); found_format_spec = strrchr(format_rewrite, 'S'); if (found_format_spec) { *found_format_spec = 's'; } else { ProgrammingError("Couldn't find the expected S format spec in %s", format_piece); } const char* const varname = data; VarRef *ref = VarRefParse(varname); DataType type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); if (type == CF_DATA_TYPE_CONTAINER) { Writer *w = StringWriter(); JsonWriteCompact(w, value); snprintf(piece, CF_BUFSIZE, format_rewrite, StringWriterData(w)); WriterClose(w); BufferAppend(buf, piece, strlen(piece)); } else // it might be a list reference { const Rlist *list = GetListReferenceArgument(ctx, fp, varname, NULL); if (NULL != list) { Writer *w = StringWriter(); WriterWrite(w, "{ "); for (const Rlist *rp = list; rp; rp = rp->next) { char *escaped = EscapeCharCopy(RlistScalarValue(rp), '"', '\\'); if (0 == strcmp(escaped, CF_NULL_VALUE)) { WriterWrite(w, "--empty-list--"); } else { WriterWriteF(w, "\"%s\"", escaped); } free(escaped); if (NULL != rp && NULL != rp->next) { WriterWrite(w, ", "); } } WriterWrite(w, " }"); snprintf(piece, CF_BUFSIZE, format_rewrite, StringWriterData(w)); WriterClose(w); BufferAppend(buf, piece, strlen(piece)); } else // whatever this is, it's not a list reference or a data container { Log(LOG_LEVEL_VERBOSE, "format() with %%S specifier needs a data container or a list instead of '%s'.", varname); BufferDestroy(buf); SeqDestroy(s); return FnFailure(); } } } else { char error[] = "(unhandled format)"; BufferAppend(buf, error, strlen(error)); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: error appending unhandled format piece = '%s' with data '%s'", format_piece, data); } } else { check = NULL; } } { if (SeqLength(s) >= 3) { const char* static_piece = SeqAt(s, 2); BufferAppend(buf, static_piece, strlen(static_piece)); // CfOut(OUTPUT_LEVEL_INFORM, "", "format: appending static piece = '%s'", static_piece); } else { check = NULL; } } { if (SeqLength(s) >= 4) { strlcpy(check_buffer, SeqAt(s, 3), CF_BUFSIZE); check = check_buffer; } else { check = NULL; } } SeqDestroy(s); } } else { BufferAppend(buf, format, strlen(format)); } char *result = xstrdup(BufferData(buf)); BufferDestroy(buf); return (FnCallResult) { FNCALL_SUCCESS, { result, RVAL_TYPE_SCALAR } }; } /*********************************************************************/ static FnCallResult FnCallIPRange(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char *range = RlistScalarValue(finalargs); Item *ip; if (!FuzzyMatchParse(range)) { return FnFailure(); } for (ip = EvalContextGetIpAddresses(ctx); ip != NULL; ip = ip->next) { if (FuzzySetMatch(range, VIPADDRESS) == 0) { return FnReturnContext(true); } else { if (FuzzySetMatch(range, ip->name) == 0) { return FnReturnContext(true); } } } return FnReturnContext(false); } /*********************************************************************/ static FnCallResult FnCallHostRange(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; buffer[0] = '\0'; /* begin fn specific content */ char *prefix = RlistScalarValue(finalargs); char *range = RlistScalarValue(finalargs->next); strcpy(buffer, "!any"); if (!FuzzyHostParse(range)) { return FnFailure(); } return FnReturnContext(FuzzyHostMatch(prefix, range, VUQNAME) == 0); } /*********************************************************************/ FnCallResult FnCallHostInNetgroup(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char *host, *user, *domain; setnetgrent(RlistScalarValue(finalargs)); while (getnetgrent(&host, &user, &domain)) { if (host == NULL) { Log(LOG_LEVEL_VERBOSE, "Matched '%s' in netgroup '%s'", VFQNAME, RlistScalarValue(finalargs)); endnetgrent(); return FnReturnContext(true); } if (strcmp(host, VFQNAME) == 0 || strcmp(host, VUQNAME) == 0) { Log(LOG_LEVEL_VERBOSE, "Matched '%s' in netgroup '%s'", host, RlistScalarValue(finalargs)); endnetgrent(); return FnReturnContext(true); } } endnetgrent(); return FnReturnContext(false); } /*********************************************************************/ static FnCallResult FnCallIsVariable(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *lval = RlistScalarValue(finalargs); bool found = false; if (!lval) { found = false; } else { VarRef *ref = VarRefParse(lval); found = EvalContextVariableGet(ctx, ref, NULL) != NULL; VarRefDestroy(ref); } return FnReturnContext(found); } /*********************************************************************/ static FnCallResult FnCallStrCmp(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { return FnReturnContext(strcmp(RlistScalarValue(finalargs), RlistScalarValue(finalargs->next)) == 0); } /*********************************************************************/ static FnCallResult FnCallTranslatePath(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[MAX_FILENAME]; snprintf(buffer, sizeof(buffer), "%s", RlistScalarValue(finalargs)); MapName(buffer); return FnReturn(buffer); } /*********************************************************************/ #if defined(__MINGW32__) static FnCallResult FnCallRegistryValue(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE] = ""; if (GetRegistryValue(RlistScalarValue(finalargs), RlistScalarValue(finalargs->next), buffer, sizeof(buffer))) { return FnReturn(buffer); } else { return FnFailure(); } return FnFailure(); } #else /* !__MINGW32__ */ static FnCallResult FnCallRegistryValue(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, ARG_UNUSED const Rlist *finalargs) { return FnFailure(); } #endif /* !__MINGW32__ */ /*********************************************************************/ static FnCallResult FnCallRemoteScalar(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; buffer[0] = '\0'; /* begin fn specific content */ char *handle = RlistScalarValue(finalargs); char *server = RlistScalarValue(finalargs->next); int encrypted = BooleanFromString(RlistScalarValue(finalargs->next->next)); if (strcmp(server, "localhost") == 0) { /* The only reason for this is testing... */ server = "127.0.0.1"; } if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON) { return FnReturn(""); } else { GetRemoteScalar(ctx, "VAR", handle, server, encrypted, buffer); if (strncmp(buffer, "BAD:", 4) == 0) { if (!RetrieveUnreliableValue("remotescalar", handle, buffer)) { // This function should never fail buffer[0] = '\0'; } } else { CacheUnreliableValue("remotescalar", handle, buffer); } return FnReturn(buffer); } } /*********************************************************************/ static FnCallResult FnCallHubKnowledge(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; buffer[0] = '\0'; char *handle = RlistScalarValue(finalargs); if (THIS_AGENT_TYPE != AGENT_TYPE_AGENT) { return FnReturn(""); } else { Log(LOG_LEVEL_VERBOSE, "Accessing hub knowledge base for '%s'", handle); GetRemoteScalar(ctx, "VAR", handle, POLICY_SERVER, true, buffer); // This should always be successful - and this one doesn't cache if (strncmp(buffer, "BAD:", 4) == 0) { return FnReturn("0"); } return FnReturn(buffer); } } /*********************************************************************/ static FnCallResult FnCallRemoteClassesMatching(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *rp, *classlist; char buffer[CF_BUFSIZE], class_name[CF_MAXVARSIZE]; buffer[0] = '\0'; /* begin fn specific content */ char *regex = RlistScalarValue(finalargs); char *server = RlistScalarValue(finalargs->next); int encrypted = BooleanFromString(RlistScalarValue(finalargs->next->next)); char *prefix = RlistScalarValue(finalargs->next->next->next); if (strcmp(server, "localhost") == 0) { /* The only reason for this is testing... */ server = "127.0.0.1"; } if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON) { return FnReturn("remote_classes"); } else { GetRemoteScalar(ctx, "CONTEXT", regex, server, encrypted, buffer); if (strncmp(buffer, "BAD:", 4) == 0) { return FnFailure(); } if ((classlist = RlistFromSplitString(buffer, ','))) { for (rp = classlist; rp != NULL; rp = rp->next) { snprintf(class_name, CF_MAXVARSIZE - 1, "%s_%s", prefix, RlistScalarValue(rp)); EvalContextClassPutSoft(ctx, class_name, CONTEXT_SCOPE_BUNDLE, "source=function,function=remoteclassesmatching"); } RlistDestroy(classlist); } return FnReturnContext(true); } } /*********************************************************************/ static FnCallResult FnCallPeers(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *rp, *pruned; char *split = "\n"; char *file_buffer = NULL; int i, found, maxent = 100000, maxsize = 100000; /* begin fn specific content */ char *filename = RlistScalarValue(finalargs); char *comment = RlistScalarValue(finalargs->next); int groupsize = IntFromString(RlistScalarValue(finalargs->next->next)); if (2 > groupsize) { Log(LOG_LEVEL_WARNING, "Function %s: called with a nonsensical group size of %d, failing", fp->name, groupsize); return FnFailure(); } file_buffer = (char *) CfReadFile(filename, maxsize); if (file_buffer == NULL) { return FnFailure(); } file_buffer = StripPatterns(file_buffer, comment, filename); Rlist *const newlist = file_buffer ? RlistFromSplitRegex(file_buffer, split, maxent, true) : NULL; /* Slice up the list and discard everything except our slice */ i = 0; found = false; pruned = NULL; for (rp = newlist; rp != NULL; rp = rp->next) { char s[CF_MAXVARSIZE]; if (EmptyString(RlistScalarValue(rp))) { continue; } strlcpy(s, RlistScalarValue(rp), CF_MAXVARSIZE); if (strcmp(s, VFQNAME) == 0 || strcmp(s, VUQNAME) == 0) { found = true; } else { RlistPrepend(&pruned, s, RVAL_TYPE_SCALAR); } if (i++ % groupsize == groupsize - 1) { if (found) { break; } else { RlistDestroy(pruned); pruned = NULL; } } } RlistDestroy(newlist); free(file_buffer); // OK if it's NULL if (pruned && found) { RlistReverse(&pruned); return (FnCallResult) { FNCALL_SUCCESS, { pruned, RVAL_TYPE_LIST } }; } RlistDestroy(pruned); pruned = NULL; RlistPrepend(&pruned, CF_NULL_VALUE, RVAL_TYPE_SCALAR); return (FnCallResult) { FNCALL_SUCCESS, { pruned, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallPeerLeader(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *rp; char *split = "\n"; char *file_buffer = NULL, buffer[CF_MAXVARSIZE]; int i, found, maxent = 100000, maxsize = 100000; buffer[0] = '\0'; /* begin fn specific content */ char *filename = RlistScalarValue(finalargs); char *comment = RlistScalarValue(finalargs->next); int groupsize = IntFromString(RlistScalarValue(finalargs->next->next)); if (2 > groupsize) { Log(LOG_LEVEL_WARNING, "Function %s: called with a nonsensical group size of %d, failing", fp->name, groupsize); return FnFailure(); } file_buffer = (char *) CfReadFile(filename, maxsize); if (file_buffer == NULL) { return FnFailure(); } file_buffer = StripPatterns(file_buffer, comment, filename); Rlist *const newlist = file_buffer ? RlistFromSplitRegex(file_buffer, split, maxent, true) : NULL; /* Slice up the list and discard everything except our slice */ i = 0; found = false; buffer[0] = '\0'; for (rp = newlist; rp != NULL; rp = rp->next) { if (EmptyString(RlistScalarValue(rp))) { continue; } char s[CF_MAXVARSIZE]; strlcpy(s, RlistScalarValue(rp), CF_MAXVARSIZE); const bool this_host = (strcmp(s, VFQNAME) == 0 || strcmp(s, VUQNAME) == 0); if (i % groupsize == 0) { if (this_host) { strlcpy(buffer, "localhost", CF_MAXVARSIZE); } else { strlcpy(buffer, s, CF_MAXVARSIZE); } } if (this_host) { found = true; break; } i++; } RlistDestroy(newlist); free(file_buffer); if (found) { return FnReturn(buffer); } return FnFailure(); } /*********************************************************************/ static FnCallResult FnCallPeerLeaders(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *rp, *pruned; char *split = "\n"; char *file_buffer = NULL; int i, maxent = 100000, maxsize = 100000; /* begin fn specific content */ char *filename = RlistScalarValue(finalargs); char *comment = RlistScalarValue(finalargs->next); int groupsize = IntFromString(RlistScalarValue(finalargs->next->next)); if (2 > groupsize) { Log(LOG_LEVEL_WARNING, "Function %s: called with a nonsensical group size of %d, failing", fp->name, groupsize); return FnFailure(); } file_buffer = (char *) CfReadFile(filename, maxsize); if (file_buffer == NULL) { return FnFailure(); } file_buffer = StripPatterns(file_buffer, comment, filename); Rlist *const newlist = file_buffer ? RlistFromSplitRegex(file_buffer, split, maxent, true) : NULL; /* Slice up the list and discard everything except our slice */ i = 0; pruned = NULL; for (rp = newlist; rp != NULL; rp = rp->next) { char s[CF_MAXVARSIZE]; if (EmptyString(RlistScalarValue(rp))) { continue; } strlcpy(s, RlistScalarValue(rp), CF_MAXVARSIZE); if (i % groupsize == 0) { if (strcmp(s, VFQNAME) == 0 || strcmp(s, VUQNAME) == 0) { RlistPrepend(&pruned, "localhost", RVAL_TYPE_SCALAR); } else { RlistPrepend(&pruned, s, RVAL_TYPE_SCALAR); } } i++; } RlistDestroy(newlist); free(file_buffer); if (NULL == pruned) { RlistPrepend(&pruned, CF_NULL_VALUE, RVAL_TYPE_SCALAR); } RlistReverse(&pruned); return (FnCallResult) { FNCALL_SUCCESS, { pruned, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallRegCmp(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; buffer[0] = '\0'; /* begin fn specific content */ strcpy(buffer, CF_ANYCLASS); char *argv0 = RlistScalarValue(finalargs); char *argv1 = RlistScalarValue(finalargs->next); return FnReturnContext(StringMatchFull(argv0, argv1)); } /*********************************************************************/ static FnCallResult FnCallRegExtract(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; buffer[0] = '\0'; /* begin fn specific content */ strcpy(buffer, CF_ANYCLASS); const char *regex = RlistScalarValue(finalargs); const char *data = RlistScalarValue(finalargs->next); char *arrayname = xstrdup(RlistScalarValue(finalargs->next->next)); if (!IsQualifiedVariable(arrayname)) { if (fp->caller) { VarRef *ref = VarRefParseFromBundle(arrayname, PromiseGetBundle(fp->caller)); free(arrayname); arrayname = VarRefToString(ref, true); VarRefDestroy(ref); } else { Log(LOG_LEVEL_ERR, "Function '%s' called with an unqualifed array reference '%s', " "and the reference could not be automatically qualified as the function was not called from a promise.", fp->name, arrayname); free(arrayname); return FnFailure(); } } Seq *s = StringMatchCaptures(regex, data); if (!s || SeqLength(s) == 0) { SeqDestroy(s); free(arrayname); return FnReturnContext(false); } for (int i = 0; i < SeqLength(s); ++i) { char var[CF_MAXVARSIZE] = ""; snprintf(var, CF_MAXVARSIZE - 1, "%s[%d]", arrayname, i); VarRef *new_ref = VarRefParse(var); EvalContextVariablePut(ctx, new_ref, SeqAt(s, i), CF_DATA_TYPE_STRING, "source=function,function=regextract"); VarRefDestroy(new_ref); } free(arrayname); SeqDestroy(s); return FnReturnContext(true); } /*********************************************************************/ static FnCallResult FnCallRegLine(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { pcre *rx = CompileRegex(RlistScalarValue(finalargs)); if (!rx) { return FnFailure(); } const char *arg_filename = RlistScalarValue(finalargs->next); FILE *fin = safe_fopen(arg_filename, "rt"); if (!fin) { pcre_free(rx); return FnReturnContext(false); } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); while (CfReadLine(&line, &line_size, fin) != -1) { if (StringMatchFullWithPrecompiledRegex(rx, line)) { free(line); fclose(fin); pcre_free(rx); return FnReturnContext(true); } } pcre_free(rx); free(line); if (!feof(fin)) { Log(LOG_LEVEL_ERR, "In function '%s', error reading from file. (getline: %s)", fp->name, GetErrorStr()); } fclose(fin); return FnReturnContext(false); } /*********************************************************************/ static FnCallResult FnCallIsLessGreaterThan(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char *argv0 = RlistScalarValue(finalargs); char *argv1 = RlistScalarValue(finalargs->next); if (IsRealNumber(argv0) && IsRealNumber(argv1)) { double a = 0; if (!DoubleFromString(argv0, &a)) { return FnFailure(); } double b = 0; if (!DoubleFromString(argv1, &b)) { return FnFailure(); } if (!strcmp(fp->name, "isgreaterthan")) { return FnReturnContext(a > b); } else { return FnReturnContext(a < b); } } if (!strcmp(fp->name, "isgreaterthan")) { return FnReturnContext(strcmp(argv0, argv1) > 0); } else { return FnReturnContext(strcmp(argv0, argv1) < 0); } } /*********************************************************************/ static FnCallResult FnCallIRange(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { long tmp; /* begin fn specific content */ long from = IntFromString(RlistScalarValue(finalargs)); long to = IntFromString(RlistScalarValue(finalargs->next)); if (from == CF_NOINT || to == CF_NOINT) { return FnFailure(); } if (from > to) { tmp = to; to = from; from = tmp; } return FnReturnF("%ld,%ld", from, to); } /*********************************************************************/ static FnCallResult FnCallRRange(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { int tmp; /* begin fn specific content */ double from = 0; if (!DoubleFromString(RlistScalarValue(finalargs), &from)) { Log(LOG_LEVEL_ERR, "Function rrange, error reading assumed real value '%s' => %lf", RlistScalarValue(finalargs), from); return FnFailure(); } double to = 0; if (!DoubleFromString(RlistScalarValue(finalargs), &to)) { Log(LOG_LEVEL_ERR, "Function rrange, error reading assumed real value '%s' => %lf", RlistScalarValue(finalargs->next), from); return FnFailure(); } if (from > to) { tmp = to; to = from; from = tmp; } return FnReturnF("%lf,%lf", from, to); } static FnCallResult FnCallReverse(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { DataType list_dtype = CF_DATA_TYPE_NONE; const Rlist *input_list = GetListReferenceArgument(ctx, fp, RlistScalarValue(finalargs), &list_dtype); if (!input_list) { return FnFailure(); } if (list_dtype != CF_DATA_TYPE_STRING_LIST) { Log(LOG_LEVEL_ERR, "Function '%s' expected a variable that resolves to a string list, got '%s'", fp->name, DataTypeToString(list_dtype)); return FnFailure(); } Rlist *copy = RlistCopy(input_list); RlistReverse(©); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { copy, RVAL_TYPE_LIST } }; } /* Convert y/m/d/h/m/s 6-tuple */ static struct tm FnArgsToTm(const Rlist *rp) { struct tm ret = { .tm_isdst = -1 }; /* .tm_year stores year - 1900 */ ret.tm_year = IntFromString(RlistScalarValue(rp)) - 1900; rp = rp->next; /* .tm_mon counts from Jan = 0 to Dec = 11 */ ret.tm_mon = IntFromString(RlistScalarValue(rp)); rp = rp->next; /* .tm_mday is day of month, 1 to 31, but we use 0 through 30 (for now) */ ret.tm_mday = IntFromString(RlistScalarValue(rp)) + 1; rp = rp->next; ret.tm_hour = IntFromString(RlistScalarValue(rp)); rp = rp->next; ret.tm_min = IntFromString(RlistScalarValue(rp)); rp = rp->next; ret.tm_sec = IntFromString(RlistScalarValue(rp)); return ret; } static FnCallResult FnCallOn(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; struct tm tmv = FnArgsToTm(finalargs); time_t cftime = mktime(&tmv); if (cftime == -1) { Log(LOG_LEVEL_INFO, "Illegal time value"); } snprintf(buffer, CF_BUFSIZE - 1, "%ld", cftime); return (FnCallResult) { FNCALL_SUCCESS, { xstrdup(buffer), RVAL_TYPE_SCALAR } }; } /*********************************************************************/ static FnCallResult FnCallOr(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char id[CF_BUFSIZE]; snprintf(id, CF_BUFSIZE, "built-in FnCall or-arg"); /* We need to check all the arguments, ArgTemplate does not check varadic functions */ for (const Rlist *arg = finalargs; arg; arg = arg->next) { SyntaxTypeMatch err = CheckConstraintTypeMatch(id, arg->val, CF_DATA_TYPE_STRING, "", 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "in %s: %s", id, SyntaxTypeMatchToString(err)); } } for (const Rlist *arg = finalargs; arg; arg = arg->next) { if (IsDefinedClass(ctx, RlistScalarValue(arg))) { return FnReturnContext(true); } } return FnReturnContext(false); } /*********************************************************************/ static FnCallResult FnCallLaterThan(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; time_t now = time(NULL); struct tm tmv = FnArgsToTm(finalargs); /* Adjust to 1-based counting (input) for month and day of month * (0-based in mktime): */ tmv.tm_mon--; tmv.tm_mday--; time_t cftime = mktime(&tmv); if (cftime == -1) { Log(LOG_LEVEL_INFO, "Illegal time value"); } if (now > cftime) { strcpy(buffer, CF_ANYCLASS); } else { strcpy(buffer, "!any"); } return (FnCallResult) { FNCALL_SUCCESS, { xstrdup(buffer), RVAL_TYPE_SCALAR } }; } static FnCallResult FnCallAgoDate(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; struct tm ago = FnArgsToTm(finalargs); time_t now = time(NULL); struct tm t; localtime_r(&now, &t); t.tm_year -= ago.tm_year + 1900; /* tm.tm_year stores year - 1900 */ t.tm_mon -= ago.tm_mon; t.tm_mday -= ago.tm_mday - 1; t.tm_hour -= ago.tm_hour; t.tm_min -= ago.tm_min; t.tm_sec -= ago.tm_sec; time_t cftime = mktime(&t); snprintf(buffer, CF_BUFSIZE - 1, "%ld", cftime); if (cftime < 0) { strcpy(buffer, "0"); } return (FnCallResult) { FNCALL_SUCCESS, { xstrdup(buffer), RVAL_TYPE_SCALAR } }; } /*********************************************************************/ static FnCallResult FnCallAccumulatedDate(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE]; struct tm tmv = FnArgsToTm(finalargs); time_t cftime = 0; cftime = 0; cftime += tmv.tm_sec; cftime += tmv.tm_min * 60; cftime += tmv.tm_hour * 3600; cftime += (tmv.tm_mday -1) * 24 * 3600; cftime += tmv.tm_mon * 30 * 24 * 3600; cftime += (tmv.tm_year + 1900) * 365 * 24 * 3600; snprintf(buffer, CF_BUFSIZE - 1, "%ld", cftime); return (FnCallResult) { FNCALL_SUCCESS, { xstrdup(buffer), RVAL_TYPE_SCALAR } }; } /*********************************************************************/ static FnCallResult FnCallNot(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { return FnReturnContext(!IsDefinedClass(ctx, RlistScalarValue(finalargs))); } /*********************************************************************/ static FnCallResult FnCallNow(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, ARG_UNUSED const Rlist *finalargs) { return FnReturnF("%ld", (long)CFSTARTTIME); } /*********************************************************************/ #ifdef __sun /* Lacks %P and */ #define STRFTIME_F_HACK #define STRFTIME_s_HACK #define STRFTIME_R_HACK #endif /* http://www.unix.com/man-page/opensolaris/3c/strftime/ */ #ifdef __hpux /* Unknown gaps, aside from: */ #define STRFTIME_F_HACK #endif #ifdef _WIN32 /* Has non-standard %z, lacks %[CDeGghklnPrRtTuV] and: */ #define STRFTIME_F_HACK #define STRFTIME_R_HACK #define STRFTIME_s_HACK #endif /* http://msdn.microsoft.com/en-us/library/fe06s4ak.aspx */ bool PortablyFormatTime(char *buffer, size_t bufsiz, const char *format, #ifndef STRFTIME_s_HACK ARG_UNUSED #endif time_t when, const struct tm *tm) { /* TODO: might be better done in a libcompat wrapper. * * The following GNU extensions may be worth adding at some point; * see individual platforms for lists of which they lack. * * %C (century) * %D => %m/%d/%y * %e: as %d but s/^0/ / * %G: like %Y but frobbed for ISO week numbers * %g: last two digits of %G * %h => %b * %k: as %H but s/^0/ / * %l: as %I but s/^0/ / * %n => \n * %P: as %p but lower-cased * %r => %I:%M:%S %p * %s: seconds since epoch * %t => \t * %T => %H:%M:%S * %u: dow, {1: Mon, ..., Sun: 7} * %V: ISO week number within year %G * * The "=>" ones can all be done by extending expansion[], below; * the rest would require actually implementing GNU strftime() * properly. */ #ifdef STRFTIME_s_HACK /* %s: seconds since epoch */ char epoch[PRINTSIZE(when)]; xsnprintf(epoch, sizeof(epoch), "%jd", (intmax_t) when); #endif /* STRFTIME_s_HACK */ typedef char * SearchReplacePair[2]; SearchReplacePair expansion[] = { /* Each pair is { search, replace }. */ #ifdef STRFTIME_F_HACK { "%F", "%Y-%m-%d" }, #endif #ifdef STRFTIME_R_HACK /* %R => %H:%M:%S */ { "%R", "%H:%M:%S" }, #endif #ifdef STRFTIME_s_HACK { "%s", epoch }, #endif /* Order as in GNU strftime's man page. */ { NULL, NULL } }; char *delenda = NULL; /* in need of destruction */ /* No-op when no STRFTIME_*_HACK were defined. */ for (size_t i = 0; expansion[i][0]; i++) { char *tmp = SearchAndReplace(format, expansion[i][0], expansion[i][1]); free(delenda); format = delenda = tmp; } size_t ans = strftime(buffer, bufsiz, format, tm); free(delenda); return ans > 0; } #undef STRFTIME_F_HACK #undef STRFTIME_R_HACK #undef STRFTIME_s_HACK /*********************************************************************/ static FnCallResult FnCallStrftime(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { /* begin fn-specific content */ char *mode = RlistScalarValue(finalargs); char *format_string = RlistScalarValue(finalargs->next); // this will be a problem on 32-bit systems... const time_t when = IntFromString(RlistScalarValue(finalargs->next->next)); struct tm* tm; if (0 == strcmp("gmtime", mode)) { tm = gmtime(&when); } else { tm = localtime(&when); } char buffer[CF_BUFSIZE]; if (tm == NULL) { Log(LOG_LEVEL_WARNING, "Function %s, the given time stamp '%ld' was invalid. (strftime: %s)", fp->name, when, GetErrorStr()); } else if (PortablyFormatTime(buffer, sizeof(buffer), format_string, when, tm)) { return FnReturn(buffer); } return FnFailure(); } /*********************************************************************/ static FnCallResult FnCallEval(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { char *input = RlistScalarValue(finalargs); char *type = RlistScalarValue(finalargs->next); char *options = RlistScalarValue(finalargs->next->next); if (0 != strcmp(type, "math") || 0 != strcmp(options, "infix")) { Log(LOG_LEVEL_ERR, "Unknown %s evaluation type %s or options %s", fp->name, type, options); return FnFailure(); } char failure[CF_BUFSIZE]; memset(failure, 0, sizeof(failure)); double result = EvaluateMathInfix(ctx, input, failure); if (strlen(failure) > 0) { Log(LOG_LEVEL_INFO, "%s error: %s (input '%s')", fp->name, failure, input); return FnReturn(""); } else { return FnReturnF("%lf", result); } } /*********************************************************************/ /* Read functions */ /*********************************************************************/ static FnCallResult FnCallReadFile(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char *contents; char *filename = RlistScalarValue(finalargs); char *requested_max = RlistScalarValue(finalargs->next); int maxsize = IntFromString(requested_max); if (maxsize > CF_BUFSIZE) { Log(LOG_LEVEL_INFO, "%s: requested max size %s is more than the internal limit " TOSTRING(CF_BUFSIZE), fp->name, requested_max); maxsize = CF_BUFSIZE; } if (maxsize == 0) { maxsize = CF_BUFSIZE; } // Read once to validate structure of file in itemlist contents = CfReadFile(filename, maxsize); if (contents) { return (FnCallResult) { FNCALL_SUCCESS, { contents, RVAL_TYPE_SCALAR } }; } else { return FnFailure(); } } /*********************************************************************/ static FnCallResult ReadList(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const FnCall *fp, const Rlist *finalargs, DataType type) { const char *filename = RlistScalarValue(finalargs); const char *comment = RlistScalarValue(finalargs->next); const char *split = RlistScalarValue(finalargs->next->next); const int maxent = IntFromString(RlistScalarValue(finalargs->next->next->next)); const int maxsize = IntFromString(RlistScalarValue(finalargs->next->next->next->next)); char *file_buffer = CfReadFile(filename, maxsize); if (!file_buffer) { return FnFailure(); } bool blanks = false; Rlist *newlist = NULL; file_buffer = StripPatterns(file_buffer, comment, filename); if (!file_buffer) { return (FnCallResult) { FNCALL_SUCCESS, { NULL, RVAL_TYPE_LIST } }; } else { newlist = RlistFromSplitRegex(file_buffer, split, maxent, blanks); } bool noerrors = true; switch (type) { case CF_DATA_TYPE_STRING: break; case CF_DATA_TYPE_INT: for (Rlist *rp = newlist; rp != NULL; rp = rp->next) { if (IntFromString(RlistScalarValue(rp)) == CF_NOINT) { Log(LOG_LEVEL_ERR, "Presumed int value '%s' read from file '%s' has no recognizable value", RlistScalarValue(rp), filename); noerrors = false; } } break; case CF_DATA_TYPE_REAL: for (Rlist *rp = newlist; rp != NULL; rp = rp->next) { double real_value = 0; if (!DoubleFromString(RlistScalarValue(rp), &real_value)) { Log(LOG_LEVEL_ERR, "Presumed real value '%s' read from file '%s' has no recognizable value", RlistScalarValue(rp), filename); noerrors = false; } } break; default: ProgrammingError("Unhandled type in switch: %d", type); } free(file_buffer); if (newlist && noerrors) { return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } else { return FnFailure(); } } static FnCallResult FnCallReadStringList(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadList(ctx, fp, args, CF_DATA_TYPE_STRING); } static FnCallResult FnCallReadIntList(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadList(ctx, fp, args, CF_DATA_TYPE_INT); } static FnCallResult FnCallReadRealList(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadList(ctx, fp, args, CF_DATA_TYPE_REAL); } static FnCallResult FnCallReadJson(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *args) { const char *input_path = RlistScalarValue(args); size_t size_max = IntFromString(RlistScalarValue(args->next)); /* FIXME: fail if truncated? */ Writer *contents = FileRead(input_path, size_max, NULL); if (!contents) { Log(LOG_LEVEL_ERR, "Error reading JSON input file '%s'", input_path); return FnFailure(); } JsonElement *json = NULL; const char *data = StringWriterData(contents); if ((JsonParse(&data, &json) != JSON_PARSE_OK) || (JsonGetElementType(json) == JSON_ELEMENT_TYPE_PRIMITIVE)) { Log(LOG_LEVEL_ERR, "Error parsing JSON file '%s'", input_path); WriterClose(contents); return FnFailure(); } WriterClose(contents); return (FnCallResult) { FNCALL_SUCCESS, (Rval) { json, RVAL_TYPE_CONTAINER } }; } static FnCallResult FnCallParseJson(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *args) { const char *data = RlistScalarValue(args); JsonElement *json = NULL; if ((JsonParse(&data, &json) != JSON_PARSE_OK)|| (JsonGetElementType(json) == JSON_ELEMENT_TYPE_PRIMITIVE)) { Log(LOG_LEVEL_ERR, "Error parsing JSON expression '%s'", data); return FnFailure(); } return (FnCallResult) { FNCALL_SUCCESS, (Rval) { json, RVAL_TYPE_CONTAINER } }; } /*********************************************************************/ static FnCallResult FnCallStoreJson(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { const char *varname = RlistScalarValue(finalargs); VarRef *ref = VarRefParse(varname); DataType type = CF_DATA_TYPE_NONE; const JsonElement *value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); if (type == CF_DATA_TYPE_CONTAINER) { Writer *w = StringWriter(); int length; JsonWrite(w, value, 0); Log(LOG_LEVEL_DEBUG, "%s: from data container %s, got JSON data '%s'", fp->name, varname, StringWriterData(w)); length = strlen(StringWriterData(w)); if (length >= CF_BUFSIZE) { Log(LOG_LEVEL_INFO, "%s: truncating data container %s JSON data from %d bytes to %d", fp->name, varname, length, CF_BUFSIZE); } char buf[CF_BUFSIZE]; snprintf(buf, CF_BUFSIZE, "%s", StringWriterData(w)); WriterClose(w); return FnReturn(buf); } else { Log(LOG_LEVEL_VERBOSE, "%s: data container %s could not be found or has an invalid type", fp->name, varname); return FnFailure(); } } /*********************************************************************/ // this function is separate so other data container readers can use it static FnCallResult DataRead(EvalContext *ctx, const FnCall *fp, const Rlist *finalargs) { char *file_buffer = NULL; JsonElement *json = NULL; /* begin fn specific content */ /* 5 args: filename,comment_regex,split_regex,max number of entries,maxfilesize */ const char *filename = RlistScalarValue(finalargs); const char *comment = RlistScalarValue(finalargs->next); const char *split = RlistScalarValue(finalargs->next->next); int maxent = IntFromString(RlistScalarValue(finalargs->next->next->next)); int maxsize = IntFromString(RlistScalarValue(finalargs->next->next->next->next)); bool make_array = 0 == strcmp(fp->name, "data_readstringarrayidx"); // Read once to validate structure of file in itemlist file_buffer = CfReadFile(filename, maxsize); if (file_buffer) { file_buffer = StripPatterns(file_buffer, comment, filename); if (file_buffer != NULL) { json = BuildData(ctx, file_buffer, split, maxent, make_array); } } free(file_buffer); if (NULL == json) { Log(LOG_LEVEL_INFO, "%s: error reading from file '%s'", fp->name, filename); return FnFailure(); } return (FnCallResult) { FNCALL_SUCCESS, (Rval) { json, RVAL_TYPE_CONTAINER } }; } /*********************************************************************/ static FnCallResult FnCallDataRead(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return DataRead(ctx, fp, args); } /*********************************************************************/ static FnCallResult ReadArray(EvalContext *ctx, const FnCall *fp, const Rlist *finalargs, DataType type, bool int_index) /* lval,filename,separator,comment,Max number of bytes */ { if (!fp->caller) { Log(LOG_LEVEL_ERR, "Function '%s' can only be called from a promise", fp->name); return FnFailure(); } char *file_buffer = NULL; int entries = 0; /* begin fn specific content */ /* 6 args: array_lval,filename,comment_regex,split_regex,max number of entries,maxfilesize */ const char *array_lval = RlistScalarValue(finalargs); const char *filename = RlistScalarValue(finalargs->next); const char *comment = RlistScalarValue(finalargs->next->next); const char *split = RlistScalarValue(finalargs->next->next->next); int maxent = IntFromString(RlistScalarValue(finalargs->next->next->next->next)); int maxsize = IntFromString(RlistScalarValue(finalargs->next->next->next->next->next)); // Read once to validate structure of file in itemlist file_buffer = CfReadFile(filename, maxsize); if (!file_buffer) { entries = 0; } else { file_buffer = StripPatterns(file_buffer, comment, filename); if (file_buffer == NULL) { entries = 0; } else { entries = BuildLineArray(ctx, PromiseGetBundle(fp->caller), array_lval, file_buffer, split, maxent, type, int_index); } } switch (type) { case CF_DATA_TYPE_STRING: case CF_DATA_TYPE_INT: case CF_DATA_TYPE_REAL: break; default: ProgrammingError("Unhandled type in switch: %d", type); } free(file_buffer); return FnReturnF("%d", entries); } /*********************************************************************/ static FnCallResult FnCallReadStringArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadArray(ctx, fp, args, CF_DATA_TYPE_STRING, false); } /*********************************************************************/ static FnCallResult FnCallReadStringArrayIndex(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadArray(ctx, fp, args, CF_DATA_TYPE_STRING, true); } /*********************************************************************/ static FnCallResult FnCallReadIntArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadArray(ctx, fp, args, CF_DATA_TYPE_INT, false); } /*********************************************************************/ static FnCallResult FnCallReadRealArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ReadArray(ctx, fp, args, CF_DATA_TYPE_REAL, false); } /*********************************************************************/ static FnCallResult ParseArray(EvalContext *ctx, const FnCall *fp, const Rlist *finalargs, DataType type, int intIndex) /* lval,filename,separator,comment,Max number of bytes */ { if (!fp->caller) { Log(LOG_LEVEL_ERR, "Function '%s' can only be called from a promise", fp->name); return FnFailure(); } int entries = 0; /* begin fn specific content */ /* 6 args: array_lval,instring,comment_regex,split_regex,max number of entries,maxtextsize */ const char *array_lval = RlistScalarValue(finalargs); int maxsize = IntFromString(RlistScalarValue(finalargs->next->next->next->next->next)); char *instring = xstrndup(RlistScalarValue(finalargs->next), maxsize); const char *comment = RlistScalarValue(finalargs->next->next); const char *split = RlistScalarValue(finalargs->next->next->next); int maxent = IntFromString(RlistScalarValue(finalargs->next->next->next->next)); // Read once to validate structure of file in itemlist Log(LOG_LEVEL_DEBUG, "Parse string data from string '%s' - , maxent %d, maxsize %d", instring, maxent, maxsize); if (instring == NULL) { entries = 0; } else { instring = StripPatterns(instring, comment, "string argument 2"); if (instring == NULL) { entries = 0; } else { entries = BuildLineArray(ctx, PromiseGetBundle(fp->caller), array_lval, instring, split, maxent, type, intIndex); } } switch (type) { case CF_DATA_TYPE_STRING: case CF_DATA_TYPE_INT: case CF_DATA_TYPE_REAL: break; default: ProgrammingError("Unhandled type in switch: %d", type); } free(instring); return FnReturnF("%d", entries); } /*********************************************************************/ static FnCallResult FnCallParseStringArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ParseArray(ctx, fp, args, CF_DATA_TYPE_STRING, false); } /*********************************************************************/ static FnCallResult FnCallParseStringArrayIndex(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ParseArray(ctx, fp, args, CF_DATA_TYPE_STRING, true); } /*********************************************************************/ static FnCallResult FnCallParseIntArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ParseArray(ctx, fp, args, CF_DATA_TYPE_INT, false); } /*********************************************************************/ static FnCallResult FnCallParseRealArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *args) { return ParseArray(ctx, fp, args, CF_DATA_TYPE_REAL, false); } /*********************************************************************/ static FnCallResult FnCallSplitString(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { Rlist *newlist = NULL; /* begin fn specific content */ /* 2args: string,split_regex,max */ char *string = RlistScalarValue(finalargs); char *split = RlistScalarValue(finalargs->next); int max = IntFromString(RlistScalarValue(finalargs->next->next)); // Read once to validate structure of file in itemlist newlist = RlistFromSplitRegex(string, split, max, true); if (newlist == NULL) { RlistPrepend(&newlist, CF_NULL_VALUE, RVAL_TYPE_SCALAR); } return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallStringSplit(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { /* 3 args: string, split_regex, max */ char *string = RlistScalarValue(finalargs); char *split = RlistScalarValue(finalargs->next); int max = IntFromString(RlistScalarValue(finalargs->next->next)); if (max < 1) { Log(LOG_LEVEL_VERBOSE, "Function '%s' called with invalid maxent argument: '%d' (should be > 0).", fp->name, max); return FnFailure(); } Rlist *newlist = RlistFromRegexSplitNoOverflow(string, split, max); if (newlist == NULL) { /* We are logging error in RlistFromRegexSplitNoOverflow() so no need to do it here as well. */ return FnFailure(); } return (FnCallResult) { FNCALL_SUCCESS, { newlist, RVAL_TYPE_LIST } }; } /*********************************************************************/ static FnCallResult FnCallFileSexist(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char naked[CF_MAXVARSIZE]; char *listvar = RlistScalarValue(finalargs); if (IsVarList(listvar)) { GetNaked(naked, listvar); } else { Log(LOG_LEVEL_VERBOSE, "Function filesexist was promised a list called '%s' but this was not found", listvar); return FnFailure(); } VarRef *ref = VarRefParse(naked); DataType input_list_type = CF_DATA_TYPE_NONE; const Rlist *input_list = EvalContextVariableGet(ctx, ref, &input_list_type); if (!input_list) { Log(LOG_LEVEL_VERBOSE, "Function filesexist was promised a list called '%s' but this was not found", listvar); VarRefDestroy(ref); return FnFailure(); } VarRefDestroy(ref); if (DataTypeToRvalType(input_list_type) != RVAL_TYPE_LIST) { Log(LOG_LEVEL_VERBOSE, "Function filesexist was promised a list called '%s' but this variable is not a list", listvar); return FnFailure(); } for (const Rlist *rp = input_list; rp != NULL; rp = rp->next) { struct stat sb; if (stat(RlistScalarValue(rp), &sb) == -1) { return FnReturnContext(false); } } return FnReturnContext(true); } /*********************************************************************/ /* LDAP Nova features */ /*********************************************************************/ static FnCallResult FnCallLDAPValue(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { char buffer[CF_BUFSIZE], handle[CF_BUFSIZE]; void *newval = NULL; /* begin fn specific content */ char *uri = RlistScalarValue(finalargs); char *dn = RlistScalarValue(finalargs->next); char *filter = RlistScalarValue(finalargs->next->next); char *name = RlistScalarValue(finalargs->next->next->next); char *scope = RlistScalarValue(finalargs->next->next->next->next); char *sec = RlistScalarValue(finalargs->next->next->next->next->next); snprintf(handle, CF_BUFSIZE, "%s_%s_%s_%s", dn, filter, name, scope); if ((newval = CfLDAPValue(uri, dn, filter, name, scope, sec))) { CacheUnreliableValue("ldapvalue", handle, newval); } else { if (RetrieveUnreliableValue("ldapvalue", handle, buffer)) { newval = xstrdup(buffer); } } if (newval) { return (FnCallResult) { FNCALL_SUCCESS, { newval, RVAL_TYPE_SCALAR } }; } else { return FnFailure(); } } /*********************************************************************/ static FnCallResult FnCallLDAPArray(EvalContext *ctx, ARG_UNUSED const Policy *policy, const FnCall *fp, const Rlist *finalargs) { if (!fp->caller) { Log(LOG_LEVEL_ERR, "Function '%s' can only be called from a promise", fp->name); return FnFailure(); } void *newval; char *array = RlistScalarValue(finalargs); char *uri = RlistScalarValue(finalargs->next); char *dn = RlistScalarValue(finalargs->next->next); char *filter = RlistScalarValue(finalargs->next->next->next); char *scope = RlistScalarValue(finalargs->next->next->next->next); char *sec = RlistScalarValue(finalargs->next->next->next->next->next); if ((newval = CfLDAPArray(ctx, PromiseGetBundle(fp->caller), array, uri, dn, filter, scope, sec))) { return (FnCallResult) { FNCALL_SUCCESS, { newval, RVAL_TYPE_SCALAR } }; } else { return FnFailure(); } } /*********************************************************************/ static FnCallResult FnCallLDAPList(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { void *newval; /* begin fn specific content */ char *uri = RlistScalarValue(finalargs); char *dn = RlistScalarValue(finalargs->next); char *filter = RlistScalarValue(finalargs->next->next); char *name = RlistScalarValue(finalargs->next->next->next); char *scope = RlistScalarValue(finalargs->next->next->next->next); char *sec = RlistScalarValue(finalargs->next->next->next->next->next); if ((newval = CfLDAPList(uri, dn, filter, name, scope, sec))) { return (FnCallResult) { FNCALL_SUCCESS, { newval, RVAL_TYPE_LIST } }; } else { return FnFailure(); } } /*********************************************************************/ static FnCallResult FnCallRegLDAP(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { void *newval; /* begin fn specific content */ char *uri = RlistScalarValue(finalargs); char *dn = RlistScalarValue(finalargs->next); char *filter = RlistScalarValue(finalargs->next->next); char *name = RlistScalarValue(finalargs->next->next->next); char *scope = RlistScalarValue(finalargs->next->next->next->next); char *regex = RlistScalarValue(finalargs->next->next->next->next->next); char *sec = RlistScalarValue(finalargs->next->next->next->next->next->next); if ((newval = CfRegLDAP(ctx, uri, dn, filter, name, scope, regex, sec))) { return (FnCallResult) { FNCALL_SUCCESS, { newval, RVAL_TYPE_SCALAR } }; } else { return FnFailure(); } } /*********************************************************************/ #define KILOBYTE 1024 static FnCallResult FnCallDiskFree(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { off_t df; df = GetDiskUsage(RlistScalarValue(finalargs), CF_SIZE_ABS); if (df == CF_INFINITY) { df = 0; } return FnReturnF("%jd", ((intmax_t) df) / KILOBYTE); } static FnCallResult FnCallMakerule(EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { const char *target = RlistScalarValue(finalargs); const char *listvar = RlistScalarValue(finalargs->next); Rlist *list = NULL; bool stale = false; time_t target_time = 0; // TODO: replace IsVarList with GetListReferenceArgument if (!IsVarList(listvar)) { RlistPrepend(&list, listvar, RVAL_TYPE_SCALAR); } else { char naked[CF_MAXVARSIZE] = ""; GetNaked(naked, listvar); VarRef *ref = VarRefParse(naked); DataType input_list_type = CF_DATA_TYPE_NONE; const Rlist *input_list = EvalContextVariableGet(ctx, ref, &input_list_type); VarRefDestroy(ref); if (!input_list) { Log(LOG_LEVEL_VERBOSE, "Function 'makerule' was promised a list called '%s' but this was not found", listvar); return FnFailure(); } if (DataTypeToRvalType(input_list_type) != RVAL_TYPE_LIST) { Log(LOG_LEVEL_WARNING, "Function 'makerule' was promised a list called '%s' but this variable is not a list", listvar); return FnFailure(); } list = RlistCopy(input_list); } struct stat statbuf; if (lstat(target, &statbuf) == -1) { stale = true; } else { if (!S_ISREG(statbuf.st_mode)) { Log(LOG_LEVEL_WARNING, "Function 'makerule' target-file '%s' exists and is not a plain file", target); // Not a probe's responsibility to fix - but have this for debugging } target_time = statbuf.st_mtime; } // For each file in sources, check they exist and are older than target for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (lstat(RvalScalarValue(rp->val), &statbuf) == -1) { Log(LOG_LEVEL_INFO, "Function MAKERULE, source dependency %s was not readable", RvalScalarValue(rp->val)); RlistDestroy(list); return FnFailure(); } else { if (statbuf.st_mtime > target_time) { stale = true; } } } RlistDestroy(list); return stale ? FnReturnContext(true) : FnFailure(); } #if !defined(__MINGW32__) FnCallResult FnCallUserExists(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct passwd *pw; uid_t uid = CF_SAME_OWNER; char *arg = RlistScalarValue(finalargs); if (StringIsNumeric(arg)) { uid = Str2Uid(arg, NULL, NULL); if (uid == CF_SAME_OWNER || uid == CF_UNKNOWN_OWNER) { return FnFailure(); } if ((pw = getpwuid(uid)) == NULL) { return FnReturnContext(false); } } else if ((pw = getpwnam(arg)) == NULL) { return FnReturnContext(false); } return FnReturnContext(true); } /*********************************************************************/ FnCallResult FnCallGroupExists(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Policy *policy, ARG_UNUSED const FnCall *fp, const Rlist *finalargs) { struct group *gr; gid_t gid = CF_SAME_GROUP; char *arg = RlistScalarValue(finalargs); if (isdigit((int) *arg)) { gid = Str2Gid(arg, NULL, NULL); if (gid == CF_SAME_GROUP || gid == CF_UNKNOWN_GROUP) { return FnFailure(); } if ((gr = getgrgid(gid)) == NULL) { return FnReturnContext(false); } } else if ((gr = getgrnam(arg)) == NULL) { return FnReturnContext(false); } return FnReturnContext(true); } #endif /* !defined(__MINGW32__) */ static bool SingleLine(const char *s) { size_t length = strcspn(s, "\n\r"); /* [\n\r] followed by EOF */ return s[length] && !s[length+1]; } static void *CfReadFile(const char *filename, int maxsize) { struct stat sb; if (stat(filename, &sb) == -1) { if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON) { Log(LOG_LEVEL_INFO, "CfReadFile: Could not examine file '%s'", filename); } else { if (IsCf3VarString(filename)) { Log(LOG_LEVEL_VERBOSE, "CfReadFile: Cannot converge/reduce variable '%s' yet .. assuming it will resolve later", filename); } else { Log(LOG_LEVEL_INFO, "CfReadFile: Could not examine file '%s' (stat: %s)", filename, GetErrorStr()); } } return NULL; } /* 0 means 'read until the end of file' */ size_t limit = maxsize > 0 ? maxsize : SIZE_MAX; bool truncated = false; Writer *w = NULL; int fd = safe_open(filename, O_RDONLY | O_TEXT); if (fd >= 0) { w = FileReadFromFd(fd, limit, &truncated); close(fd); } if (!w) { Log(LOG_LEVEL_INFO, "CfReadFile: Error while reading file '%s' (%s)", filename, GetErrorStr()); return NULL; } if (truncated) { Log(LOG_LEVEL_VERBOSE, "CfReadFile: Truncating file '%s' to %d bytes as " "requested by maxsize parameter", filename, maxsize); } size_t size = StringWriterLength(w); char *result = StringWriterClose(w); /* FIXME: Is it necessary here? Move to caller(s) */ if (SingleLine(result)) { StripTrailingNewline(result, size); } return result; } /*********************************************************************/ static char *StripPatterns(char *file_buffer, const char *pattern, const char *filename) { int start, end; int count = 0; if (NULL_OR_EMPTY(pattern)) { return file_buffer; } pcre *rx = CompileRegex(pattern); if (!rx) { return file_buffer; } while (StringMatchWithPrecompiledRegex(rx, file_buffer, &start, &end)) { CloseStringHole(file_buffer, start, end); if (count++ > strlen(file_buffer)) { Log(LOG_LEVEL_ERR, "Comment regex '%s' was irreconcilable reading input '%s' probably because it legally matches nothing", pattern, filename); pcre_free(rx); return file_buffer; } } pcre_free(rx); return file_buffer; } /*********************************************************************/ static void CloseStringHole(char *s, int start, int end) { int off = end - start; char *sp; if (off <= 0) { return; } for (sp = s + start; *(sp + off) != '\0'; sp++) { *sp = *(sp + off); } *sp = '\0'; } static JsonElement* BuildData(ARG_UNUSED EvalContext *ctx, const char *file_buffer, const char *split, int maxent, bool make_array) { JsonElement *ret = make_array ? JsonArrayCreate(10) : JsonObjectCreate(10); StringSet *lines = StringSetFromString(file_buffer, '\n'); StringSetIterator iter = StringSetIteratorInit(lines); char *line; int hcount = 0; while ((line = StringSetIteratorNext(&iter)) && hcount < maxent) { size_t line_len = strlen(line); if (line_len == 0 || (line_len == 1 && line[0] == '\r')) { continue; } if (line[line_len - 1] == '\r') { line[line_len - 1] = '\0'; } Rlist *tokens = RlistFromSplitRegex(line, split, 99999, true); JsonElement *linearray = JsonArrayCreate(10); for (const Rlist *rp = tokens; rp; rp = rp->next) { const char *token = RlistScalarValue(rp); JsonArrayAppendString(linearray, token); } RlistDestroy(tokens); if (JsonLength(linearray) > 0) { if (make_array) { JsonArrayAppendArray(ret, linearray); } else { char *key = xstrdup(JsonArrayGetAsString(linearray, 0)); JsonArrayRemoveRange(linearray, 0, 0); JsonObjectAppendArray(ret, key, linearray); free(key); } // only increase hcount if we actually got something hcount++; } } StringSetDestroy(lines); return ret; } /*********************************************************************/ static int BuildLineArray(EvalContext *ctx, const Bundle *bundle, const char *array_lval, const char *file_buffer, const char *split, int maxent, DataType type, bool int_index) { Rlist *lines = RlistFromSplitString(file_buffer, '\n'); int hcount = 0; for (Rlist *it = lines; it && hcount < maxent; it = it->next) { char *line = RlistScalarValue(it); size_t line_len = strlen(line); if (line_len == 0 || (line_len == 1 && line[0] == '\r')) { continue; } if (line[line_len - 1] == '\r') { line[line_len - 1] = '\0'; } char* first_index = NULL; int vcount = 0; Rlist *tokens = RlistFromSplitRegex(line, split, 99999, true); for (const Rlist *rp = tokens; rp; rp = rp->next) { const char *token = RlistScalarValue(rp); char *converted = NULL; switch (type) { case CF_DATA_TYPE_STRING: converted = xstrdup(token); break; case CF_DATA_TYPE_INT: { long value = IntFromString(token); if (value == CF_NOINT) { FatalError(ctx, "Could not convert token to int"); } converted = StringFormat("%ld", value); } break; case CF_DATA_TYPE_REAL: { double real_value = 0; if (!DoubleFromString(token, &real_value)) { FatalError(ctx, "Could not convert token to double"); } converted = xstrdup(token); } break; default: ProgrammingError("Unhandled type in switch: %d", type); } if (NULL == first_index) { first_index = xstrdup(converted); } char *name; if (int_index) { xasprintf(&name, "%s[%d][%d]", array_lval, hcount, vcount); } else { xasprintf(&name, "%s[%s][%d]", array_lval, first_index, vcount); } VarRef *ref = VarRefParseFromBundle(name, bundle); EvalContextVariablePut(ctx, ref, converted, type, "source=function,function=buildlinearray"); VarRefDestroy(ref); free(name); free(converted); vcount++; } free(first_index); RlistDestroy(tokens); hcount++; line++; } RlistDestroy(lines); return hcount; } /*********************************************************************/ static int ExecModule(EvalContext *ctx, char *command) { FILE *pp = cf_popen(command, "rt", true); if (!pp) { Log(LOG_LEVEL_ERR, "Couldn't open pipe from '%s'. (cf_popen: %s)", command, GetErrorStr()); return false; } bool print = false; char context[CF_BUFSIZE] = ""; StringSet *tags = StringSetNew(); size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Unable to read output from '%s'. (fread: %s)", command, GetErrorStr()); cf_pclose(pp); free(line); return false; } else { break; } } print = false; for (const char *sp = line; *sp != '\0'; sp++) { if (!isspace((int) *sp)) { print = true; break; } } ModuleProtocol(ctx, command, line, print, context, tags); } StringSetDestroy(tags); cf_pclose(pp); free(line); return true; } void ModuleProtocol(EvalContext *ctx, char *command, const char *line, int print, char* context, StringSet *tags) { assert(tags); char name[CF_BUFSIZE], content[CF_BUFSIZE]; char arg0[CF_BUFSIZE]; char *filename; size_t length = strlen(line); if (*context == '\0') { /* Infer namespace from script name */ snprintf(arg0, CF_BUFSIZE, "%s", CommandArg0(command)); filename = basename(arg0); /* Canonicalize filename into acceptable namespace name*/ CanonifyNameInPlace(filename); strcpy(context, filename); Log(LOG_LEVEL_VERBOSE, "Module context '%s'", context); } name[0] = '\0'; content[0] = '\0'; switch (*line) { case '^': content[0] = '\0'; pcre *context_name_rx = CompileRegex("[a-zA-Z0-9_]+"); // symbol ID without \200 to \377 // Allow modules to set their variable context (up to 50 characters) if (1 == sscanf(line + 1, "context=%50[^\n]", content) && content[0] != '\0') { if (!context_name_rx) { Log(LOG_LEVEL_ERR, "Internal error compiling module protocol context regex, aborting!!!"); } else if (StringMatchFullWithPrecompiledRegex(context_name_rx, content)) { Log(LOG_LEVEL_VERBOSE, "Module changed variable context from '%s' to '%s'", context, content); strcpy(context, content); } else { Log(LOG_LEVEL_ERR, "Module protocol was given an unacceptable ^context directive '%s', skipping", content); } } else if (1 == sscanf(line + 1, "meta=%1024[^\n]", content) && content[0] != '\0') { Log(LOG_LEVEL_VERBOSE, "Module set meta tags to '%s'", content); StringSetClear(tags); StringSetAddSplit(tags, content, ','); StringSetAdd(tags, xstrdup("source=module")); } else { Log(LOG_LEVEL_INFO, "Unknown extended module command '%s'", line); } if (context_name_rx) { pcre_free(context_name_rx); } break; case '+': if (length > CF_MAXVARSIZE) { Log(LOG_LEVEL_ERR, "Module protocol was given an overlong +class line (%zu bytes), skipping", length); break; } // the class name will fit safely inside CF_MAXVARSIZE - 1 bytes content[0] = '\0'; sscanf(line + 1, "%1023[^\n]", content); Log(LOG_LEVEL_VERBOSE, "Activating classes from module protocol: '%s'", content); if (CheckID(content)) { Buffer *tagbuf = StringSetToBuffer(tags, ','); EvalContextClassPutSoft(ctx, content, CONTEXT_SCOPE_NAMESPACE, BufferData(tagbuf)); BufferDestroy(tagbuf); } break; case '-': if (length > CF_MAXVARSIZE) { Log(LOG_LEVEL_ERR, "Module protocol was given an overlong -class line (%zu bytes), skipping", length); break; } // the class name(s) will fit safely inside CF_MAXVARSIZE - 1 bytes content[0] = '\0'; sscanf(line + 1, "%1023[^\n]", content); Log(LOG_LEVEL_VERBOSE, "Deactivating classes from module protocol: '%s'", content); if (CheckID(content)) { if (content[0] != '\0') { StringSet *negated = StringSetFromString(content, ','); StringSetIterator it = StringSetIteratorInit(negated); const char *negated_context = NULL; while ((negated_context = StringSetIteratorNext(&it))) { Class *cls = EvalContextClassGet(ctx, NULL, negated_context); if (cls && !cls->is_soft) { FatalError(ctx, "Cannot negate the reserved class '%s'", negated_context); } ClassRef ref = ClassRefParse(negated_context); EvalContextClassRemove(ctx, ref.ns, ref.name); ClassRefDestroy(ref); } StringSetDestroy(negated); } } break; case '=': if (length > CF_BUFSIZE + 256) { Log(LOG_LEVEL_ERR, "Module protocol was given an overlong variable =line (%zu bytes), skipping", length); break; } content[0] = '\0'; // TODO: the variable name is limited to 256 to accomodate the // context name once it's in the vartable. Maybe this can be relaxed. sscanf(line + 1, "%256[^=]=%4095[^\n]", name, content); if (CheckID(name)) { Log(LOG_LEVEL_VERBOSE, "Defined variable '%s' in context '%s' with value '%s'", name, context, content); VarRef *ref = VarRefParseFromScope(name, context); Buffer *tagbuf = StringSetToBuffer(tags, ','); EvalContextVariablePut(ctx, ref, content, CF_DATA_TYPE_STRING, BufferData(tagbuf)); BufferDestroy(tagbuf); VarRefDestroy(ref); } break; case '%': content[0] = '\0'; // TODO: the variable name is limited to 256 to accomodate the // context name once it's in the vartable. Maybe this can be relaxed. sscanf(line + 1, "%256[^=]=", name); if (CheckID(name)) { JsonElement *json = NULL; Buffer *holder = BufferNewFrom(line+strlen(name)+1+1, length - strlen(name) - 1 - 1); const char *hold = BufferData(holder); Log(LOG_LEVEL_DEBUG, "Module protocol parsing JSON %s", content); if ((JsonParse(&hold, &json) != JSON_PARSE_OK) || (JsonGetElementType(json) == JSON_ELEMENT_TYPE_PRIMITIVE)) { Log(LOG_LEVEL_INFO, "Module protocol passed an invalid or too-long JSON structure, must be object or array"); } else { Log(LOG_LEVEL_VERBOSE, "Defined data container variable '%s' in context '%s' with value '%s'", name, context, BufferData(holder)); Buffer *tagbuf = StringSetToBuffer(tags, ','); VarRef *ref = VarRefParseFromScope(name, context); EvalContextVariablePut(ctx, ref, json, CF_DATA_TYPE_CONTAINER, BufferData(tagbuf)); VarRefDestroy(ref); BufferDestroy(tagbuf); JsonDestroy(json); } BufferDestroy(holder); } break; case '@': // TODO: should not need to exist. entry size matters, not line size. bufferize module protocol if (length > CF_BUFSIZE + 256 - 1) { Log(LOG_LEVEL_ERR, "Module protocol was given an overlong variable @line (%zu bytes), skipping", length); break; } content[0] = '\0'; sscanf(line + 1, "%256[^=]=%4095[^\n]", name, content); if (CheckID(name)) { Rlist *list = RlistParseString(content); if (!list) { Log(LOG_LEVEL_ERR, "Module protocol could not parse variable %s's data content %s", name, content); } else { bool has_oversize_entry = false; for (const Rlist *rp = list; rp; rp = rp->next) { size_t entry_size = strlen(RlistScalarValue(rp)); if (entry_size > CF_MAXVARSIZE) { has_oversize_entry = true; break; } } if (has_oversize_entry) { Log(LOG_LEVEL_ERR, "Module protocol was given a variable @ line with an oversize entry, skipping"); RlistDestroy(list); break; } Log(LOG_LEVEL_VERBOSE, "Defined variable '%s' in context '%s' with value '%s'", name, context, content); VarRef *ref = VarRefParseFromScope(name, context); Buffer *tagbuf = StringSetToBuffer(tags, ','); EvalContextVariablePut(ctx, ref, list, CF_DATA_TYPE_STRING_LIST, BufferData(tagbuf)); BufferDestroy(tagbuf); VarRefDestroy(ref); RlistDestroy(list); } } break; case '\0': break; default: if (print) { Log(LOG_LEVEL_INFO, "M '%s': %s", command, line); } break; } } /*********************************************************************/ /* Level */ /*********************************************************************/ static bool CheckID(const char *id) { for (const char *sp = id; *sp != '\0'; sp++) { if (!isalnum((int) *sp) && (*sp != '.') && (*sp != '-') && (*sp != '_') && (*sp != '[') && (*sp != ']')) { Log(LOG_LEVEL_ERR, "Module protocol contained an illegal character '%c' in class/variable identifier '%s'.", *sp, id); return false; } } return true; } /*********************************************************/ /* Function prototypes */ /*********************************************************/ static const FnCallArg ACCESSEDBEFORE_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Newer filename"}, {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Older filename"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg ACCUM_ARGS[] = { {"0,1000", CF_DATA_TYPE_INT, "Years"}, {"0,1000", CF_DATA_TYPE_INT, "Months"}, {"0,1000", CF_DATA_TYPE_INT, "Days"}, {"0,1000", CF_DATA_TYPE_INT, "Hours"}, {"0,1000", CF_DATA_TYPE_INT, "Minutes"}, {"0,40000", CF_DATA_TYPE_INT, "Seconds"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg AND_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg AGO_ARGS[] = { {"0,1000", CF_DATA_TYPE_INT, "Years"}, {"0,1000", CF_DATA_TYPE_INT, "Months"}, {"0,1000", CF_DATA_TYPE_INT, "Days"}, {"0,1000", CF_DATA_TYPE_INT, "Hours"}, {"0,1000", CF_DATA_TYPE_INT, "Minutes"}, {"0,40000", CF_DATA_TYPE_INT, "Seconds"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg LATERTHAN_ARGS[] = { {"0,10000", CF_DATA_TYPE_INT, "Years"}, {"0,1000", CF_DATA_TYPE_INT, "Months"}, {"0,1000", CF_DATA_TYPE_INT, "Days"}, {"0,1000", CF_DATA_TYPE_INT, "Hours"}, {"0,1000", CF_DATA_TYPE_INT, "Minutes"}, {"0,40000", CF_DATA_TYPE_INT, "Seconds"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg DATE_ARGS[] = /* for on() */ { {"1970,3000", CF_DATA_TYPE_INT, "Year"}, {"0,1000", CF_DATA_TYPE_INT, "Month (January = 0)"}, {"0,1000", CF_DATA_TYPE_INT, "Day (First day of month = 0)"}, {"0,1000", CF_DATA_TYPE_INT, "Hour"}, {"0,1000", CF_DATA_TYPE_INT, "Minute"}, {"0,1000", CF_DATA_TYPE_INT, "Second"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg CANONIFY_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "String containing non-identifier characters"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg CHANGEDBEFORE_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Newer filename"}, {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Older filename"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg CLASSIFY_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input string"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg CLASSMATCH_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg CONCAT_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg COUNTCLASSESMATCHING_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg COUNTLINESMATCHING_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Filename"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg DIRNAME_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "File path"}, {NULL, CF_DATA_TYPE_NONE, NULL}, }; static const FnCallArg DISKFREE_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File system directory"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg ESCAPE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "IP address or string to escape"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg EXECRESULT_ARGS[] = { {CF_PATHRANGE, CF_DATA_TYPE_STRING, "Fully qualified command path"}, {"noshell,useshell,powershell", CF_DATA_TYPE_OPTION, "Shell encapsulation option"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; // fileexists, isdir,isplain,islink static const FnCallArg FILESTAT_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File object name"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg FILESTAT_DETAIL_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File object name"}, {"size,gid,uid,ino,nlink,ctime,atime,mtime,mode,modeoct,permstr,permoct,type,devno,dev_minor,dev_major,basename,dirname,linktarget,linktarget_shallow", CF_DATA_TYPE_OPTION, "stat() field to get"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg FILESEXIST_ARGS[] = { {CF_NAKEDLRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg FINDFILES_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg FILTER_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression or string"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {CF_BOOL, CF_DATA_TYPE_OPTION, "Match as regular expression if true, as exact string otherwise"}, {CF_BOOL, CF_DATA_TYPE_OPTION, "Invert matches"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of matches to return"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETFIELDS_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression to match line"}, {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Filename to read"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression to split fields"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Return array name"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETINDICES_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine array or data container identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETUSERS_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Comma separated list of User names"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Comma separated list of UserID numbers"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETENV_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Name of environment variable"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of characters to read "}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETGID_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Group name in text"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETUID_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "User name in text"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GREP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GROUPEXISTS_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Group name or identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HASH_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input text"}, {"md5,sha1,sha256,sha384,sha512", CF_DATA_TYPE_OPTION, "Hash or digest algorithm"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HASHMATCH_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Filename to hash"}, {"md5,sha1,sha256,sha384,sha512", CF_DATA_TYPE_OPTION, "Hash or digest algorithm"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "ASCII representation of hash for comparison"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HOST2IP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Host name in ascii"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg IP2HOST_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "IP address (IPv4 or IPv6)"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HOSTINNETGROUP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Netgroup name"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HOSTRANGE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Hostname prefix"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Enumerated range"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HOSTSSEEN_ARGS[] = { {CF_VALRANGE, CF_DATA_TYPE_INT, "Horizon since last seen in hours"}, {"lastseen,notseen", CF_DATA_TYPE_OPTION, "Complements for selection policy"}, {"name,address", CF_DATA_TYPE_OPTION, "Type of return value desired"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HOSTSWITHCLASS_ARGS[] = { {"[a-zA-Z0-9_]+", CF_DATA_TYPE_STRING, "Class name to look for"}, {"name,address", CF_DATA_TYPE_OPTION, "Type of return value desired"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg IFELSE_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg IPRANGE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "IP address range syntax"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg IRANGE_ARGS[] = { {CF_INTRANGE, CF_DATA_TYPE_INT, "Integer start of range"}, {CF_INTRANGE, CF_DATA_TYPE_INT, "Integer end of range"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg ISGREATERTHAN_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Larger string or value"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Smaller string or value"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg ISLESSTHAN_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Smaller string or value"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Larger string or value"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg ISNEWERTHAN_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Newer file name"}, {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Older file name"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg ISVARIABLE_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Variable identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg JOIN_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Join glue-string"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg LASTNODE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input string"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Link separator, e.g. /,:"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg LDAPARRAY_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Array name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "URI"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Distinguished name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Filter"}, {"subtree,onelevel,base", CF_DATA_TYPE_OPTION, "Search scope policy"}, {"none,ssl,sasl", CF_DATA_TYPE_OPTION, "Security level"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg LDAPLIST_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "URI"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Distinguished name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Filter"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Record name"}, {"subtree,onelevel,base", CF_DATA_TYPE_OPTION, "Search scope policy"}, {"none,ssl,sasl", CF_DATA_TYPE_OPTION, "Security level"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg LDAPVALUE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "URI"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Distinguished name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Filter"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Record name"}, {"subtree,onelevel,base", CF_DATA_TYPE_OPTION, "Search scope policy"}, {"none,ssl,sasl", CF_DATA_TYPE_OPTION, "Security level"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg LSDIRLIST_ARGS[] = { {CF_PATHRANGE, CF_DATA_TYPE_STRING, "Path to base directory"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression to match files or blank"}, {CF_BOOL, CF_DATA_TYPE_OPTION, "Include the base path in the list"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg MAPLIST_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Pattern based on $(this) as original text"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier, the list variable to map"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg MAPARRAY_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Pattern based on $(this.k) and $(this.v) as original text"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine array identifier, the array variable to map"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg MERGEDATA_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg NOT_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Class value"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg NOW_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg OR_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SUM_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "A list of arbitrary real values"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PRODUCT_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "A list of arbitrary real values"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PACKAGESMATCHING_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression (unanchored) to match package name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression (unanchored) to match package version"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression (unanchored) to match package architecture"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression (unanchored) to match package method"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PEERS_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name of host list"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Comment regex pattern"}, {"2,64", CF_DATA_TYPE_INT, "Peer group size"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PEERLEADER_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name of host list"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Comment regex pattern"}, {"2,64", CF_DATA_TYPE_INT, "Peer group size"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PEERLEADERS_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name of host list"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Comment regex pattern"}, {"2,64", CF_DATA_TYPE_INT, "Peer group size"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg RANDOMINT_ARGS[] = { {CF_INTRANGE, CF_DATA_TYPE_INT, "Lower inclusive bound"}, {CF_INTRANGE, CF_DATA_TYPE_INT, "Upper exclusive bound"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg READFILE_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg READSTRINGARRAY_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Array identifier to populate"}, {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name to read"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex matching comments"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex to split data"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of entries to read"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PARSESTRINGARRAY_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Array identifier to populate"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "A string to parse for input data"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex matching comments"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex to split data"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of entries to read"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg READSTRINGLIST_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name to read"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex matching comments"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex to split data"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of entries to read"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg READJSON_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name to read"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg PARSEJSON_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "JSON string to parse"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg STOREJSON_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine data container identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg READTCP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Host name or IP address of server socket"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Port number or service name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Protocol query string"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGARRAY_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine array identifier"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGCMP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Match string"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGEXTRACT_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Match string"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "Identifier for back-references"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGISTRYVALUE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Windows registry key"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Windows registry value-id"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGLINE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Filename to search"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGLIST_ARGS[] = { {CF_NAKEDLRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg MAKERULE_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Target filename"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Source filename or CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REGLDAP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "URI"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Distinguished name"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Filter"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Record name"}, {"subtree,onelevel,base", CF_DATA_TYPE_OPTION, "Search scope policy"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex to match results"}, {"none,ssl,sasl", CF_DATA_TYPE_OPTION, "Security level"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REMOTESCALAR_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Variable identifier"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Hostname or IP address of server"}, {CF_BOOL, CF_DATA_TYPE_OPTION, "Use enryption"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg HUB_KNOWLEDGE_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Variable identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REMOTECLASSESMATCHING_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Server name or address"}, {CF_BOOL, CF_DATA_TYPE_OPTION, "Use encryption"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "Return class prefix"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg RETURNSZERO_ARGS[] = { {CF_PATHRANGE, CF_DATA_TYPE_STRING, "Command path"}, {"noshell,useshell,powershell", CF_DATA_TYPE_OPTION, "Shell encapsulation option"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg RRANGE_ARGS[] = { {CF_REALRANGE, CF_DATA_TYPE_REAL, "Real number, start of range"}, {CF_REALRANGE, CF_DATA_TYPE_REAL, "Real number, end of range"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SELECTSERVERS_ARGS[] = { {CF_NAKEDLRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier, the list of hosts or addresses to contact"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Port number or service name."}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "A query string"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "A regular expression to match success"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of bytes to read from server"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "Name for array of results"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SPLAYCLASS_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input string for classification"}, {"daily,hourly", CF_DATA_TYPE_OPTION, "Splay time policy"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SPLITSTRING_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "A data string"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex to split on"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of pieces"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg STRCMP_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "String"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "String"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg STRFTIME_ARGS[] = { {"gmtime,localtime", CF_DATA_TYPE_OPTION, "Use GMT or local time"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "A format string"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "The time as a Unix epoch offset"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SUBLIST_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {"head,tail", CF_DATA_TYPE_OPTION, "Whether to return elements from the head or from the tail of the list"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of elements to return"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg TRANSLATEPATH_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "Unix style path"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg USEMODULE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Name of module command"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Argument string for the module"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg UNIQUE_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg NTH_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list or data container identifier"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Offset or key of element to return"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg EVERY_SOME_NONE_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression or string"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg USEREXISTS_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "User name or identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SORT_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {"lex,int,real,IP,ip,MAC,mac", CF_DATA_TYPE_OPTION, "Sorting method: lex or int or real (floating point) or IPv4/IPv6 or MAC address"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg REVERSE_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SHUFFLE_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Any seed string"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg STAT_FOLD_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg SETOP_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine base list identifier"}, {CF_IDRANGE, CF_DATA_TYPE_STRING, "CFEngine filter list identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg FORMAT_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "CFEngine format string"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg EVAL_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input string"}, {"math", CF_DATA_TYPE_OPTION, "Evaluation type"}, {"infix", CF_DATA_TYPE_OPTION, "Evaluation options"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg BUNDLESMATCHING_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regular expression"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg XFORM_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input string"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg XFORM_SUBSTR_ARGS[] = { {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Input string"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of characters to return"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg DATASTATE_ARGS[] = { {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETCLASSMETATAGS_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Class identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg GETVARIABLEMETATAGS_ARGS[] = { {CF_IDRANGE, CF_DATA_TYPE_STRING, "Variable identifier"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; static const FnCallArg DATA_READSTRINGARRAY_ARGS[] = { {CF_ABSPATHRANGE, CF_DATA_TYPE_STRING, "File name to read"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex matching comments"}, {CF_ANYSTRING, CF_DATA_TYPE_STRING, "Regex to split data"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum number of entries to read"}, {CF_VALRANGE, CF_DATA_TYPE_INT, "Maximum bytes to read"}, {NULL, CF_DATA_TYPE_NONE, NULL} }; /*********************************************************/ /* FnCalls are rvalues in certain promise constraints */ /*********************************************************/ /* see cf3.defs.h enum fncalltype */ const FnCallType CF_FNCALL_TYPES[] = { FnCallTypeNew("accessedbefore", CF_DATA_TYPE_CONTEXT, ACCESSEDBEFORE_ARGS, &FnCallIsAccessedBefore, "True if arg1 was accessed before arg2 (atime)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("accumulated", CF_DATA_TYPE_INT, ACCUM_ARGS, &FnCallAccumulatedDate, "Convert an accumulated amount of time into a system representation", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("ago", CF_DATA_TYPE_INT, AGO_ARGS, &FnCallAgoDate, "Convert a time relative to now to an integer system representation", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("and", CF_DATA_TYPE_STRING, AND_ARGS, &FnCallAnd, "Calculate whether all arguments evaluate to true", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("bundlesmatching", CF_DATA_TYPE_STRING_LIST, BUNDLESMATCHING_ARGS, &FnCallBundlesMatching, "Find all the bundles that match a regular expression and tags.", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("canonify", CF_DATA_TYPE_STRING, CANONIFY_ARGS, &FnCallCanonify, "Convert an abitrary string into a legal class name", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("canonifyuniquely", CF_DATA_TYPE_STRING, CANONIFY_ARGS, &FnCallCanonify, "Convert an abitrary string into a unique legal class name", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("concat", CF_DATA_TYPE_STRING, CONCAT_ARGS, &FnCallConcat, "Concatenate all arguments into string", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("changedbefore", CF_DATA_TYPE_CONTEXT, CHANGEDBEFORE_ARGS, &FnCallIsChangedBefore, "True if arg1 was changed before arg2 (ctime)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("classify", CF_DATA_TYPE_CONTEXT, CLASSIFY_ARGS, &FnCallClassify, "True if the canonicalization of the argument is a currently defined class", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("classmatch", CF_DATA_TYPE_CONTEXT, CLASSMATCH_ARGS, &FnCallClassMatch, "True if the regular expression matches any currently defined class", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("classesmatching", CF_DATA_TYPE_STRING_LIST, CLASSMATCH_ARGS, &FnCallClassesMatching, "List the defined classes matching regex arg1 and tag regexes arg2,arg3,...", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("countclassesmatching", CF_DATA_TYPE_INT, COUNTCLASSESMATCHING_ARGS, &FnCallCountClassesMatching, "Count the number of defined classes matching regex arg1", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("countlinesmatching", CF_DATA_TYPE_INT, COUNTLINESMATCHING_ARGS, &FnCallCountLinesMatching, "Count the number of lines matching regex arg1 in file arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("datastate", CF_DATA_TYPE_CONTAINER, DATASTATE_ARGS, &FnCallDatastate, "Construct a container of the variable and class state", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("difference", CF_DATA_TYPE_STRING_LIST, SETOP_ARGS, &FnCallSetop, "Returns all the unique elements of list arg1 that are not in list arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("dirname", CF_DATA_TYPE_STRING, DIRNAME_ARGS, &FnCallDirname, "Return the parent directory name for given path", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("diskfree", CF_DATA_TYPE_INT, DISKFREE_ARGS, &FnCallDiskFree, "Return the free space (in KB) available on the directory's current partition (0 if not found)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("escape", CF_DATA_TYPE_STRING, ESCAPE_ARGS, &FnCallEscape, "Escape regular expression characters in a string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("eval", CF_DATA_TYPE_STRING, EVAL_ARGS, &FnCallEval, "Evaluate a mathematical expression", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("every", CF_DATA_TYPE_CONTEXT, EVERY_SOME_NONE_ARGS, &FnCallEverySomeNone, "True if every element in the named list matches the given regular expression", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("execresult", CF_DATA_TYPE_STRING, EXECRESULT_ARGS, &FnCallExecResult, "Execute named command and assign output to variable", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("fileexists", CF_DATA_TYPE_CONTEXT, FILESTAT_ARGS, &FnCallFileStat, "True if the named file can be accessed", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("filesexist", CF_DATA_TYPE_CONTEXT, FILESEXIST_ARGS, &FnCallFileSexist, "True if the named list of files can ALL be accessed", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("filesize", CF_DATA_TYPE_INT, FILESTAT_ARGS, &FnCallFileStat, "Returns the size in bytes of the file", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("filestat", CF_DATA_TYPE_STRING, FILESTAT_DETAIL_ARGS, &FnCallFileStatDetails, "Returns stat() details of the file", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("filter", CF_DATA_TYPE_STRING_LIST, FILTER_ARGS, &FnCallFilter, "Similarly to grep(), filter the list arg2 for matches to arg2. The matching can be as a regular expression or exactly depending on arg3. The matching can be inverted with arg4. A maximum on the number of matches returned can be set with arg5.", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("findfiles", CF_DATA_TYPE_STRING_LIST, FINDFILES_ARGS, &FnCallFindfiles, "Find files matching a shell glob pattern", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("format", CF_DATA_TYPE_STRING, FORMAT_ARGS, &FnCallFormat, "Applies a list of string values in arg2,arg3... to a string format in arg1 with sprintf() rules", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getclassmetatags", CF_DATA_TYPE_STRING_LIST, GETCLASSMETATAGS_ARGS, &FnCallGetMetaTags, "Collect a class's meta tags into an slist", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getenv", CF_DATA_TYPE_STRING, GETENV_ARGS, &FnCallGetEnv, "Return the environment variable named arg1, truncated at arg2 characters", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getfields", CF_DATA_TYPE_INT, GETFIELDS_ARGS, &FnCallGetFields, "Get an array of fields in the lines matching regex arg1 in file arg2, split on regex arg3 as array name arg4", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getgid", CF_DATA_TYPE_INT, GETGID_ARGS, &FnCallGetGid, "Return the integer group id of the named group on this host", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getindices", CF_DATA_TYPE_STRING_LIST, GETINDICES_ARGS, &FnCallGetIndices, "Get a list of keys to the array whose id is the argument and assign to variable", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getuid", CF_DATA_TYPE_INT, GETUID_ARGS, &FnCallGetUid, "Return the integer user id of the named user on this host", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getusers", CF_DATA_TYPE_STRING_LIST, GETUSERS_ARGS, &FnCallGetUsers, "Get a list of all system users defined, minus those names defined in arg1 and uids in arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getvalues", CF_DATA_TYPE_STRING_LIST, GETINDICES_ARGS, &FnCallGetValues, "Get a list of values corresponding to the right hand sides in an array whose id is the argument and assign to variable", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("getvariablemetatags", CF_DATA_TYPE_STRING_LIST, GETVARIABLEMETATAGS_ARGS, &FnCallGetMetaTags, "Collect a variable's meta tags into an slist", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("grep", CF_DATA_TYPE_STRING_LIST, GREP_ARGS, &FnCallGrep, "Extract the sub-list if items matching the regular expression in arg1 of the list named in arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("groupexists", CF_DATA_TYPE_CONTEXT, GROUPEXISTS_ARGS, &FnCallGroupExists, "True if group or numerical id exists on this host", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hash", CF_DATA_TYPE_STRING, HASH_ARGS, &FnCallHandlerHash, "Return the hash of arg1, type arg2 and assign to a variable", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hashmatch", CF_DATA_TYPE_CONTEXT, HASHMATCH_ARGS, &FnCallHashMatch, "Compute the hash of arg1, of type arg2 and test if it matches the value in arg3", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("host2ip", CF_DATA_TYPE_STRING, HOST2IP_ARGS, &FnCallHost2IP, "Returns the primary name-service IP address for the named host", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("ip2host", CF_DATA_TYPE_STRING, IP2HOST_ARGS, &FnCallIP2Host, "Returns the primary name-service host name for the IP address", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hostinnetgroup", CF_DATA_TYPE_CONTEXT, HOSTINNETGROUP_ARGS, &FnCallHostInNetgroup, "True if the current host is in the named netgroup", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hostrange", CF_DATA_TYPE_CONTEXT, HOSTRANGE_ARGS, &FnCallHostRange, "True if the current host lies in the range of enumerated hostnames specified", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hostsseen", CF_DATA_TYPE_STRING_LIST, HOSTSSEEN_ARGS, &FnCallHostsSeen, "Extract the list of hosts last seen/not seen within the last arg1 hours", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hostswithclass", CF_DATA_TYPE_STRING_LIST, HOSTSWITHCLASS_ARGS, &FnCallHostsWithClass, "Extract the list of hosts with the given class set from the hub database (enterprise extension)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("hubknowledge", CF_DATA_TYPE_STRING, HUB_KNOWLEDGE_ARGS, &FnCallHubKnowledge, "Read global knowledge from the hub host by id (enterprise extension)", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("ifelse", CF_DATA_TYPE_STRING, IFELSE_ARGS, &FnCallIfElse, "Do If-ElseIf-ElseIf-...-Else evaluation of arguments", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("intersection", CF_DATA_TYPE_STRING_LIST, SETOP_ARGS, &FnCallSetop, "Returns all the unique elements of list arg1 that are also in list arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("iprange", CF_DATA_TYPE_CONTEXT, IPRANGE_ARGS, &FnCallIPRange, "True if the current host lies in the range of IP addresses specified", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("irange", CF_DATA_TYPE_INT_RANGE, IRANGE_ARGS, &FnCallIRange, "Define a range of integer values for cfengine internal use", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("isdir", CF_DATA_TYPE_CONTEXT, FILESTAT_ARGS, &FnCallFileStat, "True if the named object is a directory", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("isexecutable", CF_DATA_TYPE_CONTEXT, FILESTAT_ARGS, &FnCallFileStat, "True if the named object has execution rights for the current user", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("isgreaterthan", CF_DATA_TYPE_CONTEXT, ISGREATERTHAN_ARGS, &FnCallIsLessGreaterThan, "True if arg1 is numerically greater than arg2, else compare strings like strcmp", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("islessthan", CF_DATA_TYPE_CONTEXT, ISLESSTHAN_ARGS, &FnCallIsLessGreaterThan, "True if arg1 is numerically less than arg2, else compare strings like NOT strcmp", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("islink", CF_DATA_TYPE_CONTEXT, FILESTAT_ARGS, &FnCallFileStat, "True if the named object is a symbolic link", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("isnewerthan", CF_DATA_TYPE_CONTEXT, ISNEWERTHAN_ARGS, &FnCallIsNewerThan, "True if arg1 is newer (modified later) than arg2 (mtime)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("isplain", CF_DATA_TYPE_CONTEXT, FILESTAT_ARGS, &FnCallFileStat, "True if the named object is a plain/regular file", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("isvariable", CF_DATA_TYPE_CONTEXT, ISVARIABLE_ARGS, &FnCallIsVariable, "True if the named variable is defined", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("join", CF_DATA_TYPE_STRING, JOIN_ARGS, &FnCallJoin, "Join the items of arg2 into a string, using the conjunction in arg1", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("lastnode", CF_DATA_TYPE_STRING, LASTNODE_ARGS, &FnCallLastNode, "Extract the last of a separated string, e.g. filename from a path", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("laterthan", CF_DATA_TYPE_CONTEXT, LATERTHAN_ARGS, &FnCallLaterThan, "True if the current time is later than the given date", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("ldaparray", CF_DATA_TYPE_CONTEXT, LDAPARRAY_ARGS, &FnCallLDAPArray, "Extract all values from an ldap record", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("ldaplist", CF_DATA_TYPE_STRING_LIST, LDAPLIST_ARGS, &FnCallLDAPList, "Extract all named values from multiple ldap records", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("ldapvalue", CF_DATA_TYPE_STRING, LDAPVALUE_ARGS, &FnCallLDAPValue, "Extract the first matching named value from ldap", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("lsdir", CF_DATA_TYPE_STRING_LIST, LSDIRLIST_ARGS, &FnCallLsDir, "Return a list of files in a directory matching a regular expression", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("makerule", CF_DATA_TYPE_CONTEXT, MAKERULE_ARGS, &FnCallMakerule, "True if the target file arg1 does not exist or a source file in arg2 is newer", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("maparray", CF_DATA_TYPE_STRING_LIST, MAPARRAY_ARGS, &FnCallMapArray, "Return a list with each element modified by a pattern based $(this.k) and $(this.v)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("maplist", CF_DATA_TYPE_STRING_LIST, MAPLIST_ARGS, &FnCallMapList, "Return a list with each element modified by a pattern based $(this)", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("mergedata", CF_DATA_TYPE_CONTAINER, MERGEDATA_ARGS, &FnCallMergeData, "Merge two or more data containers or lists", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("none", CF_DATA_TYPE_CONTEXT, EVERY_SOME_NONE_ARGS, &FnCallEverySomeNone, "True if no element in the named list matches the given regular expression", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("not", CF_DATA_TYPE_STRING, NOT_ARGS, &FnCallNot, "Calculate whether argument is false", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("now", CF_DATA_TYPE_INT, NOW_ARGS, &FnCallNow, "Convert the current time into system representation", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("nth", CF_DATA_TYPE_STRING, NTH_ARGS, &FnCallNth, "Get the element at arg2 in list or data container arg1", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("on", CF_DATA_TYPE_INT, DATE_ARGS, &FnCallOn, "Convert an exact date/time to an integer system representation", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("or", CF_DATA_TYPE_STRING, OR_ARGS, &FnCallOr, "Calculate whether any argument evaluates to true", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("packagesmatching", CF_DATA_TYPE_CONTAINER, PACKAGESMATCHING_ARGS, &FnCallPackagesMatching, "List the installed packages (\"name,version,arch,manager\") matching regex arg1=name,arg2=version,arg3=arch,arg4=method", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("packageupdatesmatching", CF_DATA_TYPE_CONTAINER, PACKAGESMATCHING_ARGS, &FnCallPackagesMatching, "List the available patches (\"name,version,arch,manager\") matching regex arg1=name,arg2=version,arg3=arch,arg4=method. Enterprise only.", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("parseintarray", CF_DATA_TYPE_INT, PARSESTRINGARRAY_ARGS, &FnCallParseIntArray, "Read an array of integers from a string, indexing by first entry on line and sequentially within each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("parsejson", CF_DATA_TYPE_CONTAINER, PARSEJSON_ARGS, &FnCallParseJson, "Parse a JSON data container from a string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("parserealarray", CF_DATA_TYPE_INT, PARSESTRINGARRAY_ARGS, &FnCallParseRealArray, "Read an array of real numbers from a string, indexing by first entry on line and sequentially within each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("parsestringarray", CF_DATA_TYPE_INT, PARSESTRINGARRAY_ARGS, &FnCallParseStringArray, "Read an array of strings from a string, indexing by first word on line and sequentially within each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("parsestringarrayidx", CF_DATA_TYPE_INT, PARSESTRINGARRAY_ARGS, &FnCallParseStringArrayIndex, "Read an array of strings from a string, indexing by line number and sequentially within each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("peers", CF_DATA_TYPE_STRING_LIST, PEERS_ARGS, &FnCallPeers, "Get a list of peers (not including ourself) from the partition to which we belong", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("peerleader", CF_DATA_TYPE_STRING, PEERLEADER_ARGS, &FnCallPeerLeader, "Get the assigned peer-leader of the partition to which we belong", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("peerleaders", CF_DATA_TYPE_STRING_LIST, PEERLEADERS_ARGS, &FnCallPeerLeaders, "Get a list of peer leaders from the named partitioning", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("product", CF_DATA_TYPE_REAL, PRODUCT_ARGS, &FnCallProduct, "Return the product of a list of reals", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("randomint", CF_DATA_TYPE_INT, RANDOMINT_ARGS, &FnCallRandomInt, "Generate a random integer between the given limits, excluding the upper", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readfile", CF_DATA_TYPE_STRING, READFILE_ARGS, &FnCallReadFile, "Read max number of bytes from named file and assign to variable", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readintarray", CF_DATA_TYPE_INT, READSTRINGARRAY_ARGS, &FnCallReadIntArray, "Read an array of integers from a file, indexed by first entry on line and sequentially on each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readintlist", CF_DATA_TYPE_INT_LIST, READSTRINGLIST_ARGS, &FnCallReadIntList, "Read and assign a list variable from a file of separated ints", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readjson", CF_DATA_TYPE_CONTAINER, READJSON_ARGS, &FnCallReadJson, "Read a JSON data container from a file", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readrealarray", CF_DATA_TYPE_INT, READSTRINGARRAY_ARGS, &FnCallReadRealArray, "Read an array of real numbers from a file, indexed by first entry on line and sequentially on each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readreallist", CF_DATA_TYPE_REAL_LIST, READSTRINGLIST_ARGS, &FnCallReadRealList, "Read and assign a list variable from a file of separated real numbers", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readstringarray", CF_DATA_TYPE_INT, READSTRINGARRAY_ARGS, &FnCallReadStringArray, "Read an array of strings from a file, indexed by first entry on line and sequentially on each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readstringarrayidx", CF_DATA_TYPE_INT, READSTRINGARRAY_ARGS, &FnCallReadStringArrayIndex, "Read an array of strings from a file, indexed by line number and sequentially on each line; return line count", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readstringlist", CF_DATA_TYPE_STRING_LIST, READSTRINGLIST_ARGS, &FnCallReadStringList, "Read and assign a list variable from a file of separated strings", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("readtcp", CF_DATA_TYPE_STRING, READTCP_ARGS, &FnCallReadTcp, "Connect to tcp port, send string and assign result to variable", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("regarray", CF_DATA_TYPE_CONTEXT, REGARRAY_ARGS, &FnCallRegArray, "True if arg1 matches any item in the associative array with id=arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("regcmp", CF_DATA_TYPE_CONTEXT, REGCMP_ARGS, &FnCallRegCmp, "True if arg1 is a regular expression matching that matches string arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("regextract", CF_DATA_TYPE_CONTEXT, REGEXTRACT_ARGS, &FnCallRegExtract, "True if the regular expression in arg 1 matches the string in arg2 and sets a non-empty array of backreferences named arg3", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("registryvalue", CF_DATA_TYPE_STRING, REGISTRYVALUE_ARGS, &FnCallRegistryValue, "Returns a value for an MS-Win registry key,value pair", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("regline", CF_DATA_TYPE_CONTEXT, REGLINE_ARGS, &FnCallRegLine, "True if the regular expression in arg1 matches a line in file arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("reglist", CF_DATA_TYPE_CONTEXT, REGLIST_ARGS, &FnCallRegList, "True if the regular expression in arg2 matches any item in the list whose id is arg1", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("regldap", CF_DATA_TYPE_CONTEXT, REGLDAP_ARGS, &FnCallRegLDAP, "True if the regular expression in arg6 matches a value item in an ldap search", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("remotescalar", CF_DATA_TYPE_STRING, REMOTESCALAR_ARGS, &FnCallRemoteScalar, "Read a scalar value from a remote cfengine server", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("remoteclassesmatching", CF_DATA_TYPE_CONTEXT, REMOTECLASSESMATCHING_ARGS, &FnCallRemoteClassesMatching, "Read persistent classes matching a regular expression from a remote cfengine server and add them into local context with prefix", FNCALL_OPTION_NONE, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("returnszero", CF_DATA_TYPE_CONTEXT, RETURNSZERO_ARGS, &FnCallReturnsZero, "True if named shell command has exit status zero", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("rrange", CF_DATA_TYPE_REAL_RANGE, RRANGE_ARGS, &FnCallRRange, "Define a range of real numbers for cfengine internal use", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("reverse", CF_DATA_TYPE_STRING_LIST, REVERSE_ARGS, &FnCallReverse, "Reverse a string list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("selectservers", CF_DATA_TYPE_INT, SELECTSERVERS_ARGS, &FnCallSelectServers, "Select tcp servers which respond correctly to a query and return their number, set array of names", FNCALL_OPTION_CACHED, FNCALL_CATEGORY_COMM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("shuffle", CF_DATA_TYPE_STRING_LIST, SHUFFLE_ARGS, &FnCallShuffle, "Shuffle a string list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("some", CF_DATA_TYPE_CONTEXT, EVERY_SOME_NONE_ARGS, &FnCallEverySomeNone, "True if an element in the named list matches the given regular expression", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("sort", CF_DATA_TYPE_STRING_LIST, SORT_ARGS, &FnCallSort, "Sort a string list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("splayclass", CF_DATA_TYPE_CONTEXT, SPLAYCLASS_ARGS, &FnCallSplayClass, "True if the first argument's time-slot has arrived, according to a policy in arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("splitstring", CF_DATA_TYPE_STRING_LIST, SPLITSTRING_ARGS, &FnCallSplitString, "Convert a string in arg1 into a list of max arg3 strings by splitting on a regular expression in arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_DEPRECATED), FnCallTypeNew("storejson", CF_DATA_TYPE_STRING, STOREJSON_ARGS, &FnCallStoreJson, "Convert a data container to a JSON string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("strcmp", CF_DATA_TYPE_CONTEXT, STRCMP_ARGS, &FnCallStrCmp, "True if the two strings match exactly", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("strftime", CF_DATA_TYPE_STRING, STRFTIME_ARGS, &FnCallStrftime, "Format a date and time string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("sublist", CF_DATA_TYPE_STRING_LIST, SUBLIST_ARGS, &FnCallSublist, "Returns arg3 element from either the head or the tail (according to arg2) of list arg1.", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("sum", CF_DATA_TYPE_REAL, SUM_ARGS, &FnCallSum, "Return the sum of a list of reals", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("translatepath", CF_DATA_TYPE_STRING, TRANSLATEPATH_ARGS, &FnCallTranslatePath, "Translate path separators from Unix style to the host's native", FNCALL_OPTION_NONE, FNCALL_CATEGORY_FILES, SYNTAX_STATUS_NORMAL), FnCallTypeNew("unique", CF_DATA_TYPE_STRING_LIST, UNIQUE_ARGS, &FnCallUnique, "Returns all the unique elements of list arg1", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("usemodule", CF_DATA_TYPE_CONTEXT, USEMODULE_ARGS, &FnCallUseModule, "Execute cfengine module script and set class if successful", FNCALL_OPTION_NONE, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), FnCallTypeNew("userexists", CF_DATA_TYPE_CONTEXT, USEREXISTS_ARGS, &FnCallUserExists, "True if user name or numerical id exists on this host", FNCALL_OPTION_NONE, FNCALL_CATEGORY_SYSTEM, SYNTAX_STATUS_NORMAL), FnCallTypeNew("variablesmatching", CF_DATA_TYPE_STRING_LIST, CLASSMATCH_ARGS, &FnCallVariablesMatching, "List the variables matching regex arg1 and tag regexes arg2,arg3,...", FNCALL_OPTION_VARARG, FNCALL_CATEGORY_UTILS, SYNTAX_STATUS_NORMAL), // Functions section following new naming convention FnCallTypeNew("string_split", CF_DATA_TYPE_STRING_LIST, SPLITSTRING_ARGS, &FnCallStringSplit, "Convert a string in arg1 into a list of at most arg3 strings by splitting on a regular expression in arg2", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), // Text xform functions FnCallTypeNew("string_downcase", CF_DATA_TYPE_STRING, XFORM_ARGS, &FnCallTextXform, "Convert a string to lowercase", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("string_head", CF_DATA_TYPE_STRING, XFORM_SUBSTR_ARGS, &FnCallTextXform, "Extract characters from the head of the string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("string_reverse", CF_DATA_TYPE_STRING, XFORM_ARGS, &FnCallTextXform, "Reverse a string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("string_length", CF_DATA_TYPE_INT, XFORM_ARGS, &FnCallTextXform, "Return the length of a string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("string_tail", CF_DATA_TYPE_STRING, XFORM_SUBSTR_ARGS, &FnCallTextXform, "Extract characters from the tail of the string", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("string_upcase", CF_DATA_TYPE_STRING, XFORM_ARGS, &FnCallTextXform, "Convert a string to UPPERCASE", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), // List folding functions FnCallTypeNew("length", CF_DATA_TYPE_INT, STAT_FOLD_ARGS, &FnCallLength, "Return the length of a list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("max", CF_DATA_TYPE_STRING, SORT_ARGS, &FnCallFold, "Return the maximum of a list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("mean", CF_DATA_TYPE_REAL, STAT_FOLD_ARGS, &FnCallFold, "Return the mean (average) of a list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("min", CF_DATA_TYPE_STRING, SORT_ARGS, &FnCallFold, "Return the minimum of a list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), FnCallTypeNew("variance", CF_DATA_TYPE_REAL, STAT_FOLD_ARGS, &FnCallFold, "Return the variance of a list", FNCALL_OPTION_NONE, FNCALL_CATEGORY_DATA, SYNTAX_STATUS_NORMAL), // File parsing functions that output a data container FnCallTypeNew("data_readstringarray", CF_DATA_TYPE_CONTAINER, DATA_READSTRINGARRAY_ARGS, &FnCallDataRead, "Read an array of strings from a file into a data container map, using the first element as a key", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNew("data_readstringarrayidx", CF_DATA_TYPE_CONTAINER, DATA_READSTRINGARRAY_ARGS, &FnCallDataRead, "Read an array of strings from a file into a data container array", FNCALL_OPTION_NONE, FNCALL_CATEGORY_IO, SYNTAX_STATUS_NORMAL), FnCallTypeNewNull() }; cfengine-3.6.2/libpromises/actuator.c0000664000175100017510000000304712411001073017325 0ustar00a10038a1003800000000000000#include #include PromiseResult PromiseResultUpdate(PromiseResult prior, PromiseResult evidence) { switch (prior) { case PROMISE_RESULT_DENIED: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_INTERRUPTED: case PROMISE_RESULT_TIMEOUT: return prior; case PROMISE_RESULT_WARN: switch (evidence) { case PROMISE_RESULT_DENIED: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_INTERRUPTED: case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_WARN: return evidence; case PROMISE_RESULT_CHANGE: case PROMISE_RESULT_NOOP: case PROMISE_RESULT_SKIPPED: return prior; } case PROMISE_RESULT_SKIPPED: return evidence; case PROMISE_RESULT_NOOP: switch (evidence) { case PROMISE_RESULT_SKIPPED: return prior; default: return evidence; } case PROMISE_RESULT_CHANGE: switch (evidence) { case PROMISE_RESULT_DENIED: case PROMISE_RESULT_FAIL: case PROMISE_RESULT_INTERRUPTED: case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_WARN: return evidence; case PROMISE_RESULT_CHANGE: case PROMISE_RESULT_NOOP: case PROMISE_RESULT_SKIPPED: return prior; } } ProgrammingError("Never reach"); } bool PromiseResultIsOK(PromiseResult result) { return (result == PROMISE_RESULT_CHANGE) || (result == PROMISE_RESULT_NOOP); } cfengine-3.6.2/libpromises/item_lib.c0000664000175100017510000006500212400110676017276 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include /* StringMatchFull,CompileRegex,StringMatchWithPrecompiledRegex */ #include #include #ifdef CYCLE_DETECTION /* While looping over entry lp in an Item list, advance slow half as * fast as lp; let n be the number of steps it has fallen behind; this * increases by one every second time round the loop. If there's a * cycle of length M, lp shall run round and round it; once slow gets * into the loop, they shall be n % M steps apart; at most 2*M more * times round the loop and n % M shall be 0 so lp == slow. If the * lead-in to the loop is of length L, this takes at most 2*(L+M) * turns round the loop to discover the cycle. The added cost is O(1) * per time round the loop, so the typical O(list length) user doesn't * change order when this is enabled, albeit the constant of * proportionality is up. * * Note, however, that none of this works if you're messing with the * structure (e.g. reversing or deleting) of the list as you go. * * To use the macros: before the loop, declare and initialize your * loop variable; pass it as lp to CYCLE_DECLARE(), followed by two * names not in use in your code. Then, in the body of the loop, * after advancing the loop variable, CYCLE_CHECK() the same three * parameters. This is apt to require a while loop where you might * otherwise have used a for loop; you also need to make sure your * loop doesn't continue past the checking. When you compile with * CYCLE_DETECTION defined, your function shall catch cycles, raising * a ProgrammingError() if it sees one. */ #define CYCLE_DECLARE(lp, slow, toggle) \ const Item *slow = lp; bool toggle = false #define CYCLE_VERIFY(lp, slow) if (!lp) { /* skip */ } \ else if (!slow) ProgrammingError("Loop-detector bug :-("); \ else if (lp == slow) ProgrammingError("Found loop in Item list") #define CYCLE_CHECK(lp, slow, toggle) \ CYCLE_VERIFY(lp, slow); \ if (toggle) { slow = slow->next; CYCLE_VERIFY(lp, slow); } \ toggle = !toggle #else #define CYCLE_DECLARE(lp, slow, toggle) /* skip */ #define CYCLE_CHECK(lp, slow, toggle) /* skip */ #endif #ifndef NDEBUG /* Only intended for use in assertions. Note that its cost is O(list * length), so you don't want to call it inside a loop over the * list. */ static bool ItemIsInList(const Item *list, const Item *item) { CYCLE_DECLARE(list, slow, toggle); while (list) { if (list == item) { return true; } list = list->next; CYCLE_CHECK(list, slow, toggle); } return false; } #endif /* NDEBUG */ /*******************************************************************/ Item *ReverseItemList(Item *list) { /* TODO: cycle-detection, which is somewhat harder here, without * turning this into a quadratic-cost function, albeit only when * assert() is enabled. */ Item *tail = NULL; while (list) { Item *here = list; list = here->next; /* assert(!ItemIsInList(here, list)); // quadratic cost */ here->next = tail; tail = here; } return tail; } /*******************************************************************/ void PrintItemList(const Item *list, Writer *w) { WriterWriteChar(w, '{'); const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { if (ip != list) { WriterWriteChar(w, ','); } WriterWriteChar(w, '\''); WriterWrite(w, ip->name); WriterWriteChar(w, '\''); ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } WriterWriteChar(w, '}'); } /*********************************************************************/ int ItemListSize(const Item *list) { int size = 0; const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { if (ip->name) { size += strlen(ip->name); } ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } return size; } /*********************************************************************/ Item *ReturnItemIn(Item *list, const char *item) { if (item == NULL || item[0] == '\0') { return NULL; } Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { return ptr; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return NULL; } /*********************************************************************/ Item *ReturnItemInClass(Item *list, const char *item, const char *classes) { if (item == NULL || item[0] == '\0') { return NULL; } Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0 && strcmp(ptr->classes, classes) == 0) { return ptr; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return NULL; } /*********************************************************************/ Item *ReturnItemAtIndex(Item *list, int index) { Item *ptr = list; for (int i = 0; ptr != NULL && i < index; i++) { ptr = ptr->next; } return ptr; } /*********************************************************************/ bool IsItemIn(const Item *list, const char *item) { if (item == NULL || item[0] == '\0') { return true; } const Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { return true; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return false; } /*********************************************************************/ /* True precisely if the lists are of equal length and every entry of * the first appears in the second. As long as each list is known to * have no duplication of its entries, this is equivalent to testing * they have the same set of entries (ignoring order). * * This is not, in general, the same as the lists being equal ! They * may have the same entries in different orders. If the first list * has some duplicate entries, the second list can have some entries * not in the first, yet compare equal. Two lists with the same set * of entries but with different multiplicities are equal or different * precisely if of equal length. */ bool ListsCompare(const Item *list1, const Item *list2) { if (ListLen(list1) != ListLen(list2)) { return false; } const Item *ptr = list1; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (IsItemIn(list2, ptr->name) == false) { return false; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return true; } /*********************************************************************/ Item *EndOfList(Item *ip) { Item *prev = CF_UNDEFINED_ITEM; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { prev = ip; ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } return prev; } /*********************************************************************/ Item *IdempPrependItem(Item **liststart, const char *itemstring, const char *classes) { Item *ip = ReturnItemIn(*liststart, itemstring); if (ip) { return ip; } PrependItem(liststart, itemstring, classes); return *liststart; } /*********************************************************************/ Item *IdempPrependItemClass(Item **liststart, const char *itemstring, const char *classes) { Item *ip = ReturnItemInClass(*liststart, itemstring, classes); if (ip) // already exists { return ip; } PrependItem(liststart, itemstring, classes); return *liststart; } /*********************************************************************/ void IdempItemCount(Item **liststart, const char *itemstring, const char *classes) { Item *ip = ReturnItemIn(*liststart, itemstring); if (ip) { ip->counter++; } else { PrependItem(liststart, itemstring, classes); } // counter+1 is the histogram of occurrences } /*********************************************************************/ Item *PrependItem(Item **liststart, const char *itemstring, const char *classes) { Item *ip = xcalloc(1, sizeof(Item)); ip->name = xstrdup(itemstring); if (classes != NULL) { ip->classes = xstrdup(classes); } ip->next = *liststart; *liststart = ip; return ip; } /*********************************************************************/ void PrependFullItem(Item **liststart, const char *itemstring, const char *classes, int counter, time_t t) { Item *ip = xcalloc(1, sizeof(Item)); ip->name = xstrdup(itemstring); ip->next = *liststart; ip->counter = counter; ip->time = t; if (classes != NULL) { ip->classes = xstrdup(classes); } *liststart = ip; } /*********************************************************************/ /* Warning: doing this a lot incurs quadratic costs, as we have to run * to the end of the list each time. If you're building long lists, * it is usually better to build the list with PrependItemList() and * then use ReverseItemList() to get the entries in the order you * wanted; for modest-sized n, 2*n < n*n, even after you've applied * different fixed scalings to the two sides. */ void AppendItem(Item **liststart, const char *itemstring, const char *classes) { Item *ip = xcalloc(1, sizeof(Item)); ip->name = xstrdup(itemstring); if (classes) { ip->classes = xstrdup(classes); /* unused now */ } if (*liststart == NULL) { *liststart = ip; } else { Item *lp = EndOfList(*liststart); assert(lp != CF_UNDEFINED_ITEM); lp->next = ip; } } /*********************************************************************/ void PrependItemList(Item **liststart, const char *itemstring) { Item *ip = xcalloc(1, sizeof(Item)); ip->name = xstrdup(itemstring); ip->next = *liststart; *liststart = ip; } /*********************************************************************/ int ListLen(const Item *list) { int count = 0; const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { count++; ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } return count; } /***************************************************************************/ void CopyList(Item **dest, const Item *source) /* Copy a list. */ { if (*dest != NULL) { ProgrammingError("CopyList - list not initialized"); } if (source == NULL) { return; } const Item *ip = source; CYCLE_DECLARE(ip, slow, toggle); Item *backwards = NULL; while (ip != NULL) { PrependFullItem(&backwards, ip->name, ip->classes, ip->counter, ip->time); ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } *dest = ReverseItemList(backwards); } /*********************************************************************/ Item *ConcatLists(Item *list1, Item *list2) /* Notes: * Refrain from freeing list2 after using ConcatLists * list1 must have at least one element in it */ { if (list1 == NULL) { ProgrammingError("ConcatLists: first argument must have at least one element"); } Item *tail = EndOfList(list1); assert(tail != CF_UNDEFINED_ITEM); assert(tail->next == NULL); /* If any entry in list1 is in list2, so is tail; so this is a * sufficient check that we're not creating a loop: */ assert(!ItemIsInList(list2, tail)); tail->next = list2; return list1; } void InsertAfter(Item **filestart, Item *ptr, const char *string) { if (*filestart == NULL || ptr == CF_UNDEFINED_ITEM) { AppendItem(filestart, string, NULL); return; } if (ptr == NULL) { AppendItem(filestart, string, NULL); return; } Item *ip = xcalloc(1, sizeof(Item)); ip->next = ptr->next; ptr->next = ip; ip->name = xstrdup(string); ip->classes = NULL; } Item *SplitString(const char *string, char sep) /* Splits a string containing a separator like : into a linked list of separate items, */ { Item *liststart = NULL; const char *sp = string; char before[CF_BUFSIZE]; int i = 0; while (*sp != '\0') { if (*sp != sep) { before[i] = *sp; i++; } else if (sp > string && sp[-1] == '\\') { /* Escaped use of list separator; over-write the backslash * we copied last time round the loop (and don't increment * i, so next time round we'll continue in the right * place). */ before[i - 1] = sep; } else { before[i] = '\0'; PrependItem(&liststart, before, NULL); i = 0; } sp++; } before[i] = '\0'; PrependItem(&liststart, before, ""); return ReverseItemList(liststart); } /*********************************************************************/ Item *SplitStringAsItemList(const char *string, char sep) /* Splits a string containing a separator like : into a linked list of separate items, */ { Item *liststart = NULL; char node[256]; char format[] = "%255[^\0]"; /* Overwrite format's internal \0 with sep: */ format[strlen(format)] = sep; assert(strlen(format) + 1 == sizeof(format) || sep == '\0'); for (const char *sp = string; *sp != '\0'; sp++) { if (sscanf(sp, format, node) == 1 && node[0] != '\0') { sp += strlen(node) - 1; PrependItem(&liststart, node, NULL); } } return ReverseItemList(liststart); } /*********************************************************************/ /* NB: does not escape entries in list ! */ char *ItemList2CSV(const Item *list) { /* After each entry, we need space for either a ',' (before the * next entry) or a final '\0'. */ int len = ItemListSize(list) + ListLen(list); char *s = xmalloc(len); *s = '\0'; /* No point cycle-checking; done while computing len. */ for (const Item *ip = list; ip != NULL; ip = ip->next) { if (ip->name) { strcat(s, ip->name); } if (ip->next) { strcat(s, ","); } } assert(strlen(s) + 1 == len); return s; } /** * Write all strings in list to buffer #buf, separating them with * #separator. Watch out, no escaping happens. * * @return Final strlen(#buf), or #buf_size if string was truncated. * Always '\0'-terminates #buf (within #buf_size). */ size_t ItemList2CSV_bound(const Item *list, char *buf, size_t buf_size, char separator) { size_t space = buf_size - 1; /* Reserve one for a '\0' */ char *tail = buf; /* Point to end of what we've written. */ const Item *ip = list; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { size_t len = strlen(ip->name); assert(buf + buf_size == tail + space + 1); if (space < len) /* We must truncate */ { memcpy(tail, ip->name, space); tail[space] = '\0'; /* a.k.a. buf[buf_size - 1] */ return buf_size; /* This signifies truncation */ } else { memcpy(tail, ip->name, len); tail += len; space -= len; } /* Output separator if list has more entries. */ if (ip->next != NULL) { if (space > 0) { *tail = separator; tail++; space--; } else /* truncation */ { *tail = '\0'; return buf_size; } } ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } *tail = '\0'; return tail - buf; } /*********************************************************************/ /* Basic operations */ /*********************************************************************/ void IncrementItemListCounter(Item *list, const char *item) { if (item == NULL || item[0] == '\0') { return; } Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { ptr->counter++; return; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } } /*********************************************************************/ void SetItemListCounter(Item *list, const char *item, int value) { if (item == NULL || item[0] == '\0') { return; } Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (strcmp(ptr->name, item) == 0) { ptr->counter = value; return; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } } /*********************************************************************/ int IsMatchItemIn(const Item *list, const char *item) /* Solve for possible regex/fuzzy models unified */ { if (item == NULL || item[0] == '\0') { return true; } const Item *ptr = list; CYCLE_DECLARE(ptr, slow, toggle); while (ptr != NULL) { if (FuzzySetMatch(ptr->name, item) == 0 || (IsRegex(ptr->name) && StringMatchFull(ptr->name, item))) { return true; } ptr = ptr->next; CYCLE_CHECK(ptr, slow, toggle); } return false; } /*********************************************************************/ /* Cycle-detection: you'll get a double free if there's a cycle. */ void DeleteItemList(Item *item) /* delete starting from item */ { while (item != NULL) { Item *here = item; item = here->next; /* before free()ing here */ free(here->name); free(here->classes); free(here); } } /*********************************************************************/ void DeleteItem(Item **liststart, Item *item) { if (item != NULL) { if (item == *liststart) { *liststart = item->next; } else { Item *ip = *liststart; CYCLE_DECLARE(ip, slow, toggle); while (ip && ip->next != item) { ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } if (ip != NULL) { assert(ip->next == item); ip->next = item->next; } } free(item->name); free(item->classes); free(item); } } /*********************************************************************/ /* DeleteItem* function notes: * -They all take an item list and an item specification ("string" argument.) * -Some of them treat the item spec as a literal string, while others * treat it as a regular expression. * -They all delete the first item meeting their criteria, as below. * function deletes item * ------------------------------------------------------------------------ * DeleteItemStarting start is literally equal to string item spec * DeleteItemLiteral literally equal to string item spec * DeleteItemMatching fully matched by regex item spec * DeleteItemContaining containing string item spec */ /*********************************************************************/ int DeleteItemGeneral(Item **list, const char *string, ItemMatchType type) { if (list == NULL) { return false; } pcre *rx = NULL; if (type == ITEM_MATCH_TYPE_REGEX_COMPLETE_NOT || type == ITEM_MATCH_TYPE_REGEX_COMPLETE) { rx = CompileRegex(string); if (!rx) { return false; } } Item *ip = *list, *last = NULL; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { if (ip->name != NULL) { bool match = false, flip = false; switch (type) { case ITEM_MATCH_TYPE_LITERAL_START_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_LITERAL_START: match = (strncmp(ip->name, string, strlen(string)) == 0); break; case ITEM_MATCH_TYPE_LITERAL_COMPLETE_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_LITERAL_COMPLETE: match = (strcmp(ip->name, string) == 0); break; case ITEM_MATCH_TYPE_LITERAL_SOMEWHERE_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_LITERAL_SOMEWHERE: match = (strstr(ip->name, string) != NULL); break; case ITEM_MATCH_TYPE_REGEX_COMPLETE_NOT: flip = true; /* and fall through */ case ITEM_MATCH_TYPE_REGEX_COMPLETE: match = StringMatchFullWithPrecompiledRegex(rx, ip->name); break; } if (flip) { match = !match; } if (match) { if (ip == *list) { *list = ip->next; } else { assert(ip != NULL); assert(last != NULL); assert(last->next == ip); last->next = ip->next; } free(ip->name); free(ip->classes); free(ip); if (rx) { pcre_free(rx); } return true; } } last = ip; ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } if (rx) { pcre_free(rx); } return false; } /*********************************************************************/ int DeleteItemStarting(Item **list, const char *string) /* delete 1st item starting with string */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_LITERAL_START); } /*********************************************************************/ int DeleteItemNotStarting(Item **list, const char *string) /* delete 1st item starting with string */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_LITERAL_START_NOT); } /*********************************************************************/ int DeleteItemLiteral(Item **list, const char *string) /* delete 1st item which is string */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_LITERAL_COMPLETE); } /*********************************************************************/ int DeleteItemMatching(Item **list, const char *string) /* delete 1st item fully matching regex */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_REGEX_COMPLETE); } /*********************************************************************/ int DeleteItemNotMatching(Item **list, const char *string) /* delete 1st item fully matching regex */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_REGEX_COMPLETE_NOT); } /*********************************************************************/ int DeleteItemContaining(Item **list, const char *string) /* delete first item containing string */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_LITERAL_SOMEWHERE); } /*********************************************************************/ int DeleteItemNotContaining(Item **list, const char *string) /* delete first item containing string */ { return DeleteItemGeneral(list, string, ITEM_MATCH_TYPE_LITERAL_SOMEWHERE_NOT); } /*********************************************************************/ bool RawSaveItemList(const Item *liststart, const char *filename, NewLineMode new_line_mode) { char new[CF_BUFSIZE]; strcpy(new, filename); strcat(new, CF_EDITED); unlink(new); /* Just in case of races */ FILE *fp = safe_fopen(new, (new_line_mode == NewLineMode_Native) ? "wt" : "w"); if (fp == NULL) { Log(LOG_LEVEL_ERR, "Couldn't write file '%s'. (fopen: %s)", new, GetErrorStr()); return false; } const Item *ip = liststart; CYCLE_DECLARE(ip, slow, toggle); while (ip != NULL) { fprintf(fp, "%s\n", ip->name); ip = ip->next; CYCLE_CHECK(ip, slow, toggle); } if (fclose(fp) == -1) { Log(LOG_LEVEL_ERR, "Unable to close file '%s' while writing. (fclose: %s)", new, GetErrorStr()); return false; } if (rename(new, filename) == -1) { Log(LOG_LEVEL_INFO, "Error while renaming file '%s' to '%s'. (rename: %s)", new, filename, GetErrorStr()); return false; } return true; } Item *RawLoadItemList(const char *filename) { FILE *fp = safe_fopen(filename, "r"); if (!fp) { return NULL; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); Item *list = NULL; while (CfReadLine(&line, &line_size, fp) != -1) { PrependItem(&list, line, NULL); } free(line); if (!feof(fp)) { Log(LOG_LEVEL_ERR, "Error while reading item list from file: %s", filename); DeleteItemList(list); list = NULL; } fclose(fp); return ReverseItemList(list); } cfengine-3.6.2/libpromises/dbm_migration_lastseen.c0000644000175100017510000001271212332162314022221 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include typedef struct { double q; double expect; double var; } QPoint0; #define QPOINT0_OFFSET 128 /* * Structure of version 0 lastseen entry: * * flag | hostkey -> address | QPoint * | | | \- 3*double * | | \- 128 chars * | \- N*chars * \- 1 byte, '+' or '-' */ static bool LastseenMigrationVersion0(DBHandle *db) { bool errors = false; DBCursor *cursor; if (!NewDBCursor(db, &cursor)) { return false; } char *key; void *value; int ksize, vsize; while (NextDB(cursor, &key, &ksize, &value, &vsize)) { if (ksize == 0) { Log(LOG_LEVEL_INFO, "LastseenMigrationVersion0: Database structure error -- zero-length key."); continue; } /* Only look for old [+-]kH -> IP entries */ if ((key[0] != '+') && (key[0] != '-')) { /* Warn about completely unexpected keys */ if ((key[0] != 'q') && (key[0] != 'k') && (key[0] != 'a')) { Log(LOG_LEVEL_INFO, "LastseenMigrationVersion0: Malformed key found '%s'", key); } continue; } bool incoming = key[0] == '-'; const char *hostkey = key + 1; /* Only migrate sane data */ if (vsize != QPOINT0_OFFSET + sizeof(QPoint0)) { Log(LOG_LEVEL_INFO, "LastseenMigrationVersion0: invalid value size for key '%s', entry is deleted", key); DBCursorDeleteEntry(cursor); continue; } /* Properly align the data */ const char *old_data_address = (const char *) value; QPoint0 old_data_q; memcpy(&old_data_q, (const char *) value + QPOINT0_OFFSET, sizeof(QPoint0)); char hostkey_key[CF_BUFSIZE]; snprintf(hostkey_key, CF_BUFSIZE, "k%s", hostkey); if (!WriteDB(db, hostkey_key, old_data_address, strlen(old_data_address) + 1)) { Log(LOG_LEVEL_INFO, "Unable to write version 1 lastseen entry for '%s'", key); errors = true; continue; } char address_key[CF_BUFSIZE]; snprintf(address_key, CF_BUFSIZE, "a%s", old_data_address); if (!WriteDB(db, address_key, hostkey, strlen(hostkey) + 1)) { Log(LOG_LEVEL_INFO, "Unable to write version 1 reverse lastseen entry for '%s'", key); errors = true; continue; } char quality_key[CF_BUFSIZE]; snprintf(quality_key, CF_BUFSIZE, "q%c%s", incoming ? 'i' : 'o', hostkey); /* Ignore malformed connection quality data */ if ((!isfinite(old_data_q.q)) || (old_data_q.q < 0) || (!isfinite(old_data_q.expect)) || (!isfinite(old_data_q.var))) { Log(LOG_LEVEL_INFO, "Ignoring malformed connection quality data for '%s'", key); DBCursorDeleteEntry(cursor); continue; } KeyHostSeen data = { .lastseen = (time_t)old_data_q.q, .Q = { /* Previously .q wasn't stored in database, but was calculated every time as a difference between previous timestamp and a new timestamp. Given we don't have this information during the database upgrade, just assume that last reading is an average one. */ .q = old_data_q.expect, .dq = 0, .expect = old_data_q.expect, .var = old_data_q.var, } }; if (!WriteDB(db, quality_key, &data, sizeof(data))) { Log(LOG_LEVEL_INFO, "Unable to write version 1 connection quality key for '%s'", key); errors = true; continue; } if (!DBCursorDeleteEntry(cursor)) { Log(LOG_LEVEL_INFO, "Unable to delete version 0 lastseen entry for '%s'", key); errors = true; } } if (DeleteDBCursor(cursor) == false) { Log(LOG_LEVEL_ERR, "LastseenMigrationVersion0: Unable to close cursor"); errors = true; } if ((!errors) && (!WriteDB(db, "version", "1", sizeof("1")))) { errors = true; } return !errors; } const DBMigrationFunction dbm_migration_plan_lastseen[] = { LastseenMigrationVersion0, NULL }; cfengine-3.6.2/libpromises/math_eval.c0000644000175100017510000001122712316547775017474 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #define MATH_EVAL_STACK_SIZE 1024 const char *const math_eval_function_names[] = { "ceil", "floor", "log10", "log2", "log", "sqrt", "sin", "cos", "tan", "asin", "acos", "atan", "abs", "step" }; static double _math_eval_step(double p) { return ((p < 0) ? 0 : 1); } typedef double (*MathEvalFunctionType)(double); static const MathEvalFunctionType math_eval_functions[] = { ceil, floor, log10, log2, log, sqrt, sin, cos, tan, asin, acos, atan, fabs, _math_eval_step }; double math_eval_push(double n, double *stack, int *stackp) { if (*stackp > MATH_EVAL_STACK_SIZE) { Log(LOG_LEVEL_ERR, "Math evaluation stack size exceeded"); return 0; } return stack[++(*stackp)]= n; } double math_eval_pop(double *stack, int *stackp) { if (*stackp < 0) { Log(LOG_LEVEL_ERR, "Math evaluation stack could not be popped, internal error!"); return 0; } return stack[(*stackp)--]; } #define YYSTYPE double #define YYPARSE yymath_parse #define YYPARSEFROM yymath_parsefrom #define YY_CTX_LOCAL #define YY_PARSE(T) T #define YY_INPUT(ctx, buf, result, max_size) { \ result = 0; \ if (NULL != ctx->input) \ { \ /*Log(LOG_LEVEL_ERR, "YYINPUT: %s", ctx->input);*/ \ strncpy(buf, ctx->input, max_size); \ int n = strlen(ctx->input)+1; \ if (n > max_size) n = max_size; \ if (n > 0) buf[n - 1]= '\0'; \ result = strlen(buf); \ ctx->input = NULL; \ } \ } #undef malloc #undef realloc #define malloc xmalloc #define realloc xrealloc #define YY_CTX_MEMBERS char *failure; \ const char *input; \ const char *original_input; \ EvalContext *eval_context; \ double result; \ char fname[50]; \ double stack[MATH_EVAL_STACK_SIZE]; \ int stackp; /* Mark unused functions as such */ struct _yycontext; static int yyAccept(struct _yycontext *yy, int tp0) FUNC_UNUSED; static void yyPush(struct _yycontext *yy, char *text, int count) FUNC_UNUSED; static void yyPop(struct _yycontext *yy, char *text, int count) FUNC_UNUSED; static void yySet(struct _yycontext *yy, char *text, int count) FUNC_UNUSED; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #include #pragma GCC diagnostic pop double EvaluateMathInfix(EvalContext *ctx, const char *input, char *failure) { yycontext yyctx; memset(&yyctx, 0, sizeof(yycontext)); yyctx.failure = failure; yyctx.original_input = input; yyctx.input = input; yyctx.eval_context = ctx; yyctx.result = 0; yyctx.stackp = -1; yymath_parse(&yyctx); yyrelease(&yyctx); return yyctx.result; } double EvaluateMathFunction(const char *f, double p) { int count = sizeof(math_eval_functions)/sizeof(math_eval_functions[0]); for (int i=0; i < count; i++) { if (0 == strcmp(math_eval_function_names[i], f)) { return (*math_eval_functions[i])(p); } } return p; } cfengine-3.6.2/libpromises/files_names.c0000664000175100017510000004063412403637345020015 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include /*********************************************************************/ int IsNewerFileTree(const char *dir, time_t reftime) { const struct dirent *dirp; char path[CF_BUFSIZE] = { 0 }; Dir *dirh; struct stat sb; // Assumes that race conditions on the file path are unlikely and unimportant if (lstat(dir, &sb) == -1) { Log(LOG_LEVEL_ERR, "Unable to stat directory '%s' in IsNewerFileTree. (stat: %s)", dir, GetErrorStr()); // return true to provoke update return true; } if (S_ISDIR(sb.st_mode)) { if (sb.st_mtime > reftime) { Log(LOG_LEVEL_VERBOSE, " >> Detected change in %s", dir); return true; } } if ((dirh = DirOpen(dir)) == NULL) { Log(LOG_LEVEL_ERR, "Unable to open directory '%s' in IsNewerFileTree. (opendir: %s)", dir, GetErrorStr()); return false; } else { for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, "..")) { continue; } strlcpy(path, dir, CF_BUFSIZE); if (!JoinPath(path, dirp->d_name)) { Log(LOG_LEVEL_ERR, "Internal limit: Buffer ran out of space adding %s to %s in IsNewerFileTree", dir, path); DirClose(dirh); return false; } if (lstat(path, &sb) == -1) { Log(LOG_LEVEL_ERR, "Unable to stat directory '%s' in IsNewerFileTree. (lstat: %s)", path, GetErrorStr()); DirClose(dirh); // return true to provoke update return true; } if (S_ISDIR(sb.st_mode)) { if (sb.st_mtime > reftime) { Log(LOG_LEVEL_VERBOSE, " >> Detected change in %s", path); DirClose(dirh); return true; } else { if (IsNewerFileTree(path, reftime)) { DirClose(dirh); return true; } } } } } DirClose(dirh); return false; } /*********************************************************************/ int IsDir(const char *path) /* Checks if the object pointed to by path exists and is a directory. Returns true if so, false otherwise. */ { #ifdef __MINGW32__ return NovaWin_IsDir(path); #else struct stat sb; if (stat(path, &sb) != -1) { if (S_ISDIR(sb.st_mode)) { return true; } } return false; #endif /* !__MINGW32__ */ } /*********************************************************************/ /*********************************************************************/ char *JoinPath(char *path, const char *leaf) { int len = strlen(leaf); if (Chop(path, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } AddSlash(path); if ((strlen(path) + len) > (CF_BUFSIZE - CF_BUFFERMARGIN)) { Log(LOG_LEVEL_ERR, "Internal limit 1: Buffer ran out of space constructing string. Tried to add %s to %s", leaf, path); return NULL; } strcat(path, leaf); return path; } /*********************************************************************/ char *JoinSuffix(char *path, const char *leaf) { int len = strlen(leaf); if (Chop(path, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } DeleteSlash(path); if ((strlen(path) + len) > (CF_BUFSIZE - CF_BUFFERMARGIN)) { Log(LOG_LEVEL_ERR, "Internal limit 2: Buffer ran out of space constructing string. Tried to add %s to %s", leaf, path); return NULL; } strcat(path, leaf); return path; } int IsAbsPath(const char *path) { if (IsFileSep(*path)) { return true; } else { return false; } } /*******************************************************************/ void AddSlash(char *str) { char *sp, *sep = FILE_SEPARATOR_STR; int f = false, b = false; if (str == NULL) { return; } if (strlen(str) == 0) { strcpy(str, sep); return; } /* Try to see what convention is being used for filenames in case this is a cross-system copy from Win/Unix */ for (sp = str; *sp != '\0'; sp++) { switch (*sp) { case '/': f = true; break; case '\\': b = true; break; default: break; } } if (f && (!b)) { sep = "/"; } else if (b && (!f)) { sep = "\\"; } if (!IsFileSep(str[strlen(str) - 1])) { strcat(str, sep); } } /*********************************************************************/ char *GetParentDirectoryCopy(const char *path) /** * WARNING: Remember to free return value. **/ { assert(path); assert(strlen(path) > 0); char *path_copy = xstrdup(path); if(strcmp(path_copy, "/") == 0) { return path_copy; } char *sp = (char *)LastFileSeparator(path_copy); if(!sp) { Log(LOG_LEVEL_ERR, "Path %s does not contain file separators (GetParentDirectory())", path_copy); free(path_copy); return NULL; } if(sp == FirstFileSeparator(path_copy)) // don't chop off first path separator { *(sp + 1) = '\0'; } else { *sp = '\0'; } return path_copy; } /*********************************************************************/ // Can remove several slashes if they are redundant. void DeleteSlash(char *str) { int size = strlen(str); if ((size == 0) || (str == NULL)) { return; } int root = RootDirLength(str); while (IsFileSep(str[size - 1]) && size - 1 > root) { size--; } str[size] = '\0'; /* no-op if we didn't change size */ } /*********************************************************************/ void DeleteRedundantSlashes(char *str) { int move_from; // Invariant: newpos <= oldpos int oldpos = RootDirLength(str); int newpos = oldpos; while (str[oldpos] != '\0') { // Skip over subsequent separators. while (IsFileSep(str[oldpos])) { oldpos++; } move_from = oldpos; // And then skip over the next path component. while (str[oldpos] != '\0' && !IsFileSep(str[oldpos])) { oldpos++; } // If next character is file separator, move past it, since we want to keep one. if (IsFileSep(str[oldpos])) { oldpos++; } int move_len = oldpos - move_from; memmove(&str[newpos], &str[move_from], move_len); newpos += move_len; } str[newpos] = '\0'; } /*********************************************************************/ const char *FirstFileSeparator(const char *str) { assert(str); assert(strlen(str) > 0); if(strncmp(str, "\\\\", 2) == 0) // windows share { return str + 1; } for(const char *pos = str; *pos != '\0'; pos++) { if(IsFileSep(*pos)) { return pos; } } return NULL; } /*********************************************************************/ const char *LastFileSeparator(const char *str) /* Return pointer to last file separator in string, or NULL if string does not contains any file separtors */ { const char *sp; /* Walk through string backwards */ sp = str + strlen(str) - 1; while (sp >= str) { if (IsFileSep(*sp)) { return sp; } sp--; } return NULL; } /*********************************************************************/ bool ChopLastNode(char *str) /* Chop off trailing node name (possible blank) starting from last character and removing up to the first / encountered e.g. /a/b/c -> /a/b /a/b/ -> /a/b Will also collapse redundant/repeating path separators. */ { char *sp; int ret; DeleteRedundantSlashes(str); /* Here cast is necessary and harmless, str is modifiable */ if ((sp = (char *) LastFileSeparator(str)) == NULL) { int pos = RootDirLength(str); if (str[pos] == '\0') { ret = false; } else { str[pos] = '.'; str[pos + 1] = '\0'; ret = true; } } else { // Don't chop the root slash in an absolute path. if (IsAbsoluteFileName(str) && FirstFileSeparator(str) == sp) { *(++sp) = '\0'; } else { *sp = '\0'; } ret = true; } return ret; } /*********************************************************************/ void CanonifyNameInPlace(char *s) { for (; *s != '\0'; s++) { if ((!isalnum((int)(unsigned char)*s)) || (*s == '.')) { *s = '_'; } } } /*********************************************************************/ void TransformNameInPlace(char *s, char from, char to) { for (; *s != '\0'; s++) { if (*s == from) { *s = to; } } } /*********************************************************************/ char *CanonifyName(const char *str) { static char buffer[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */ strlcpy(buffer, str, CF_BUFSIZE); CanonifyNameInPlace(buffer); return buffer; } /*********************************************************************/ char *CanonifyChar(const char *str, char ch) { static char buffer[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */ char *sp; strlcpy(buffer, str, CF_BUFSIZE); for (sp = buffer; *sp != '\0'; sp++) { if (*sp == ch) { *sp = '_'; } } return buffer; } /*********************************************************************/ int CompareCSVName(const char *s1, const char *s2) { const char *sp1, *sp2; char ch1, ch2; for (sp1 = s1, sp2 = s2; (*sp1 != '\0') || (*sp2 != '\0'); sp1++, sp2++) { ch1 = (*sp1 == ',') ? '_' : *sp1; ch2 = (*sp2 == ',') ? '_' : *sp2; if (ch1 > ch2) { return 1; } else if (ch1 < ch2) { return -1; } } return 0; } /*********************************************************************/ const char *ReadLastNode(const char *str) /* Return the last node of a pathname string */ { const char *sp; if ((sp = LastFileSeparator(str)) == NULL) { return str; } else { return sp + 1; } } /*********************************************************************/ int CompressPath(char *dest, const char *src) { char node[CF_BUFSIZE]; int nodelen; int rootlen; memset(dest, 0, CF_BUFSIZE); rootlen = RootDirLength(src); memcpy(dest, src, rootlen); for (const char *sp = src + rootlen; *sp != '\0'; sp++) { if (IsFileSep(*sp)) { continue; } for (nodelen = 0; (sp[nodelen] != '\0') && (!IsFileSep(sp[nodelen])); nodelen++) { if (nodelen > CF_MAXLINKSIZE) { Log(LOG_LEVEL_ERR, "Link in path suspiciously large"); return false; } } strncpy(node, sp, nodelen); node[nodelen] = '\0'; sp += nodelen - 1; if (strcmp(node, ".") == 0) { continue; } if (strcmp(node, "..") == 0) { if (!ChopLastNode(dest)) { Log(LOG_LEVEL_DEBUG, "used .. beyond top of filesystem!"); return false; } continue; } else { AddSlash(dest); } if (!JoinPath(dest, node)) { return false; } } return true; } /*********************************************************************/ FilePathType FilePathGetType(const char *file_path) { if (IsAbsoluteFileName(file_path)) { return FILE_PATH_TYPE_ABSOLUTE; } else if (*file_path == '.') { return FILE_PATH_TYPE_RELATIVE; } else { return FILE_PATH_TYPE_NON_ANCHORED; } } bool IsFileOutsideDefaultRepository(const char *f) { return !StringStartsWith(f, GetInputDir()); } /*******************************************************************/ static int UnixRootDirLength(const char *f) { if (IsFileSep(*f)) { return 1; } return 0; } #ifdef _WIN32 static int NTRootDirLength(const char *f) { int len; if (f[0] == '\\' && f[1] == '\\') { /* UNC style path */ /* Skip over host name */ for (len = 2; f[len] != '\\'; len++) { if (f[len] == '\0') { return len; } } /* Skip over share name */ for (len++; f[len] != '\\'; len++) { if (f[len] == '\0') { return len; } } /* Skip over file separator */ len++; return len; } if (isalpha(f[0]) && f[1] == ':') { if (IsFileSep(f[2])) { return 3; } return 2; } return UnixRootDirLength(f); } #endif int RootDirLength(const char *f) /* Return length of Initial directory in path - */ { #ifdef _WIN32 return NTRootDirLength(f); #else return UnixRootDirLength(f); #endif } /* Buffer should be at least CF_MAXVARSIZE large */ const char *GetSoftwareCacheFilename(char *buffer) { snprintf(buffer, CF_MAXVARSIZE, "%s/state/%s", CFWORKDIR, SOFTWARE_PACKAGES_CACHE); MapName(buffer); return buffer; } /* Buffer should be at least CF_MAXVARSIZE large */ const char *GetSoftwarePatchesFilename(char *buffer) { snprintf(buffer, CF_MAXVARSIZE, "%s/state/%s", CFWORKDIR, SOFTWARE_PATCHES_CACHE); MapName(buffer); return buffer; } const char *RealPackageManager(const char *manager) { const char *pos = strchr(manager, ' '); if (strncmp(manager, "env ", 4) != 0 && (!pos || pos - manager < 4 || strncmp(pos - 4, "/env", 4) != 0)) { return CommandArg0(manager); } // Look for variable assignments. const char *last_pos; bool eq_sign_found = false; while (true) { if (eq_sign_found) { last_pos = pos + 1; } else { last_pos = pos + strspn(pos, " "); // Skip over consecutive spaces. } pos = strpbrk(last_pos, "= "); if (!pos) { break; } if (*pos == '=') { eq_sign_found = true; } else if (eq_sign_found) { eq_sign_found = false; } else { return CommandArg0(last_pos); } } // Reached the end? Weird. Must be env command with no real command. return CommandArg0(manager); } cfengine-3.6.2/libpromises/cf3.defs.h0000664000175100017510000010650412411001073017105 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF3_DEFS_H #define CFENGINE_CF3_DEFS_H /* ALWAYS INCLUDE EITHER THIS FILE OR platform.h FIRST */ #include #include #include /* HashMethod */ #include #include #include /* ProtocolVersion, CF_BUFSIZE etc */ #include /* xsnprintf, ProgrammingError etc */ /*******************************************************************/ /* Preprocessor tricks */ /*******************************************************************/ /* Convert integer constant to string */ #define STRINGIFY__INTERNAL_MACRO(x) #x #define TOSTRING(x) STRINGIFY__INTERNAL_MACRO(x) /*******************************************************************/ /* Various defines */ /*******************************************************************/ #define CF_BILLION 1000000000L #define CF_EXPANDSIZE (2*CF_BUFSIZE) #define CF_BUFFERMARGIN 128 #define CF_BLOWFISHSIZE 16 #define CF_MAXVARSIZE 1024 #define CF_MAXSIDSIZE 2048 /* Windows only: Max size (bytes) of security identifiers */ #define CF_NONCELEN (CF_BUFSIZE/16) #define CF_MAXLINKSIZE 256 #define CF_PROCCOLS 16 #define CF_HASHTABLESIZE 8192 #define CF_MACROALPHABET 61 /* a-z, A-Z plus a bit */ #define CF_ALPHABETSIZE 256 #define CF_SAMEMODE 7777 #define CF_SAME_OWNER ((uid_t)-1) #define CF_UNKNOWN_OWNER ((uid_t)-2) #define CF_SAME_GROUP ((gid_t)-1) #define CF_UNKNOWN_GROUP ((gid_t)-2) #define CF_INFINITY ((int)999999999) #define CF_MONDAY_MORNING 345600 #define MINUTES_PER_HOUR 60 #define SECONDS_PER_MINUTE 60 #define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE) #define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) #define SECONDS_PER_WEEK (7 * SECONDS_PER_DAY) #define SECONDS_PER_YEAR (365 * SECONDS_PER_DAY) /* Long-term monitoring constants */ #define HOURS_PER_SHIFT 6 #define SECONDS_PER_SHIFT (HOURS_PER_SHIFT * SECONDS_PER_HOUR) #define SHIFTS_PER_DAY 4 #define SHIFTS_PER_WEEK (4*7) #define MAX_MONTH_NAME 9 #define MAX_DIGEST_BYTES (512 / 8) /* SHA-512 */ #define MAX_DIGEST_HEX (MAX_DIGEST_BYTES * 2) /*******************************************************************/ #define CF_FILECHANGE "file_change.log" #define CF_FILECHANGE_NEW "file_changes.log" #define CF_PROMISE_LOG "promise_summary.log" #define CF_ENV_FILE "env_data" #define CF_SAVED ".cfsaved" #define CF_EDITED ".cfedited" #define CF_NEW ".cfnew" #define CFD_TERMINATOR "---cfXen/gine/cfXen/gine---" #define CFD_TRUE "CFD_TRUE" #define CFD_FALSE "CFD_FALSE" #define CF_ANYCLASS "any" #define CF_SMALL_OFFSET 2 #define CF_NS ':' // namespace character separator /*****************************************************************************/ /* Auditing key */ typedef enum { PROMISE_RESULT_SKIPPED, PROMISE_RESULT_NOOP = 'n', PROMISE_RESULT_CHANGE = 'c', PROMISE_RESULT_WARN = 'w', // something wrong but nothing done PROMISE_RESULT_FAIL = 'f', PROMISE_RESULT_DENIED = 'd', PROMISE_RESULT_TIMEOUT = 't', PROMISE_RESULT_INTERRUPTED = 'i' } PromiseResult; /*****************************************************************************/ #define CF_FAILEDSTR "BAD: Unspecified server refusal (see verbose server output)" #define CF_CHANGEDSTR1 "BAD: File changed " /* Split this so it cannot be recognized */ #define CF_CHANGEDSTR2 "while copying" #define CF_START_DOMAIN "undefined.domain" #define CF_GRAINS 64 #define ATTR 20 #define CF_NETATTR 7 /* icmp udp dns tcpsyn tcpfin tcpack */ #define CF_MEASURE_INTERVAL (5.0*60.0) #define CF_SHIFT_INTERVAL (6*3600) #define CF_OBSERVABLES 100 enum observables { ob_users, ob_rootprocs, ob_otherprocs, ob_diskfree, ob_loadavg, ob_netbiosns_in, ob_netbiosns_out, ob_netbiosdgm_in, ob_netbiosdgm_out, ob_netbiosssn_in, ob_netbiosssn_out, ob_imap_in, ob_imap_out, ob_cfengine_in, ob_cfengine_out, ob_nfsd_in, ob_nfsd_out, ob_smtp_in, ob_smtp_out, ob_www_in, ob_www_out, ob_ftp_in, ob_ftp_out, ob_ssh_in, ob_ssh_out, ob_wwws_in, ob_wwws_out, ob_icmp_in, ob_icmp_out, ob_udp_in, ob_udp_out, ob_dns_in, ob_dns_out, ob_tcpsyn_in, ob_tcpsyn_out, ob_tcpack_in, ob_tcpack_out, ob_tcpfin_in, ob_tcpfin_out, ob_tcpmisc_in, ob_tcpmisc_out, ob_webaccess, ob_weberrors, ob_syslog, ob_messages, ob_temp0, ob_temp1, ob_temp2, ob_temp3, ob_cpuall, ob_cpu0, ob_cpu1, ob_cpu2, ob_cpu3, ob_microsoft_ds_in, ob_microsoft_ds_out, ob_www_alt_in, ob_www_alt_out, ob_imaps_in, ob_imaps_out, ob_ldap_in, ob_ldap_out, ob_ldaps_in, ob_ldaps_out, ob_mongo_in, ob_mongo_out, ob_mysql_in, ob_mysql_out, ob_postgresql_in, ob_postgresql_out, ob_ipp_in, ob_ipp_out, ob_spare }; #include typedef struct { time_t t; QPoint Q; } Event; typedef struct { time_t last_seen; QPoint Q[CF_OBSERVABLES]; } Averages; /******************************************************************/ typedef struct { pid_t pid; time_t time; time_t process_start_time; } LockData; /*****************************************************************************/ #ifdef __MINGW32__ # define NULLFILE "nul" # define EXEC_SUFFIX ".exe" #else # define NULLFILE "/dev/null" # define EXEC_SUFFIX "" #endif /* !__MINGW32__ */ #define CF_WORDSIZE 8 /* Number of bytes in a word */ /*******************************************************************/ typedef struct Item_ Item; /*******************************************************************/ typedef enum { CF_SIZE_ABS, CF_SIZE_PERCENT } CfSize; /*******************************************************************/ typedef enum { CONTEXT_STATE_POLICY_RESET, /* Policy when trying to add already defined persistent states */ CONTEXT_STATE_POLICY_PRESERVE } PersistentClassPolicy; /*******************************************************************/ typedef struct UidList_ UidList; // TODO: why do UIDs have their own list type? Clean up. struct UidList_ { #ifdef __MINGW32__ // TODO: remove uid for NT ? char sid[CF_MAXSIDSIZE]; /* Invalid sid indicates unset */ #endif /* __MINGW32__ */ uid_t uid; char *uidname; /* when uid is -2 */ UidList *next; }; /*******************************************************************/ typedef struct GidList_ GidList; // TODO: why do UIDs have their own list type? Clean up. struct GidList_ { gid_t gid; char *gidname; /* when gid is -2 */ GidList *next; }; /*************************************************************************/ /* Fundamental (meta) types */ /*************************************************************************/ #define CF_UNDEFINED -1 #define CF_NOINT -678L #define CF_UNDEFINED_ITEM (void *)0x1234 #define DEFAULTMODE ((mode_t)0755) #define CF_DONEPASSES 4 #define CFPULSETIME 60 /*************************************************************************/ /* Parsing and syntax tree structures */ /*************************************************************************/ extern const int CF3_MODULES; /*************************************************************************/ typedef struct Policy_ Policy; typedef struct Bundle_ Bundle; typedef struct Body_ Body; typedef struct Promise_ Promise; typedef struct PromiseType_ PromiseType; typedef struct FnCall_ FnCall; /*************************************************************************/ /* Abstract datatypes */ /*************************************************************************/ typedef enum { CF_DATA_TYPE_STRING, CF_DATA_TYPE_INT, CF_DATA_TYPE_REAL, CF_DATA_TYPE_STRING_LIST, CF_DATA_TYPE_INT_LIST, CF_DATA_TYPE_REAL_LIST, CF_DATA_TYPE_OPTION, CF_DATA_TYPE_OPTION_LIST, CF_DATA_TYPE_BODY, CF_DATA_TYPE_BUNDLE, CF_DATA_TYPE_CONTEXT, CF_DATA_TYPE_CONTEXT_LIST, CF_DATA_TYPE_INT_RANGE, CF_DATA_TYPE_REAL_RANGE, CF_DATA_TYPE_COUNTER, CF_DATA_TYPE_CONTAINER, CF_DATA_TYPE_NONE } DataType; /*************************************************************************/ #define CF_COMMONC "common" #define CF_AGENTC "agent" #define CF_SERVERC "server" #define CF_MONITORC "monitor" #define CF_EXECC "executor" #define CF_RUNC "runagent" #define CF_KEYGEN "keygenerator" #define CF_HUBC "hub" typedef enum { AGENT_TYPE_COMMON, AGENT_TYPE_AGENT, AGENT_TYPE_SERVER, AGENT_TYPE_MONITOR, AGENT_TYPE_EXECUTOR, AGENT_TYPE_RUNAGENT, AGENT_TYPE_KEYGEN, AGENT_TYPE_HUB, AGENT_TYPE_NOAGENT } AgentType; /*************************************************************************/ typedef enum { COMMON_CONTROL_BUNDLESEQUENCE, COMMON_CONTROL_GOALPATTERNS, COMMON_CONTROL_IGNORE_MISSING_BUNDLES, COMMON_CONTROL_IGNORE_MISSING_INPUTS, COMMON_CONTROL_INPUTS, COMMON_CONTROL_VERSION, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER, COMMON_CONTROL_OUTPUT_PREFIX, COMMON_CONTROL_DOMAIN, COMMON_CONTROL_REQUIRE_COMMENTS, COMMON_CONTROL_LICENSES, COMMON_CONTROL_SITE_CLASSES, COMMON_CONTROL_SYSLOG_HOST, COMMON_CONTROL_SYSLOG_PORT, COMMON_CONTROL_FIPS_MODE, COMMON_CONTROL_CACHE_SYSTEM_FUNCTIONS, COMMON_CONTROL_PROTOCOL_VERSION, COMMON_CONTROL_MAX } CommonControl; /*************************************************************************/ typedef enum { AGENT_CONTROL_ABORTCLASSES, AGENT_CONTROL_ABORTBUNDLECLASSES, AGENT_CONTROL_ADDCLASSES, AGENT_CONTROL_AGENTACCESS, AGENT_CONTROL_AGENTFACILITY, AGENT_CONTROL_ALLCLASSESREPORT, AGENT_CONTROL_ALWAYSVALIDATE, AGENT_CONTROL_AUDITING, AGENT_CONTROL_BINARYPADDINGCHAR, AGENT_CONTROL_BINDTOINTERFACE, AGENT_CONTROL_HASHUPDATES, AGENT_CONTROL_CHILDLIBPATH, AGENT_CONTROL_CHECKSUM_ALERT_TIME, AGENT_CONTROL_DEFAULTCOPYTYPE, AGENT_CONTROL_DRYRUN, AGENT_CONTROL_EDITBINARYFILESIZE, AGENT_CONTROL_EDITFILESIZE, AGENT_CONTROL_ENVIRONMENT, AGENT_CONTROL_EXCLAMATION, AGENT_CONTROL_EXPIREAFTER, AGENT_CONTROL_FSINGLECOPY, AGENT_CONTROL_FAUTODEFINE, AGENT_CONTROL_HOSTNAMEKEYS, AGENT_CONTROL_IFELAPSED, AGENT_CONTROL_INFORM, AGENT_CONTROL_INTERMITTENCY, AGENT_CONTROL_MAX_CHILDREN, AGENT_CONTROL_MAXCONNECTIONS, AGENT_CONTROL_MOUNTFILESYSTEMS, AGENT_CONTROL_NONALPHANUMFILES, AGENT_CONTROL_REPCHAR, AGENT_CONTROL_REFRESH_PROCESSES, AGENT_CONTROL_REPOSITORY, AGENT_CONTROL_SECUREINPUT, AGENT_CONTROL_SENSIBLECOUNT, AGENT_CONTROL_SENSIBLESIZE, AGENT_CONTROL_SKIPIDENTIFY, AGENT_CONTROL_SUSPICIOUSNAMES, AGENT_CONTROL_SYSLOG, AGENT_CONTROL_TRACK_VALUE, AGENT_CONTROL_TIMEZONE, AGENT_CONTROL_TIMEOUT, AGENT_CONTROL_VERBOSE, AGENT_CONTROL_NONE } AgentControl; /*************************************************************************/ typedef enum { EXEC_CONTROL_SPLAYTIME, EXEC_CONTROL_MAILFROM, EXEC_CONTROL_MAILTO, EXEC_CONTROL_MAILSUBJECT, EXEC_CONTROL_SMTPSERVER, EXEC_CONTROL_MAILMAXLINES, EXEC_CONTROL_SCHEDULE, EXEC_CONTROL_EXECUTORFACILITY, EXEC_CONTROL_EXECCOMMAND, EXEC_CONTROL_AGENT_EXPIREAFTER, EXEC_CONTROL_NONE } ExecControl; typedef enum { EDIT_ORDER_BEFORE, EDIT_ORDER_AFTER } EditOrder; /*************************************************************************/ /* Syntax module range/pattern constants for type validation */ /*************************************************************************/ #define CF_BUNDLE (void*)1234 /* any non-null value, not used */ /* Initial values for max=low, min=high when determining a range, for * which we'll revise max upwards and in downwards if given meaningful * bounds for them. Quite why they're these values, rather than 9999 * (longest string of 9s to fit in an int16) or 999999999 (similar for * int32) remains a mystery. */ #define CF_HIGHINIT 999999L #define CF_LOWINIT -999999L #define CF_SIGNALRANGE "hup,int,trap,kill,pipe,cont,abrt,stop,quit,term,child,usr1,usr2,bus,segv" #define CF_BOOL "true,false,yes,no,on,off" #define CF_LINKRANGE "symlink,hardlink,relative,absolute" #define CF_TIMERANGE "0,2147483647" /* i.e. "0,0x7fffffff" */ /* Syntax checker accepts absurdly big numbers for backwards * compatibility. WARNING: internally they are stored as longs, possibly * being truncated to LONG_MAX within IntFromString(). */ #define CF_VALRANGE "0,99999999999" #define CF_INTRANGE "-99999999999,99999999999" #define CF_INTLISTRANGE "[-0-9_$(){}\\[\\].]+" #define CF_REALRANGE "-9.99999E100,9.99999E100" #define CF_CHARRANGE "^.$" #define CF_NULL_VALUE "cf_null" #define CF_MODERANGE "[0-7augorwxst,+-]+" #define CF_BSDFLAGRANGE "[+-]*[(arch|archived|nodump|opaque|sappnd|sappend|schg|schange|simmutable|sunlnk|sunlink|uappnd|uappend|uchg|uchange|uimmutable|uunlnk|uunlink)]+" #define CF_CLASSRANGE "[a-zA-Z0-9_!&@@$|.()\\[\\]{}:]+" #define CF_IDRANGE "[a-zA-Z0-9_$(){}\\[\\].:]+" #define CF_USERRANGE "[a-zA-Z0-9_$.-]+" #define CF_IPRANGE "[a-zA-Z0-9_$(){}.:-]+" #define CF_FNCALLRANGE "[a-zA-Z0-9_(){}.$@]+" #define CF_NAKEDLRANGE "@[(][a-zA-Z0-9_$(){}\\[\\].:]+[)]" #define CF_ANYSTRING ".*" #define CF_KEYSTRING "^(SHA|MD5)=[0123456789abcdef]*$" #ifndef __MINGW32__ # define CF_ABSPATHRANGE "\"?(/.*)" #else // can start with e.g. c:\... or "c:\... | unix (for Cygwin-style paths) # define CF_ABSPATHRANGE "\"?(([a-zA-Z]:\\\\.*)|(/.*))" #endif /* Any non-empty string can be an absolute path under Unix */ #define CF_PATHRANGE ".+" // Put this here now for caching efficiency #define SOFTWARE_PACKAGES_CACHE "software_packages.csv" #define SOFTWARE_PATCHES_CACHE "software_patches_avail.csv" #define PACKAGES_CONTEXT "cf_pack_context" #define PACKAGES_CONTEXT_ANYVER "cf_pack_context_anyver" /*************************************************************************/ typedef struct EvalContext_ EvalContext; typedef enum { RVAL_TYPE_SCALAR = 's', RVAL_TYPE_LIST = 'l', RVAL_TYPE_FNCALL = 'f', RVAL_TYPE_CONTAINER = 'c', RVAL_TYPE_NOPROMISEE = 'X' // TODO: must be another hack } RvalType; typedef struct { void *item; RvalType type; } Rval; typedef struct Rlist_ Rlist; typedef struct ConstraintSyntax_ ConstraintSyntax; typedef struct BodySyntax_ BodySyntax; /* * Promise types or bodies may optionally provide parse-tree check function, called after * parsing to do a preliminary syntax/semantic checking of unexpanded promises. * * This check function should populate #errors sequence with errors it finds and * return false in case it has found at least one error. * * If the check function has not found any errors, it should return true. */ typedef bool (*PromiseCheckFn)(const Promise *pp, Seq *errors); typedef bool (*BodyCheckFn)(const Body *body, Seq *errors); typedef enum { SYNTAX_STATUS_NORMAL, SYNTAX_STATUS_DEPRECATED, SYNTAX_STATUS_REMOVED } SyntaxStatus; typedef enum { FNCALL_CATEGORY_SYSTEM, FNCALL_CATEGORY_FILES, FNCALL_CATEGORY_IO, FNCALL_CATEGORY_COMM, FNCALL_CATEGORY_DATA, FNCALL_CATEGORY_UTILS } FnCallCategory; struct ConstraintSyntax_ { const char *lval; const DataType dtype; union { const char *validation_string; const BodySyntax *body_type_syntax; } range; const char *description; SyntaxStatus status; }; struct BodySyntax_ { const char *body_type; const ConstraintSyntax *constraints; BodyCheckFn check_body; SyntaxStatus status; }; typedef struct { const char *bundle_type; const char *promise_type; const ConstraintSyntax *constraints; const PromiseCheckFn check_promise; SyntaxStatus status; } PromiseTypeSyntax; /*************************************************************************/ typedef struct Constraint_ Constraint; typedef enum { INTERVAL_HOURLY, INTERVAL_DAILY, INTERVAL_NONE } Interval; typedef enum { FILE_COMPARATOR_ATIME, FILE_COMPARATOR_MTIME, FILE_COMPARATOR_CTIME, FILE_COMPARATOR_CHECKSUM, FILE_COMPARATOR_HASH, FILE_COMPARATOR_BINARY, FILE_COMPARATOR_EXISTS, FILE_COMPARATOR_NONE } FileComparator; typedef enum { FILE_LINK_TYPE_SYMLINK, FILE_LINK_TYPE_HARDLINK, FILE_LINK_TYPE_RELATIVE, FILE_LINK_TYPE_ABSOLUTE, FILE_LINK_TYPE_NONE } FileLinkType; enum cfopaction { cfa_fix, cfa_warn, }; typedef enum { BACKUP_OPTION_BACKUP, BACKUP_OPTION_NO_BACKUP, BACKUP_OPTION_TIMESTAMP, BACKUP_OPTION_ROTATE, BACKUP_OPTION_REPOSITORY_STORE /* for internal use only */ } BackupOption; enum cfnofile { cfa_force, cfa_delete, cfa_skip }; enum cflinkchildren { cfa_override, cfa_onlynonexisting }; typedef enum { FILE_CHANGE_REPORT_NONE, FILE_CHANGE_REPORT_CONTENT_CHANGE, FILE_CHANGE_REPORT_STATS_CHANGE, FILE_CHANGE_REPORT_ALL } FileChangeReport; enum signalnames { cfa_hup, cfa_int, cfa_trap, cfa_kill, cfa_pipe, cfa_cont, cfa_abrt, cfa_stop, cfa_quit, cfa_term, cfa_child, cfa_usr1, cfa_usr2, cfa_bus, cfa_segv }; typedef enum { PACKAGE_ACTION_ADD, PACKAGE_ACTION_DELETE, PACKAGE_ACTION_REINSTALL, PACKAGE_ACTION_UPDATE, PACKAGE_ACTION_ADDUPDATE, PACKAGE_ACTION_PATCH, PACKAGE_ACTION_VERIFY, PACKAGE_ACTION_NONE } PackageAction; typedef enum { PACKAGE_VERSION_COMPARATOR_EQ, PACKAGE_VERSION_COMPARATOR_NEQ, PACKAGE_VERSION_COMPARATOR_GT, PACKAGE_VERSION_COMPARATOR_LT, PACKAGE_VERSION_COMPARATOR_GE, PACKAGE_VERSION_COMPARATOR_LE, PACKAGE_VERSION_COMPARATOR_NONE } PackageVersionComparator; typedef enum { PACKAGE_ACTION_POLICY_INDIVIDUAL, PACKAGE_ACTION_POLICY_BULK, PACKAGE_ACTION_POLICY_NONE } PackageActionPolicy; typedef enum { PROMISE_STATE_REPAIRED = 'r', PROMISE_STATE_NOTKEPT = 'n', PROMISE_STATE_KEPT = 'c', PROMISE_STATE_ANY = 'x' } PromiseState; /************************************************************************************/ typedef enum { LAST_SEEN_DIRECTION_INCOMING = '-', LAST_SEEN_DIRECTION_OUTGOING = '+' } LastSeenDirection; /************************************************************************************/ typedef enum { ACL_METHOD_APPEND, ACL_METHOD_OVERWRITE, ACL_METHOD_NONE } AclMethod; typedef enum { ACL_TYPE_GENERIC, ACL_TYPE_POSIX, ACL_TYPE_NTFS_, ACL_TYPE_NONE } AclType; typedef enum { ACL_DEFAULT_NO_CHANGE, ACL_DEFAULT_SPECIFY, ACL_DEFAULT_ACCESS, ACL_DEFAULT_CLEAR, ACL_DEFAULT_NONE } AclDefault; typedef enum { ACL_INHERIT_FALSE, ACL_INHERIT_TRUE, ACL_INHERIT_NOCHANGE } AclInherit; typedef struct { AclMethod acl_method; AclType acl_type; AclDefault acl_default; Rlist *acl_entries; Rlist *acl_default_entries; /* Only used on Windows */ AclInherit acl_inherit; } Acl; typedef enum { INHERIT_ACCESS_ONLY, INHERIT_DEFAULT_ONLY, INHERIT_ACCESS_AND_DEFAULT } inherit_t; typedef enum { INSERT_MATCH_TYPE_IGNORE_LEADING, INSERT_MATCH_TYPE_IGNORE_TRAILING, INSERT_MATCH_TYPE_IGNORE_EMBEDDED, INSERT_MATCH_TYPE_EXACT } InsertMatchType; /*************************************************************************/ /* Runtime constraint structures */ /*************************************************************************/ #define OVECCOUNT 30 /*******************************************************************/ typedef struct { char *last; char *lock; char *log; bool is_dummy; } CfLock; /*************************************************************************/ typedef struct { char *host; char *source; char *mounton; char *options; int unmount; } Mount; /*************************************************************************/ typedef struct { int travlinks; int rmdeadlinks; int depth; int xdev; int include_basedir; Rlist *include_dirs; Rlist *exclude_dirs; } DirectoryRecursion; /*************************************************************************/ typedef struct { enum cfopaction action; int ifelapsed; int expireafter; int background; char *log_string; char *log_kept; char *log_repaired; char *log_failed; int log_priority; char *measure_id; int audit; LogLevel report_level; LogLevel log_level; } TransactionContext; /*************************************************************************/ typedef enum { CONTEXT_SCOPE_NAMESPACE, CONTEXT_SCOPE_BUNDLE, CONTEXT_SCOPE_NONE } ContextScope; typedef struct { ContextScope scope; Rlist *change; Rlist *failure; Rlist *denied; Rlist *timeout; Rlist *kept; int persist; PersistentClassPolicy timer; Rlist *del_change; Rlist *del_kept; Rlist *del_notkept; Rlist *retcode_kept; Rlist *retcode_repaired; Rlist *retcode_failed; } DefineClasses; /*************************************************************************/ /* SQL Database connectors */ /*************************************************************************/ typedef enum { DATABASE_TYPE_MYSQL, DATABASE_TYPE_POSTGRES, DATABASE_TYPE_NONE } DatabaseType; /*************************************************************************/ /* Package promises */ /*************************************************************************/ typedef struct PackageItem_ PackageItem; typedef struct PackageManager_ PackageManager; struct PackageManager_ { char *manager; PackageAction action; PackageActionPolicy policy; PackageItem *pack_list; PackageItem *patch_list; PackageItem *patch_avail; PackageManager *next; }; /*************************************************************************/ struct PackageItem_ { char *name; char *version; char *arch; Promise *pp; PackageItem *next; }; typedef struct { unsigned int expires; PersistentClassPolicy policy; char tags[]; // variable length, must be zero terminated } PersistentClassInfo; /*************************************************************************/ typedef struct { mode_t plus; mode_t minus; UidList *owners; GidList *groups; char *findertype; u_long plus_flags; /* for *BSD chflags */ u_long minus_flags; /* for *BSD chflags */ int rxdirs; } FilePerms; /*************************************************************************/ typedef struct { Rlist *name; Rlist *path; Rlist *perms; Rlist *bsdflags; Rlist *owners; Rlist *groups; long max_size; long min_size; time_t max_ctime; time_t min_ctime; time_t max_mtime; time_t min_mtime; time_t max_atime; time_t min_atime; char *exec_regex; char *exec_program; Rlist *filetypes; Rlist *issymlinkto; char *result; } FileSelect; /*************************************************************************/ typedef struct { enum { TIDY_LINK_DELETE, TIDY_LINK_KEEP } dirlinks; int rmdirs; } FileDelete; /*************************************************************************/ typedef struct { char *newname; char *disable_suffix; int disable; int rotate; mode_t plus; mode_t minus; } FileRename; /*************************************************************************/ typedef struct { HashMethod hash; FileChangeReport report_changes; int report_diffs; int update; } FileChange; /*************************************************************************/ typedef struct { char *source; FileLinkType link_type; Rlist *copy_patterns; enum cfnofile when_no_file; enum cflinkchildren when_linking_children; int link_children; } FileLink; /*************************************************************************/ typedef enum { SHELL_TYPE_NONE, SHELL_TYPE_USE, SHELL_TYPE_POWERSHELL } ShellType; typedef struct { ShellType shelltype; mode_t umask; uid_t owner; gid_t group; char *chdir; char *chroot; int preview; int nooutput; int timeout; } ExecContain; /*************************************************************************/ typedef struct { long min_range; long max_range; Rlist *in_range_define; Rlist *out_of_range_define; } ProcessCount; /*************************************************************************/ typedef struct { Rlist *owner; long min_pid; long max_pid; long min_ppid; long max_ppid; long min_pgid; long max_pgid; long min_rsize; long max_rsize; long min_vsize; long max_vsize; time_t min_ttime; time_t max_ttime; time_t min_stime; time_t max_stime; long min_pri; long max_pri; long min_thread; long max_thread; char *status; char *command; char *tty; char *process_result; } ProcessSelect; /*************************************************************************/ typedef struct { Constraint *expression; ContextScope scope; int nconstraints; int persistent; } ContextConstraint; /*************************************************************************/ typedef struct { BackupOption backup; int empty_before_use; int maxfilesize; int joinlines; int rotate; int inherit; } EditDefaults; /*************************************************************************/ typedef struct { Rlist *startwith_from_list; Rlist *not_startwith_from_list; Rlist *match_from_list; Rlist *not_match_from_list; Rlist *contains_from_list; Rlist *not_contains_from_list; } LineSelect; typedef struct { char *build_xpath; char *select_xpath; char *attribute_value; int havebuildxpath; int haveselectxpath; int haveattributevalue; } EditXml; typedef struct { char *line_matching; EditOrder before_after; char *first_last; } EditLocation; typedef struct { char *select_start; char *select_end; int include_start; int include_end; } EditRegion; typedef struct { char *column_separator; int select_column; char value_separator; char *column_value; char *column_operation; int extend_columns; int blanks_ok; } EditColumn; typedef struct { char *replace_value; char *occurrences; } EditReplace; /*************************************************************************/ typedef struct { char *mount_type; char *mount_source; char *mount_server; Rlist *mount_options; int editfstab; int unmount; } StorageMount; typedef struct { int check_foreign; long freespace; int sensible_size; int sensible_count; int scan_arrivals; } StorageVolume; /*************************************************************************/ typedef struct { int haveprintfile; int havelastseen; int lastseen; char *result; double intermittency; char *friend_pattern; char *filename; char *to_file; int numlines; Rlist *showstate; } Report; /*************************************************************************/ typedef struct { PackageAction package_policy; int have_package_methods; char *package_version; Rlist *package_architectures; PackageVersionComparator package_select; PackageActionPolicy package_changes; Rlist *package_file_repositories; char *package_default_arch_command; char *package_list_command; char *package_list_version_regex; char *package_list_name_regex; char *package_list_arch_regex; char *package_patch_list_command; char *package_patch_version_regex; char *package_patch_name_regex; char *package_patch_arch_regex; char *package_patch_installed_regex; char *package_list_update_command; int package_list_update_ifelapsed; char *package_version_regex; char *package_name_regex; char *package_arch_regex; char *package_installed_regex; char *package_add_command; char *package_delete_command; char *package_update_command; char *package_patch_command; char *package_verify_command; char *package_noverify_regex; char *package_name_convention; char *package_delete_convention; bool package_commands_useshell; char *package_multiline_start; char *package_version_less_command; char *package_version_equal_command; int package_noverify_returncode; } Packages; /*************************************************************************/ typedef enum { MEASURE_POLICY_AVERAGE, MEASURE_POLICY_SUM, MEASURE_POLICY_FIRST, MEASURE_POLICY_LAST, MEASURE_POLICY_NONE } MeasurePolicy; typedef struct { char *stream_type; DataType data_type; MeasurePolicy policy; char *history_type; char *select_line_matching; int select_line_number; char *extraction_regex; char *units; int growing; } Measurement; typedef struct { char *db_server_owner; char *db_server_password; char *db_server_host; char *db_connect_db; DatabaseType db_server_type; char *server; char *type; char *operation; Rlist *columns; Rlist *rows; Rlist *exclude; } Database; /*************************************************************************/ typedef enum { USER_STATE_PRESENT, USER_STATE_ABSENT, USER_STATE_LOCKED, USER_STATE_NONE } UserState; typedef enum { PASSWORD_FORMAT_PLAINTEXT, PASSWORD_FORMAT_HASH, PASSWORD_FORMAT_NONE } PasswordFormat; typedef struct { UserState policy; char *uid; PasswordFormat password_format; char *password; char *description; char *group_primary; Rlist *groups_secondary; char *home_dir; char *shell; } User; /*************************************************************************/ typedef enum { SERVICE_POLICY_START, SERVICE_POLICY_STOP, SERVICE_POLICY_DISABLE, SERVICE_POLICY_RESTART, SERVICE_POLICY_RELOAD, SERVICE_POLICY_NONE } ServicePolicy; typedef struct { Rlist *service_depend; char *service_type; char *service_args; ServicePolicy service_policy; char *service_autostart_policy; char *service_depend_chain; FnCall *service_method; } Services; /*************************************************************************/ typedef enum { ENVIRONMENT_STATE_CREATE, ENVIRONMENT_STATE_DELETE, ENVIRONMENT_STATE_RUNNING, ENVIRONMENT_STATE_SUSPENDED, ENVIRONMENT_STATE_DOWN, ENVIRONMENT_STATE_NONE } EnvironmentState; typedef struct { int cpus; int memory; int disk; char *baseline; char *spec; Rlist *addresses; char *name; char *host; char *type; EnvironmentState state; } Environments; /* This is huge, but the simplification of logic is huge too so we leave it to the compiler to optimize */ #include typedef struct { const char *source; const char *port; /* port or service name */ char *destination; FileComparator compare; FileLinkType link_type; Rlist *servers; Rlist *link_instead; Rlist *copy_links; BackupOption backup; int stealth; int preserve; int collapse; int check_root; int type_check; int force_update; int force_ipv4; size_t min_size; /* Safety margin not search criterion */ size_t max_size; int trustkey; int encrypt; int verify; int purge; short timeout; ProtocolVersion protocol_version; } FileCopy; typedef struct { FileSelect select; FilePerms perms; FileCopy copy; FileDelete delete; FileRename rename; FileChange change; FileLink link; EditDefaults edits; Packages packages; ContextConstraint context; Measurement measure; Acl acl; Database database; Services service; User users; Environments env; char *transformer; char *pathtype; char *repository; char *edit_template; char *template_method; JsonElement *template_data; int touch; int create; int move_obstructions; int inherit; DirectoryRecursion recursion; TransactionContext transaction; DefineClasses classes; ExecContain contain; char *args; int module; Rlist *signals; char *process_stop; char *restart_class; ProcessCount process_count; ProcessSelect process_select; Report report; StorageMount mount; StorageVolume volume; int havedepthsearch; int haveselect; int haverename; int havedelete; int haveperms; int havechange; int havecopy; int havelink; int haveeditline; int haveeditxml; int haveedit; int havecontain; int haveclasses; int havetrans; int haveprocess_count; int havemount; int havevolume; int havebundle; int havepackages; /* editline */ EditRegion region; EditLocation location; EditColumn column; EditReplace replace; EditXml xml; int haveregion; int havelocation; int havecolumn; int havereplace; int haveinsertselect; int havedeleteselect; LineSelect line_select; char *sourcetype; int expandvars; int not_matching; Rlist *insert_match; } Attributes; /*************************************************************************/ /* common macros */ /*************************************************************************/ #define NULL_OR_EMPTY(str) ((str == NULL) || (str[0] == '\0')) #define BEGINSWITH(str,start) (strncmp(str,start,strlen(start)) == 0) #include #include #include #include #include extern const ConstraintSyntax CF_COMMON_BODIES[]; extern const ConstraintSyntax CF_VARBODY[]; extern const PromiseTypeSyntax *const CF_ALL_PROMISE_TYPES[]; extern const ConstraintSyntax CFG_CONTROLBODY[]; extern const BodySyntax CONTROL_BODIES[]; extern const ConstraintSyntax CFH_CONTROLBODY[]; extern const PromiseTypeSyntax CF_COMMON_PROMISE_TYPES[]; extern const ConstraintSyntax CF_CLASSBODY[]; extern const ConstraintSyntax CFA_CONTROLBODY[]; extern const ConstraintSyntax CFEX_CONTROLBODY[]; typedef struct ServerConnectionState_ ServerConnectionState; #endif cfengine-3.6.2/libpromises/unix.c0000664000175100017510000001240112400110676016470 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #ifdef HAVE_SYS_UIO_H # include #endif #ifndef __MINGW32__ static bool IsProcessRunning(pid_t pid); void ProcessSignalTerminate(pid_t pid) { if(!IsProcessRunning(pid)) { return; } if(kill(pid, SIGINT) == -1) { Log(LOG_LEVEL_ERR, "Could not send SIGINT to pid '%jd'. (kill: %s)", (intmax_t)pid, GetErrorStr()); } sleep(1); if(kill(pid, SIGTERM) == -1) { Log(LOG_LEVEL_ERR, "Could not send SIGTERM to pid '%jd'. (kill: %s)", (intmax_t)pid, GetErrorStr()); } sleep(5); if(kill(pid, SIGKILL) == -1) { Log(LOG_LEVEL_ERR, "Could not send SIGKILL to pid '%jd'. (kill: %s)", (intmax_t)pid, GetErrorStr()); } sleep(1); } /*************************************************************/ static bool IsProcessRunning(pid_t pid) { int res = kill(pid, 0); if(res == 0) { return true; } if(res == -1 && errno == ESRCH) { return false; } Log(LOG_LEVEL_ERR, "Failed checking for process existence. (kill: %s)", GetErrorStr()); return false; } /*************************************************************/ int GetCurrentUserName(char *userName, int userNameLen) { struct passwd *user_ptr; memset(userName, 0, userNameLen); user_ptr = getpwuid(getuid()); if (user_ptr == NULL) { Log(LOG_LEVEL_ERR, "Could not get user name of current process, using 'UNKNOWN'. (getpwuid: %s)", GetErrorStr()); strlcpy(userName, "UNKNOWN", userNameLen); return false; } strlcpy(userName, user_ptr->pw_name, userNameLen); return true; } /*************************************************************/ int IsExecutable(const char *file) { struct stat sb; gid_t grps[NGROUPS]; int n; if (stat(file, &sb) == -1) { Log(LOG_LEVEL_ERR, "Proposed executable file '%s' doesn't exist", file); return false; } if (sb.st_mode & 02) { Log(LOG_LEVEL_ERR, "SECURITY ALERT: promised executable '%s' is world writable! ", file); Log(LOG_LEVEL_ERR, "SECURITY ALERT: CFEngine will not execute this - requires human inspection"); return false; } if ((getuid() == sb.st_uid) || (getuid() == 0)) { if (sb.st_mode & 0100) { return true; } } else if (getgid() == sb.st_gid) { if (sb.st_mode & 0010) { return true; } } else { if (sb.st_mode & 0001) { return true; } if ((n = getgroups(NGROUPS, grps)) > 0) { int i; for (i = 0; i < n; i++) { if (grps[i] == sb.st_gid) { if (sb.st_mode & 0010) { return true; } } } } } return false; } bool ShellCommandReturnsZero(const char *command, ShellType shell) { int status; pid_t pid; if (shell == SHELL_TYPE_POWERSHELL) { Log(LOG_LEVEL_ERR, "Powershell is only supported on Windows"); return false; } if ((pid = fork()) < 0) { Log(LOG_LEVEL_ERR, "Failed to fork new process: %s", command); return false; } else if (pid == 0) /* child */ { ALARM_PID = -1; if (shell == SHELL_TYPE_USE) { if (execl(SHELL_PATH, "sh", "-c", command, NULL) == -1) { Log(LOG_LEVEL_ERR, "Command '%s' failed. (execl: %s)", command, GetErrorStr()); exit(EXIT_FAILURE); } } else { char **argv = ArgSplitCommand(command); if (execv(argv[0], argv) == -1) { Log(LOG_LEVEL_ERR, "Command '%s' failed. (execv: %s)", argv[0], GetErrorStr()); exit(EXIT_FAILURE); } } } else /* parent */ { ALARM_PID = pid; while (waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { return -1; } } return (WEXITSTATUS(status) == 0); } return false; } #endif /* !__MINGW32__ */ cfengine-3.6.2/libpromises/syslog_client.h0000664000175100017510000000246312243421446020404 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SYSLOG_CLIENT_H #define CFENGINE_SYSLOG_CLIENT_H #include /* * This module provides implementation of UDP syslog protocol */ bool SetSyslogHost(const char *host); void SetSyslogPort(uint16_t port); void SetSyslogFacility(int facility); void RemoteSysLog(int log_priority, const char *log_string); #endif cfengine-3.6.2/libpromises/files_interfaces.h0000644000175100017510000000274512352022221021021 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_INTERFACES_H #define CFENGINE_FILES_INTERFACES_H #include #include /* AgentConnection */ int cf_lstat(const char *file, struct stat *buf, FileCopy fc, AgentConnection *conn); /** * @brief Works exactly like posix 'getline', EXCEPT it does not include carriage return at the end. * @return -1 on error OR EOF, so check. Or bytes in buff without null terminator. */ ssize_t CfReadLine(char **buff, size_t *size, FILE *fp); #endif cfengine-3.6.2/libpromises/mod_access.c0000644000175100017510000002013712316547775017634 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* This file can act as a template for adding functionality to cfengine 3. All functionality can be added by extending the main array CF_MOD_PROMISE_TYPES[CF3_MODULES] and its array dimension, in mod_common, in the manner shown here. */ #include #include #include #include /* Read this module file backwards, as dependencies have to be defined first - these arrays declare pairs of constraints lval => rval in the form (lval,type,range) If the type is cf_body then the range is a pointer to another array of pairs, like in a body "sub-routine" */ static const char *const POLICY_ERROR_WRONG_RESOURCE_FOR_DATA_SELECT = "Constraint report_data_select is allowed only for 'query' resource_type"; static bool AccessParseTreeCheck(const Promise *pp, Seq *errors); static const ConstraintSyntax report_data_select_constraints[] = { ConstraintSyntaxNewStringList("classes_include", CF_ANYSTRING, "List of regex filters for class names to be included into class report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("classes_exclude", CF_ANYSTRING, "List of regex filters for class names to be excluded from class report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("variables_include", CF_ANYSTRING, "List of regex filters for variable full qualified path to be included into variables report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("variables_exclude", CF_ANYSTRING, "List of regex filters for variable full qualified path to be excluded from variables report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("promise_notkept_log_include", CF_ANYSTRING, "List of regex filters for handle name to be included into promise not kept log report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("promise_notkept_log_exclude", CF_ANYSTRING, "List of regex filters for handle name to be excluded from promise not kept log report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("promise_repaired_log_include", CF_ANYSTRING, "List of regex filters for handle name to be included into promise repaired log report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("promise_repaired_log_exclude", CF_ANYSTRING, "List of regex filters for handle name to be excluded from promise repaired log report", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("monitoring_include", CF_ANYSTRING, "List of regex filters for slot name to be included from monitoring report", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("monitoring_exclude", CF_ANYSTRING, "List of regex filters for slot name to be excluded from monitoring report", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("metatags_include", CF_ANYSTRING, "List of regex filters for metatags to be included into reports", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("metatags_exclude", CF_ANYSTRING, "List of regex filters for metatags to be excluded from reports", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("promise_handle_include", CF_ANYSTRING, "List of regex filters for promise handle to be included into reports", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("promise_handle_exclude", CF_ANYSTRING, "List of regex filters for promise handle to be excluded from reports", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax report_data_select_body = BodySyntaxNew("report_data_select", report_data_select_constraints, NULL, SYNTAX_STATUS_NORMAL); const ConstraintSyntax CF_REMACCESS_BODIES[REMOTE_ACCESS_NONE + 1] = { ConstraintSyntaxNewStringList("admit", "", "List of host names or IP addresses to grant access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("deny", "", "List of host names or IP addresses to deny access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("admit_ips", "", "List of IP addresses or subnet masks to grant access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("deny_ips", "", "List of IP addresses or subnet masks to deny access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("admit_hostnames", "", "List of hostnames to grant access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("deny_hostnames", "", "List of hostnames to deny access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("admit_keys", "", "List of host keys that will be granted access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("deny_keys", "", "List of host keys that will be denied access to file objects", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("maproot", "", "List of host names or IP addresses to grant full read-privilege on the server", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBool("ifencrypted", "true/false whether the current file access promise is conditional on the connection from the client being encrypted. Default value: false", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("resource_type", "path,literal,context,query,variable", "The type of object being granted access (the default grants access to files)", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewBody("report_data_select", &report_data_select_body, "Report content filter", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("shortcut", "", "For path resource_type, the server will expand a relative path beginning with this text", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const ConstraintSyntax CF_REMROLE_BODIES[REMOTE_ROLE_NONE + 1] = { ConstraintSyntaxNewStringList("authorize", "", "List of public-key user names that are allowed to activate the promised class during remote agent activation", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_REMACCESS_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("server", "access", CF_REMACCESS_BODIES, &AccessParseTreeCheck, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNew("server", "roles", CF_REMROLE_BODIES, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; static bool AccessParseTreeCheck(const Promise *pp, Seq *errors) { bool success = true; bool isResourceType = false; bool isReportDataSelect = false; Constraint *data_select_const = NULL; for (size_t i = 0; i conlist); i++) { Constraint *con = SeqAt(pp->conlist, i); if (StringSafeCompare("resource_type", con->lval) == 0) { if (con->rval.type == RVAL_TYPE_SCALAR) { if (StringSafeCompare("query", (char*)con->rval.item) == 0) { isResourceType = true; } } } else if (StringSafeCompare("report_data_select", con->lval) == 0) { data_select_const = con; isReportDataSelect = true; } } if (isReportDataSelect && !isResourceType) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, data_select_const, POLICY_ERROR_WRONG_RESOURCE_FOR_DATA_SELECT)); success = false; } return success; } cfengine-3.6.2/libpromises/mod_databases.c0000664000175100017510000000617712411001073020300 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax database_server_constraints[] = { ConstraintSyntaxNewString("db_server_owner", "", "User name for database connection", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("db_server_password", "", "Clear text password for database connection", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("db_server_host", "", "Hostname or address for connection to database, blank means localhost", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("db_server_type", "postgres,mysql", "The dialect of the database server. Default value: none", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewString("db_server_connection_db", "", "The name of an existing database to connect to in order to create/manage other databases", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; static const BodySyntax database_server_body = BodySyntaxNew("database_server", database_server_constraints, NULL, SYNTAX_STATUS_NORMAL); static const ConstraintSyntax databases_constraints[] = { ConstraintSyntaxNewBody("database_server", &database_server_body, "Credentials for connecting to a local/remote database server", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("database_type", "sql,ms_registry", "The type of database that is to be manipulated. Default value: none", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewOption("database_operation", "create,delete,drop,cache,verify,restore", "The nature of the promise - to be or not to be", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("database_columns", ".*", "A list of column definitions to be promised by SQL databases", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("database_rows", ".*,.*", "An ordered list of row values to be promised by SQL databases", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewStringList("registry_exclude", "", "A list of regular expressions to ignore in key/value verification", SYNTAX_STATUS_NORMAL), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_DATABASES_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("agent", "databases", databases_constraints, NULL, SYNTAX_STATUS_NORMAL), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/files_hashes.h0000664000175100017510000000342512400110676020155 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_HASHES_H #define CFENGINE_FILES_HASHES_H #include /* Enough room for "SHA=asdfasdfasdf". */ #define CF_HOSTKEY_STRING_SIZE (4 + 2 * EVP_MAX_MD_SIZE + 1) void HashFile(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type); void HashString(const char *buffer, int len, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type); int HashesMatch(const unsigned char digest1[EVP_MAX_MD_SIZE + 1], const unsigned char digest2[EVP_MAX_MD_SIZE + 1], HashMethod type); char *HashPrintSafe(char *dst, size_t dst_size, const unsigned char *digest, HashMethod type, bool use_prefix); char *SkipHashType(char *hash); void HashPubKey(RSA *key, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type); #endif cfengine-3.6.2/libpromises/sort.c0000644000175100017510000002706512352022221016500 0ustar00a10038a1003800000000000000/*******************************************************************/ /* The following sort functions are trivial rewrites of merge-sort * implementation by Simon Tatham * copyright 2001 Simon Tatham. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include typedef bool (*LessFn)(void *lhs, void *rhs, void *ctx); typedef void * (*GetNextElementFn)(void *element); typedef void (*PutNextElementFn)(void *element, void *next); static void *Sort(void *list, LessFn less, GetNextElementFn next, PutNextElementFn putnext, void *ctx) { void *p, *q, *e, *tail; int insize, nmerges, psize, qsize, i; if (list == NULL) { return NULL; } insize = 1; while (true) { p = list; list = NULL; tail = NULL; nmerges = 0; /* count number of merges we do in this pass */ while (p) { nmerges++; /* there exists a merge to be done */ /* step `insize' places along from p */ q = p; psize = 0; for (i = 0; i < insize; i++) { psize++; q = next(q); if (!q) { break; } } /* if q hasn't fallen off end, we have two lists to merge */ qsize = insize; /* now we have two lists; merge them */ while ((psize > 0) || ((qsize > 0) && q)) { /* decide whether next element of merge comes from p or q */ if (psize == 0) { /* p is empty; e must come from q. */ e = q; q = next(q); qsize--; } else if ((qsize == 0) || (!q)) { /* q is empty; e must come from p. */ e = p; p = next(p); psize--; } else if (less(p, q, ctx)) { /* First element of p is lower (or same); * e must come from p. */ e = p; p = next(p); psize--; } else { /* First element of q is lower; e must come from q. */ e = q; q = next(q); qsize--; } /* add the next element to the merged list */ if (tail) { putnext(tail, e); } else { list = e; } tail = e; } /* now p has stepped `insize' places along, and q has too */ p = q; } putnext(tail, NULL); /* If we have done only one merge, we're finished. */ if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ { return list; } /* Otherwise repeat, merging lists twice the size */ insize *= 2; } } /* Item* callbacks */ static bool ItemNameLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return strcmp(((Item*)lhs)->name, ((Item*)rhs)->name) < 0; } static bool ItemClassesLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return strcmp(((Item*)lhs)->classes, ((Item*)rhs)->classes) < 0; } static bool ItemCounterMore(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return ((Item*)lhs)->counter > ((Item*)rhs)->counter; } static bool ItemTimeMore(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return ((Item*)lhs)->time > ((Item*)rhs)->time; } static void *ItemGetNext(void *element) { return ((Item*)element)->next; } static void ItemPutNext(void *element, void *next) { ((Item*)element)->next = (Item *)next; } /* Item* sorting */ Item *SortItemListNames(Item *list) { return Sort(list, &ItemNameLess, &ItemGetNext, &ItemPutNext, NULL); } Item *SortItemListClasses(Item *list) { return Sort(list, &ItemClassesLess, &ItemGetNext, &ItemPutNext, NULL); } Item *SortItemListCounters(Item *list) { return Sort(list, &ItemCounterMore, &ItemGetNext, &ItemPutNext, NULL); } Item *SortItemListTimes(Item *list) { return Sort(list, &ItemTimeMore, &ItemGetNext, &ItemPutNext, NULL); } /* Rlist* and String* callbacks */ static bool RlistCustomItemLess(void *lhs_, void *rhs_, void *ctx) { Rlist *lhs = lhs_; Rlist *rhs = rhs_; int (*cmp)() = ctx; return (*cmp)(lhs->val.item, rhs->val.item); } static bool RlistItemLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return strcmp(((Rlist*)lhs)->val.item, ((Rlist*)rhs)->val.item) < 0; } static bool StringItemLess(const char *lhs, const char *rhs, ARG_UNUSED void *ctx) { return strcmp(lhs, rhs) < 0; } static bool StringItemNumberLess(const char *lhs, const char *rhs, ARG_UNUSED void *ctx, bool int_mode) { char remainder[CF_BUFSIZE]; double left; double right; bool matched_left = sscanf(lhs, "%lf", &left) > 0; bool matched_right = sscanf(rhs, "%lf", &right) > 0; if (!matched_left) { matched_left = sscanf(lhs, "%lf%s", &left, remainder) > 0; } if (!matched_right) { matched_right = sscanf(rhs, "%lf%s", &right, remainder) > 0; } if (matched_left && matched_right) { if (int_mode) { return ((long int)left) - ((long int)right) < 0; } else { return left - right < 0; } } if (matched_left) { return false; } if (matched_right) { return true; } // neither item matched return StringItemLess(lhs, rhs, ctx); } static bool RlistItemNumberLess(void *lhs, void *rhs, ARG_UNUSED void *ctx, bool int_mode) { return StringItemNumberLess(RlistScalarValue((Rlist*)lhs), RlistScalarValue((Rlist*)rhs), ctx, int_mode); } static bool RlistItemIntLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return RlistItemNumberLess(lhs, rhs, ctx, true); } static bool RlistItemRealLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return RlistItemNumberLess(lhs, rhs, ctx, false); } static bool StringItemIPLess(const char *left_item, const char *right_item, ARG_UNUSED void *ctx) { Buffer *left_buffer = BufferNewFrom(left_item, strlen(left_item)); Buffer *right_buffer = BufferNewFrom(right_item, strlen(right_item)); IPAddress *left = IPAddressNew(left_buffer); IPAddress *right = IPAddressNew(right_buffer); bool matched_left = left != NULL; bool matched_right = right != NULL; BufferDestroy(left_buffer); BufferDestroy(right_buffer); if (matched_left && matched_right) { int less = IPAddressCompareLess(left, right); IPAddressDestroy(&left); IPAddressDestroy(&right); return less; } IPAddressDestroy(&left); IPAddressDestroy(&right); if (matched_left) { return false; } if (matched_right) { return true; } // neither item matched return StringItemLess(left_item, right_item, ctx); } static bool RlistItemIPLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return StringItemIPLess(RlistScalarValue((Rlist*)lhs), RlistScalarValue((Rlist*)rhs), ctx); } static long ParseEtherAddress(const char* input, unsigned char *addr) { if (strlen(input) > 12) { return sscanf(input, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); } return sscanf(input, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]); } static bool StringItemMACLess(const char *lhs, const char *rhs, ARG_UNUSED void *ctx) { int bytes = 6; unsigned char left[bytes], right[bytes]; int matched_left = 6 == ParseEtherAddress(lhs, left); int matched_right = 6 == ParseEtherAddress(rhs, right); if (matched_left && matched_right) { int difference = memcmp(left, right, bytes); if (difference != 0) return difference < 0; } if (matched_left) { return false; } if (matched_right) { return true; } // neither item matched return StringItemLess(lhs, rhs, ctx); } static bool RlistItemMACLess(void *lhs, void *rhs, ARG_UNUSED void *ctx) { return StringItemMACLess(RlistScalarValue((Rlist*)lhs), RlistScalarValue((Rlist*)rhs), ctx); } static void *RlistGetNext(void *element) { return ((Rlist*)element)->next; } static void RlistPutNext(void *element, void *next) { ((Rlist*)element)->next = (Rlist *)next; } /* Rlist* sorting */ Rlist *SortRlist(Rlist *list, int (*CompareItems) ()) { return Sort(list, &RlistCustomItemLess, &RlistGetNext, &RlistPutNext, CompareItems); } Rlist *AlphaSortRListNames(Rlist *list) { return Sort(list, &RlistItemLess, &RlistGetNext, &RlistPutNext, NULL); } Rlist *IntSortRListNames(Rlist *list) { return Sort(list, &RlistItemIntLess, &RlistGetNext, &RlistPutNext, NULL); } Rlist *RealSortRListNames(Rlist *list) { return Sort(list, &RlistItemRealLess, &RlistGetNext, &RlistPutNext, NULL); } Rlist *IPSortRListNames(Rlist *list) { return Sort(list, &RlistItemIPLess, &RlistGetNext, &RlistPutNext, NULL); } Rlist *MACSortRListNames(Rlist *list) { return Sort(list, &RlistItemMACLess, &RlistGetNext, &RlistPutNext, NULL); } bool GenericItemLess(const char *sort_type, void *lhs, void *rhs) { if (strcmp(sort_type, "int") == 0) { return RlistItemNumberLess(lhs, rhs, NULL, true); } else if (strcmp(sort_type, "real") == 0) { return RlistItemNumberLess(lhs, rhs, NULL, false); } else if (strcasecmp(sort_type, "IP") == 0) { return RlistItemIPLess(lhs, rhs, NULL); } else if (strcasecmp(sort_type, "MAC") == 0) { return RlistItemMACLess(lhs, rhs, NULL); } // "lex" return RlistItemLess(lhs, rhs, NULL); } bool GenericStringItemLess(const char *sort_type, const char *lhs, const char *rhs) { if (strcmp(sort_type, "int") == 0) { return StringItemNumberLess(lhs, rhs, NULL, true); } else if (strcmp(sort_type, "real") == 0) { return StringItemNumberLess(lhs, rhs, NULL, false); } else if (strcasecmp(sort_type, "IP") == 0) { return StringItemIPLess(lhs, rhs, NULL); } else if (strcasecmp(sort_type, "MAC") == 0) { return StringItemMACLess(lhs, rhs, NULL); } // "lex" return StringItemLess(lhs, rhs, NULL); } cfengine-3.6.2/libpromises/crypto.c0000664000175100017510000004562412411001073017032 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* ERR_* */ #include /* RAND_* */ #include /* BN_* */ #include #include #include #include #include #include #include #include #include #include /* UnexpectedError,ProgrammingError */ #include #ifdef DARWIN // On Mac OSX 10.7 and later, majority of functions in /usr/include/openssl/crypto.h // are deprecated. No known replacement, so shutting up compiler warnings #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif /* The deprecated is the easy way to setup threads for OpenSSL. */ #ifdef OPENSSL_NO_DEPRECATED void CRYPTO_set_id_callback(unsigned long (*func)(void)); #endif static void RandomSeed(void); static void SetupOpenSSLThreadLocks(void); static void CleanupOpenSSLThreadLocks(void); LogLevel CryptoGetMissingKeyLogLevel(); /* TODO move crypto.[ch] to libutils. Will need to remove all manipulation of * lastseen db. */ static bool crypto_initialized = false; /* GLOBAL_X */ const char *CryptoLastErrorString() { const char *errmsg = ERR_reason_error_string(ERR_get_error()); return (errmsg != NULL) ? errmsg : "no error message"; } void CryptoInitialize() { if (!crypto_initialized) { SetupOpenSSLThreadLocks(); OpenSSL_add_all_algorithms(); OpenSSL_add_all_digests(); ERR_load_crypto_strings(); RandomSeed(); crypto_initialized = true; } } void CryptoDeInitialize() { if (crypto_initialized) { EVP_cleanup(); CleanupOpenSSLThreadLocks(); // TODO: Is there an ERR_unload_crypto_strings() ? // TODO: Are there OpenSSL_clear_all_{digests,algorithms} ? crypto_initialized = false; } } static void RandomSeed(void) { /* 1. Seed the weak C PRNGs. */ /* Mix various stuff. */ pid_t pid = getpid(); size_t fqdn_len = strlen(VFQNAME) > 0 ? strlen(VFQNAME) : 1; time_t start_time = CFSTARTTIME; time_t now = time(NULL); srand((unsigned) pid * start_time ^ (unsigned) fqdn_len * now); srand48((long) pid * start_time ^ (long) fqdn_len * now); /* 2. Seed the strong OpenSSL PRNG. */ /* randseed file is written by cf-key. */ char randfile[CF_BUFSIZE]; snprintf(randfile, CF_BUFSIZE, "%s%crandseed", CFWORKDIR, FILE_SEPARATOR); Log(LOG_LEVEL_VERBOSE, "Looking for a source of entropy in '%s'", randfile); if (!RAND_load_file(randfile, -1)) { Log(LOG_LEVEL_VERBOSE, "Could not read sufficient randomness from '%s'", randfile); } #ifndef __MINGW32__ /* windows may hang */ RAND_poll(); #else RAND_screen(); #endif /* We should have had enough entropy by now. Else we print a message and * use non-crypto-safe random data. */ if (RAND_status() != 1) { /* TODO raise to LOG_LEVEL_WARNING? */ Log(LOG_LEVEL_INFO, "PRNG hasn't been seeded enough, using some pseudo-random bytes for seed!"); Log(LOG_LEVEL_INFO, "A workaround is to copy 1KB of random bytes to '%s'", randfile); unsigned char rand_buf[128]; for (size_t i = 0; i < sizeof(rand_buf); i++) { rand_buf[i] = rand() % 256; } RAND_seed(rand_buf, sizeof(rand_buf)); /* If we *still* do not have enough entropy, then things will be * failing all over the place. Should never happen because of the * rand() buffer above which should be enough for all cases. */ if (RAND_status() != 1) { UnexpectedError("Low entropy, crypto operations will fail! " "See verbose log and report which platform you are using."); } } } static const char *const priv_passphrase = "Cfengine passphrase"; /** * @return true the error is not so severe that we must stop */ bool LoadSecretKeys(void) { { char *privkeyfile = PrivateKeyFile(GetWorkDir()); FILE *fp = fopen(privkeyfile, "r"); if (!fp) { Log(CryptoGetMissingKeyLogLevel(), "Couldn't find a private key at '%s', use cf-key to get one. (fopen: %s)", privkeyfile, GetErrorStr()); free(privkeyfile); return false; } if ((PRIVKEY = PEM_read_RSAPrivateKey(fp, (RSA **) NULL, NULL, (void *)priv_passphrase)) == NULL) { Log(LOG_LEVEL_ERR, "Error reading private key. (PEM_read_RSAPrivateKey: %s)", CryptoLastErrorString()); PRIVKEY = NULL; fclose(fp); return false; } fclose(fp); Log(LOG_LEVEL_VERBOSE, "Loaded private key at '%s'", privkeyfile); free(privkeyfile); } { char *pubkeyfile = PublicKeyFile(GetWorkDir()); FILE *fp = fopen(pubkeyfile, "r"); if (!fp) { Log(CryptoGetMissingKeyLogLevel(), "Couldn't find a public key at '%s', use cf-key to get one (fopen: %s)", pubkeyfile, GetErrorStr()); free(pubkeyfile); return false; } PUBKEY = PEM_read_RSAPublicKey(fp, NULL, NULL, (void *)priv_passphrase); if (NULL == PUBKEY) { Log(LOG_LEVEL_ERR, "Error reading public key at '%s'. (PEM_read_RSAPublicKey: %s)", pubkeyfile, CryptoLastErrorString()); fclose(fp); free(pubkeyfile); return false; } Log(LOG_LEVEL_VERBOSE, "Loaded public key '%s'", pubkeyfile); free(pubkeyfile); fclose(fp); } if (NULL != PUBKEY && ((BN_num_bits(PUBKEY->e) < 2) || (!BN_is_odd(PUBKEY->e)))) { Log(LOG_LEVEL_ERR, "The public key RSA exponent is too small or not odd"); return false; } return true; } void PolicyHubUpdateKeys(const char *policy_server) { if (GetAmPolicyHub(CFWORKDIR) && NULL != PUBKEY) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; char dst_public_key_filename[CF_BUFSIZE] = ""; { char buffer[CF_HOSTKEY_STRING_SIZE]; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); snprintf(dst_public_key_filename, sizeof(dst_public_key_filename), "%s/ppkeys/%s-%s.pub", CFWORKDIR, "root", HashPrintSafe(buffer, sizeof(buffer), digest, CF_DEFAULT_DIGEST, true)); MapName(dst_public_key_filename); } struct stat sb; if ((stat(dst_public_key_filename, &sb) == -1)) { char src_public_key_filename[CF_BUFSIZE] = ""; snprintf(src_public_key_filename, CF_MAXVARSIZE, "%s/ppkeys/localhost.pub", CFWORKDIR); MapName(src_public_key_filename); // copy localhost.pub to root-HASH.pub on policy server if (!LinkOrCopy(src_public_key_filename, dst_public_key_filename, false)) { Log(LOG_LEVEL_ERR, "Unable to copy policy server's own public key from '%s' to '%s'", src_public_key_filename, dst_public_key_filename); } if (policy_server) { LastSaw(policy_server, digest, LAST_SEEN_ROLE_CONNECT); } } } } /*********************************************************************/ /** * @brief Search for a key just like HavePublicKey(), but get the * hash value from lastseen db. * @return NULL if the key was not found in any form. */ RSA *HavePublicKeyByIP(const char *username, const char *ipaddress) { char hash[CF_HOSTKEY_STRING_SIZE]; bool found = Address2Hostkey(hash, sizeof(hash), ipaddress); if (found) { return HavePublicKey(username, ipaddress, hash); } else { Log(LOG_LEVEL_VERBOSE, "Key for host '%s' not found in lastseen db", ipaddress); return HavePublicKey(username, ipaddress, ""); } } static const char *const pub_passphrase = "public"; /** * @brief Search for a key: * 1. username-hash.pub * 2. username-ip.pub * @return NULL if key not found in any form */ RSA *HavePublicKey(const char *username, const char *ipaddress, const char *digest) { char keyname[CF_MAXVARSIZE], newname[CF_BUFSIZE], oldname[CF_BUFSIZE]; struct stat statbuf; FILE *fp; RSA *newkey = NULL; snprintf(keyname, CF_MAXVARSIZE, "%s-%s", username, digest); snprintf(newname, CF_BUFSIZE, "%s/ppkeys/%s.pub", CFWORKDIR, keyname); MapName(newname); if (stat(newname, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "Did not find new key format '%s'", newname); snprintf(oldname, CF_BUFSIZE, "%s/ppkeys/%s-%s.pub", CFWORKDIR, username, ipaddress); MapName(oldname); Log(LOG_LEVEL_VERBOSE, "Trying old style '%s'", oldname); if (stat(oldname, &statbuf) == -1) { Log(LOG_LEVEL_DEBUG, "Did not have old-style key '%s'", oldname); return NULL; } if (strlen(digest) > 0) { Log(LOG_LEVEL_INFO, "Renaming old key from '%s' to '%s'", oldname, newname); if (rename(oldname, newname) != 0) { Log(LOG_LEVEL_ERR, "Could not rename from old key format '%s' to new '%s'. (rename: %s)", oldname, newname, GetErrorStr()); } } else { /* We don't know the digest (e.g. because we are a client and have no lastseen-map yet), so we're using old file format (root-IP.pub). */ Log(LOG_LEVEL_VERBOSE, "We have no digest yet, using old keyfile name: %s", oldname); snprintf(newname, sizeof(newname), "%s", oldname); } } if ((fp = fopen(newname, "r")) == NULL) { Log(CryptoGetMissingKeyLogLevel(), "Couldn't find a public key '%s'. (fopen: %s)", newname, GetErrorStr()); return NULL; } if ((newkey = PEM_read_RSAPublicKey(fp, NULL, NULL, (void *)pub_passphrase)) == NULL) { Log(LOG_LEVEL_ERR, "Error reading public key. (PEM_read_RSAPublicKey: %s)", CryptoLastErrorString()); fclose(fp); return NULL; } fclose(fp); if ((BN_num_bits(newkey->e) < 2) || (!BN_is_odd(newkey->e))) { Log(LOG_LEVEL_ERR, "RSA Exponent too small or not odd"); RSA_free(newkey); return NULL; } return newkey; } /*********************************************************************/ void SavePublicKey(const char *user, const char *digest, const RSA *key) { char keyname[CF_MAXVARSIZE], filename[CF_BUFSIZE]; struct stat statbuf; FILE *fp; int ret; ret = snprintf(keyname, sizeof(keyname), "%s-%s", user, digest); if (ret >= sizeof(keyname)) { Log(LOG_LEVEL_ERR, "USERNAME-KEY (%s-%s) string too long!", user, digest); return; } ret = snprintf(filename, sizeof(filename), "%s/ppkeys/%s.pub", CFWORKDIR, keyname); if (ret >= sizeof(filename)) { Log(LOG_LEVEL_ERR, "Filename too long!"); return; } MapName(filename); if (stat(filename, &statbuf) != -1) { return; } Log(LOG_LEVEL_VERBOSE, "Saving public key to file '%s'", filename); if ((fp = fopen(filename, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Unable to write a public key '%s'. (fopen: %s)", filename, GetErrorStr()); return; } if (!PEM_write_RSAPublicKey(fp, key)) { Log(LOG_LEVEL_ERR, "Error saving public key to '%s'. (PEM_write_RSAPublicKey: %s)", filename, CryptoLastErrorString()); } fclose(fp); } int EncryptString(char type, const char *in, char *out, unsigned char *key, int plainlen) { int cipherlen = 0, tmplen; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; EVP_CIPHER_CTX ctx; if (key == NULL) ProgrammingError("EncryptString: session key == NULL"); EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, CfengineCipher(type), NULL, key, iv); if (!EVP_EncryptUpdate(&ctx, out, &cipherlen, in, plainlen)) { EVP_CIPHER_CTX_cleanup(&ctx); return -1; } if (!EVP_EncryptFinal_ex(&ctx, out + cipherlen, &tmplen)) { EVP_CIPHER_CTX_cleanup(&ctx); return -1; } cipherlen += tmplen; EVP_CIPHER_CTX_cleanup(&ctx); return cipherlen; } /*********************************************************************/ int DecryptString(char type, const char *in, char *out, unsigned char *key, int cipherlen) { int plainlen = 0, tmplen; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; EVP_CIPHER_CTX ctx; if (key == NULL) ProgrammingError("DecryptString: session key == NULL"); EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, CfengineCipher(type), NULL, key, iv); if (!EVP_DecryptUpdate(&ctx, out, &plainlen, in, cipherlen)) { Log(LOG_LEVEL_ERR, "Failed to decrypt string"); EVP_CIPHER_CTX_cleanup(&ctx); return -1; } if (!EVP_DecryptFinal_ex(&ctx, out + plainlen, &tmplen)) { unsigned long err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Failed to decrypt at final of cipher length %d. (EVP_DecryptFinal_ex: %s)", cipherlen, ERR_error_string(err, NULL)); EVP_CIPHER_CTX_cleanup(&ctx); return -1; } plainlen += tmplen; EVP_CIPHER_CTX_cleanup(&ctx); return plainlen; } /*********************************************************************/ void DebugBinOut(char *buffer, int len, char *comment) { unsigned char *sp; char buf[CF_BUFSIZE]; char hexStr[3]; // one byte as hex if (len >= (sizeof(buf) / 2)) // hex uses two chars per byte { Log(LOG_LEVEL_DEBUG, "Debug binary print is too large (len = %d)", len); return; } memset(buf, 0, sizeof(buf)); for (sp = buffer; sp < (unsigned char *) (buffer + len); sp++) { xsnprintf(hexStr, sizeof(hexStr), "%2.2x", (int) *sp); strcat(buf, hexStr); } Log(LOG_LEVEL_VERBOSE, "BinaryBuffer, %d bytes, comment '%s', buffer '%s'", len, comment, buf); } char *PublicKeyFile(const char *workdir) { char *keyfile; xasprintf(&keyfile, "%s" FILE_SEPARATOR_STR "ppkeys" FILE_SEPARATOR_STR "localhost.pub", workdir); return keyfile; } char *PrivateKeyFile(const char *workdir) { char *keyfile; xasprintf(&keyfile, "%s" FILE_SEPARATOR_STR "ppkeys" FILE_SEPARATOR_STR "localhost.priv", workdir); return keyfile; } LogLevel CryptoGetMissingKeyLogLevel(void) { if (getuid() == 0 && NULL == getenv("FAKEROOTKEY") && NULL == getenv("CFENGINE_TEST_OVERRIDE_WORKDIR")) { return LOG_LEVEL_ERR; } else { return LOG_LEVEL_VERBOSE; } } /********************************************************************* * Functions for threadsafe OpenSSL usage * * Only pthread support - we don't create threads with any other API * *********************************************************************/ static pthread_mutex_t *cf_openssl_locks = NULL; #ifndef __MINGW32__ unsigned long ThreadId_callback(void) { return (unsigned long) pthread_self(); } #endif static void OpenSSLLock_callback(int mode, int index, char *file, int line) { if (mode & CRYPTO_LOCK) { int ret = pthread_mutex_lock(&(cf_openssl_locks[index])); if (ret != 0) { Log(LOG_LEVEL_ERR, "OpenSSL locking failure at %s:%d! (pthread_mutex_lock: %s)", file, line, GetErrorStrFromCode(ret)); } } else { int ret = pthread_mutex_unlock(&(cf_openssl_locks[index])); if (ret != 0) { Log(LOG_LEVEL_ERR, "OpenSSL locking failure at %s:%d! (pthread_mutex_unlock: %s)", file, line, GetErrorStrFromCode(ret)); } } } static void SetupOpenSSLThreadLocks(void) { const int num_locks = CRYPTO_num_locks(); assert(cf_openssl_locks == NULL); cf_openssl_locks = xmalloc(num_locks * sizeof(*cf_openssl_locks)); for (int i = 0; i < num_locks; i++) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); int ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); if (ret != 0) { Log(LOG_LEVEL_ERR, "Failed to use error-checking mutexes for openssl," " falling back to normal ones (pthread_mutexattr_settype: %s)", GetErrorStrFromCode(ret)); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); } ret = pthread_mutex_init(&cf_openssl_locks[i], &attr); if (ret != 0) { Log(LOG_LEVEL_CRIT, "Failed to use initialise mutexes for openssl" " (pthread_mutex_init: %s)!", GetErrorStrFromCode(ret)); } pthread_mutexattr_destroy(&attr); } #ifndef __MINGW32__ CRYPTO_set_id_callback((unsigned long (*)())ThreadId_callback); #endif CRYPTO_set_locking_callback((void (*)())OpenSSLLock_callback); } static void CleanupOpenSSLThreadLocks(void) { const int numLocks = CRYPTO_num_locks(); CRYPTO_set_locking_callback(NULL); #ifndef __MINGW32__ CRYPTO_set_id_callback(NULL); #endif for (int i = 0; i < numLocks; i++) { pthread_mutex_destroy(&(cf_openssl_locks[i])); } free(cf_openssl_locks); cf_openssl_locks = NULL; } cfengine-3.6.2/libpromises/audit.h0000644000175100017510000000301512316547775016643 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_AUDIT_H #define CFENGINE_AUDIT_H /* * This module keeps track of amount and value of promises kept/repaired/not-kept */ #include #include #include void BeginAudit(void); void UpdatePromiseCounters(PromiseResult status); void EndAudit(const EvalContext *ctx, int background_tasks); /* * FatalError causes EndAudit, so don't call it from the low-memory or corrupted stack situations. */ void FatalError(const EvalContext *ctx, char *s, ...) FUNC_ATTR_NORETURN FUNC_ATTR_PRINTF(2, 3); #endif cfengine-3.6.2/libpromises/logic_expressions.h0000664000175100017510000000635412243421446021270 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LOGIC_EXPRESSIONS_H #define CFENGINE_LOGIC_EXPRESSIONS_H # include # include /* Logic expressions grammar: ::= ::= | || ::= . & ::= ! ::= ( ) Basis of logic evaluation is values which are provided by StringExpression and suitable string->bool evaluator. */ typedef enum { LOGICAL_OP_OR, LOGICAL_OP_AND, LOGICAL_OP_NOT, LOGICAL_OP_EVAL } LogicalOp; typedef struct Expression_ Expression; struct Expression_ { LogicalOp op; union { struct { Expression *lhs; Expression *rhs; } andor; struct { Expression *arg; } not; struct { StringExpression *name; } eval; } val; }; /* Parsing and evaluation */ /* * Result of parsing. * * if succeeded, then result is the result of parsing and position is last * character consumed. * * if not succeded, then result is NULL and position is last character consumed * before the error. */ typedef struct { Expression *result; int position; } ParseResult; ParseResult ParseExpression(const char *expr, int start, int end); typedef enum ExpressionValue { EXPRESSION_VALUE_ERROR = -1, EXPRESSION_VALUE_FALSE = false, EXPRESSION_VALUE_TRUE = true, } ExpressionValue; /* * Evaluator should return FALSE, TRUE or ERROR if unable to parse result. In * later case evaluation will be aborted and ERROR will be returned from * EvalExpression. */ typedef ExpressionValue(*NameEvaluator) (const char *name, void *param); /* * Result is heap-allocated. In case evalfn() returns ERROR whole * EvalExpression returns ERROR as well. */ ExpressionValue EvalExpression(const Expression *expr, NameEvaluator nameevalfn, VarRefEvaluator varrefevalfn, void *param); /* * Frees Expression produced by ParseExpression. NULL-safe. */ void FreeExpression(Expression *expr); #endif cfengine-3.6.2/libpromises/cf3parse.h0000664000175100017510000000476512405556127017250 0ustar00a10038a1003800000000000000/* A Bison parser, made by GNU Bison 3.0.2. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 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, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef YY_YY_CF_PARSE_H_INCLUDED # define YY_YY_CF_PARSE_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { IDSYNTAX = 258, BLOCKID = 259, QSTRING = 260, CLASS = 261, PROMISE_TYPE = 262, BUNDLE = 263, BODY = 264, ASSIGN = 265, ARROW = 266, NAKEDVAR = 267, OP = 268, CP = 269, OB = 270, CB = 271 }; #endif /* Tokens. */ #define IDSYNTAX 258 #define BLOCKID 259 #define QSTRING 260 #define CLASS 261 #define PROMISE_TYPE 262 #define BUNDLE 263 #define BODY 264 #define ASSIGN 265 #define ARROW 266 #define NAKEDVAR 267 #define OP 268 #define CP 269 #define OB 270 #define CB 271 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; int yyparse (void); #endif /* !YY_YY_CF_PARSE_H_INCLUDED */ cfengine-3.6.2/libpromises/mod_knowledge.c0000664000175100017510000001540612243421446020340 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const ConstraintSyntax association_constraints[] = { ConstraintSyntaxNewString("forward_relationship", "", "Name of forward association between promiser topic and associates", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewString("backward_relationship", "", "Name of backward/inverse association from associates to promiser topic", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("associates", "", "List of associated topics by this forward relationship", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; static const BodySyntax association_body = BodySyntaxNew("association", association_constraints, NULL, SYNTAX_STATUS_REMOVED); static const ConstraintSyntax topics_constraints[] = { ConstraintSyntaxNewBody("association", &association_body, "Declare associated topics", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("synonyms", "", "A list of words to be treated as equivalents in the defined context", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("generalizations", "", "A list of words to be treated as super-sets for the current topic, used when reasoning", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; static const ConstraintSyntax occurrences_constraints[] = { ConstraintSyntaxNewStringList("about_topics", "", "List of topics that the document or resource addresses", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("represents", "", "List of explanations for what relationship this document has to the topics it is about", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("representation", "literal,url,db,file,web,image,portal", "How to interpret the promiser string e.g. actual data or reference to data", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; static const ConstraintSyntax things_constraints[] = { ConstraintSyntaxNewStringList("synonyms", "", "A list of words to be treated as equivalents in the defined context", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("affects", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("belongs_to", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("causes", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewOption("certainty", "certain,uncertain,possible", "Selects the level of certainty for the proposed knowledge, for use in inferential reasoning", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("determines", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("generalizations", "", "A list of words to be treated as super-sets for the current topic, used when reasoning", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("implements", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("involves", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_caused_by", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_connected_to", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_determined_by", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_followed_by", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_implemented_by", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_located_in", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_measured_by", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_part_of", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("is_preceded_by", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("measures", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("needs", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("provides", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("uses", "", "Special fixed relation for describing topics that are things", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; static const ConstraintSyntax inferences_constraints[] = { ConstraintSyntaxNewStringList("precedents", "", "The foundational vector for a trinary inference", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewStringList("qualifiers", "", "The second vector in a trinary inference", SYNTAX_STATUS_REMOVED), ConstraintSyntaxNewNull() }; const PromiseTypeSyntax CF_KNOWLEDGE_PROMISE_TYPES[] = { PromiseTypeSyntaxNew("knowledge", "inferences", inferences_constraints, NULL, SYNTAX_STATUS_REMOVED), PromiseTypeSyntaxNew("knowledge", "things", things_constraints, NULL, SYNTAX_STATUS_REMOVED), PromiseTypeSyntaxNew("knowledge", "topics", topics_constraints, NULL, SYNTAX_STATUS_REMOVED), PromiseTypeSyntaxNew("knowledge", "occurrences", occurrences_constraints, NULL, SYNTAX_STATUS_REMOVED), PromiseTypeSyntaxNewNull() }; cfengine-3.6.2/libpromises/known_dirs.c0000644000175100017510000001225212352557236017701 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #if defined(__CYGWIN__) static const char *GetDefaultWorkDir(void) { return WORKDIR; } static const char *GetDefaultLogDir(void) { return LOGDIR; } static const char *GetDefaultPidDir(void) { return PIDDIR; } static const char *GetDefaultInputDir(void) { return INPUTDIR; } static const char *GetDefaultMasterDir(void) { return MASTERDIR; } #elif defined(__ANDROID__) static const char *GetDefaultWorkDir(void) { /* getpwuid() on Android returns /data, so use compile-time default instead */ return WORKDIR; } static const char *GetDefaultLogDir(void) { return LOGDIR; } static const char *GetDefaultPidDir(void) { return PIDDIR; } static const char *GetDefaultInputDir(void) { return INPUTDIR; } static const char *GetDefaultMasterDir(void) { return MASTERDIR; } #elif !defined(__MINGW32__) #define MAX_WORKDIR_LENGTH (CF_BUFSIZE / 2) static const char *GetDefaultDir_helper(char dir[MAX_WORKDIR_LENGTH], const char *root_dir, const char *append_dir) { if (getuid() > 0) { if (!*dir) { struct passwd *mpw = getpwuid(getuid()); if ( append_dir == NULL ) { if (snprintf(dir, MAX_WORKDIR_LENGTH, "%s/.cfagent", mpw->pw_dir) >= MAX_WORKDIR_LENGTH) { return NULL; } } else { if (snprintf(dir, MAX_WORKDIR_LENGTH, "%s/.cfagent/%s", mpw->pw_dir, append_dir) >= MAX_WORKDIR_LENGTH) { return NULL; } } } return dir; } else { return root_dir; } } static const char *GetDefaultWorkDir(void) { static char workdir[MAX_WORKDIR_LENGTH] = ""; /* GLOBAL_C */ return GetDefaultDir_helper(workdir, WORKDIR, NULL); } static const char *GetDefaultLogDir(void) { static char logdir[MAX_WORKDIR_LENGTH] = ""; /* GLOBAL_C */ return GetDefaultDir_helper(logdir, LOGDIR, NULL); } static const char *GetDefaultPidDir(void) { static char piddir[MAX_WORKDIR_LENGTH] = ""; /* GLOBAL_C */ return GetDefaultDir_helper(piddir, PIDDIR, NULL); } static const char *GetDefaultMasterDir(void) { static char masterdir[MAX_WORKDIR_LENGTH] = ""; /* GLOBAL_C */ return GetDefaultDir_helper(masterdir, MASTERDIR, "masterfiles"); } static const char *GetDefaultInputDir(void) { static char inputdir[MAX_WORKDIR_LENGTH] = ""; /* GLOBAL_C */ return GetDefaultDir_helper(inputdir, INPUTDIR, "inputs"); } #endif const char *GetWorkDir(void) { const char *workdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); return workdir == NULL ? GetDefaultWorkDir() : workdir; } const char *GetLogDir(void) { const char *logdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); return logdir == NULL ? GetDefaultLogDir() : logdir; } const char *GetPidDir(void) { const char *piddir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); return piddir == NULL ? GetDefaultPidDir() : piddir; } const char *GetInputDir(void) { const char *inputdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); if (inputdir != NULL) { static char workbuf[CF_BUFSIZE]; snprintf(workbuf, CF_BUFSIZE, "%s%cinputs", inputdir, FILE_SEPARATOR); return MapName(workbuf); } else if (strcmp(INPUTDIR, "default") == 0 ) { static char workbuf[CF_BUFSIZE]; snprintf(workbuf, CF_BUFSIZE, "%s%cinputs", GetWorkDir(), FILE_SEPARATOR); return MapName(workbuf); } else { return GetDefaultInputDir(); } } const char *GetMasterDir(void) { const char *masterdir = getenv("CFENGINE_TEST_OVERRIDE_WORKDIR"); if (masterdir != NULL) { static char workbuf[CF_BUFSIZE]; snprintf(workbuf, CF_BUFSIZE, "%s%cmasterfiles", masterdir, FILE_SEPARATOR); return MapName(workbuf); } else if (strcmp(MASTERDIR, "default") == 0 ) { static char workbuf[CF_BUFSIZE]; snprintf(workbuf, CF_BUFSIZE, "%s%cmasterfiles", GetWorkDir(), FILE_SEPARATOR); return MapName(workbuf); } else { return GetDefaultMasterDir(); } } cfengine-3.6.2/libpromises/rlist.c0000664000175100017510000010003612400110676016644 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include /* StringHash */ #include /* StringMatchWithPrecompiledRegex,CompileRegex */ #include #include #include #include #include static Rlist *RlistPrependRval(Rlist **start, Rval rval); RvalType DataTypeToRvalType(DataType datatype) { switch (datatype) { case CF_DATA_TYPE_BODY: case CF_DATA_TYPE_BUNDLE: case CF_DATA_TYPE_CONTEXT: case CF_DATA_TYPE_COUNTER: case CF_DATA_TYPE_INT: case CF_DATA_TYPE_INT_RANGE: case CF_DATA_TYPE_OPTION: case CF_DATA_TYPE_REAL: case CF_DATA_TYPE_REAL_RANGE: case CF_DATA_TYPE_STRING: return RVAL_TYPE_SCALAR; case CF_DATA_TYPE_CONTEXT_LIST: case CF_DATA_TYPE_INT_LIST: case CF_DATA_TYPE_OPTION_LIST: case CF_DATA_TYPE_REAL_LIST: case CF_DATA_TYPE_STRING_LIST: return RVAL_TYPE_LIST; case CF_DATA_TYPE_CONTAINER: return RVAL_TYPE_CONTAINER; case CF_DATA_TYPE_NONE: return RVAL_TYPE_NOPROMISEE; } ProgrammingError("DataTypeToRvalType, unhandled"); } char *RlistScalarValue(const Rlist *rlist) { if (rlist->val.type != RVAL_TYPE_SCALAR) { ProgrammingError("Rlist value contains type %c instead of expected scalar", rlist->val.type); } return rlist->val.item; } /*******************************************************************/ FnCall *RlistFnCallValue(const Rlist *rlist) { if (rlist->val.type != RVAL_TYPE_FNCALL) { ProgrammingError("Rlist value contains type %c instead of expected FnCall", rlist->val.type); } return rlist->val.item; } /*******************************************************************/ Rlist *RlistRlistValue(const Rlist *rlist) { if (rlist->val.type != RVAL_TYPE_LIST) { ProgrammingError("Rlist value contains type %c instead of expected List", rlist->val.type); } return rlist->val.item; } /*******************************************************************/ char *RvalScalarValue(Rval rval) { if (rval.type != RVAL_TYPE_SCALAR) { ProgrammingError("Internal error: Rval contains type %c instead of expected scalar", rval.type); } return rval.item; } /*******************************************************************/ FnCall *RvalFnCallValue(Rval rval) { if (rval.type != RVAL_TYPE_FNCALL) { ProgrammingError("Rval contains type %c instead of expected FnCall", rval.type); } return rval.item; } /*******************************************************************/ Rlist *RvalRlistValue(Rval rval) { if (rval.type != RVAL_TYPE_LIST) { ProgrammingError("Rval contain type %c instead of expected List", rval.type); } return rval.item; } /*******************************************************************/ JsonElement *RvalContainerValue(Rval rval) { if (rval.type != RVAL_TYPE_CONTAINER) { ProgrammingError("Rval contain type %c instead of expected container", rval.type); } return rval.item; } const char *RvalTypeToString(RvalType type) { switch (type) { case RVAL_TYPE_CONTAINER: return "data"; case RVAL_TYPE_FNCALL: return "call"; case RVAL_TYPE_LIST: return "list"; case RVAL_TYPE_NOPROMISEE: return "null"; case RVAL_TYPE_SCALAR: return "scalar"; } assert(false && "never reach"); return NULL; } Rlist *RlistKeyIn(Rlist *list, const char *key) { for (Rlist *rp = list; rp != NULL; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR && strcmp(RlistScalarValue(rp), key) == 0) { return rp; } } return NULL; } /*******************************************************************/ bool RlistMatchesRegexRlist(const Rlist *list, const Rlist *search) /* Returns true if "list" contains all the regular expressions in "search". Non-scalars in "list" and "search" are skipped. */ { for (const Rlist *rp = search; rp != NULL; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR && // check for the current element in the search list !RlistMatchesRegex(list, RlistScalarValue(search))) { return false; } } return true; } bool RlistMatchesRegex(const Rlist *list, const char *regex) /* Returns true if any of the "list" of strings matches "regex". Non-scalars in "list" are skipped. */ { if (regex == NULL || list == NULL) { return false; } pcre *rx = CompileRegex(regex); if (!rx) { return false; } for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR && StringMatchFullWithPrecompiledRegex(rx, RlistScalarValue(rp))) { pcre_free(rx); return true; } } pcre_free(rx); return false; } // TODO: cf_null lists should not be needed bool RlistIsNullList(const Rlist *list) { for (const Rlist *rp = list; rp; rp = rp->next) { if (rp->val.type != RVAL_TYPE_SCALAR) { return false; } if (strcmp(CF_NULL_VALUE, RlistScalarValue(rp)) != 0) { return false; } } return true; } bool RlistIsInListOfRegex(const Rlist *list, const char *str) /* Returns true if any of the "list" of regular expressions matches "str". Non-scalars in "list" are skipped. */ { if (str == NULL || list == NULL) { return false; } for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (rp->val.type == RVAL_TYPE_SCALAR && StringMatchFull(RlistScalarValue(rp), str)) { return true; } } return false; } /*******************************************************************/ static Rval RvalCopyScalar(Rval rval) { assert(rval.type == RVAL_TYPE_SCALAR); const char * src = rval.item ? rval.item : ""; return (Rval) {xstrdup(src), RVAL_TYPE_SCALAR}; } Rlist *RlistAppendRval(Rlist **start, Rval rval) { Rlist *rp = xmalloc(sizeof(Rlist)); if (*start == NULL) { *start = rp; } else { Rlist *lp = *start; while (lp->next != NULL) { lp = lp->next; } lp->next = rp; } rp->val = rval; ThreadLock(cft_lock); rp->next = NULL; ThreadUnlock(cft_lock); return rp; } Rval RvalNew(const void *item, RvalType type) { switch (type) { case RVAL_TYPE_SCALAR: return (Rval) { xstrdup(item), RVAL_TYPE_SCALAR }; case RVAL_TYPE_FNCALL: return (Rval) { FnCallCopy(item), RVAL_TYPE_FNCALL }; case RVAL_TYPE_LIST: return (Rval) { RlistCopy(item), RVAL_TYPE_LIST }; case RVAL_TYPE_CONTAINER: return (Rval) { JsonCopy(item), RVAL_TYPE_CONTAINER }; case RVAL_TYPE_NOPROMISEE: return ((Rval) {NULL, type}); } assert(false); return ((Rval) { NULL, RVAL_TYPE_NOPROMISEE }); } Rval RvalCopy(Rval rval) { return RvalNew(rval.item, rval.type); } /*******************************************************************/ Rlist *RlistCopy(const Rlist *rp) { Rlist *start = NULL; while (rp != NULL) { RlistAppendRval(&start, RvalCopy(rp->val)); rp = rp->next; } return start; } /*******************************************************************/ void RlistDestroy(Rlist *rl) /* Delete an rlist and all its references */ { while (rl != NULL) { Rlist *next = rl->next; if (rl->val.item) { RvalDestroy(rl->val); } free(rl); rl = next; } } /*******************************************************************/ Rlist *RlistAppendScalarIdemp(Rlist **start, const char *scalar) { if (RlistKeyIn(*start, scalar)) { return NULL; } return RlistAppendScalar(start, scalar); } Rlist *RlistPrependScalarIdemp(Rlist **start, const char *scalar) { if (RlistKeyIn(*start, scalar)) { return NULL; } return RlistPrepend(start, scalar, RVAL_TYPE_SCALAR); } Rlist *RlistAppendScalar(Rlist **start, const char *scalar) { return RlistAppendRval(start, RvalCopyScalar((Rval) { (char *)scalar, RVAL_TYPE_SCALAR })); } Rlist *RlistAppend(Rlist **start, const void *item, RvalType type) { Rlist *lp = *start; switch (type) { case RVAL_TYPE_SCALAR: return RlistAppendScalar(start, item); case RVAL_TYPE_FNCALL: break; case RVAL_TYPE_LIST: for (const Rlist *rp = item; rp; rp = rp->next) { lp = RlistAppendRval(start, RvalCopy(rp->val)); } return lp; default: Log(LOG_LEVEL_DEBUG, "Cannot append %c to rval-list '%s'", type, (char *) item); return NULL; } Rlist *rp = xmalloc(sizeof(Rlist)); if (*start == NULL) { *start = rp; } else { for (lp = *start; lp->next != NULL; lp = lp->next) { } lp->next = rp; } rp->val = RvalCopy((Rval) {(void *) item, type}); ThreadLock(cft_lock); rp->next = NULL; ThreadUnlock(cft_lock); return rp; } /*******************************************************************/ static Rlist *RlistPrependRval(Rlist **start, Rval rval) { Rlist *rp = xmalloc(sizeof(Rlist)); rp->next = *start; rp->val = rval; ThreadLock(cft_lock); *start = rp; ThreadUnlock(cft_lock); return rp; } Rlist *RlistPrepend(Rlist **start, const void *item, RvalType type) { switch (type) { case RVAL_TYPE_LIST: { Rlist *lp = NULL; for (const Rlist *rp = item; rp; rp = rp->next) { lp = RlistPrependRval(start, RvalCopy(rp->val)); } return lp; } case RVAL_TYPE_SCALAR: case RVAL_TYPE_FNCALL: case RVAL_TYPE_CONTAINER: case RVAL_TYPE_NOPROMISEE: return RlistPrependRval(start, RvalNew(item, type)); } assert(false); return NULL; } /*******************************************************************/ int RlistLen(const Rlist *start) { int count = 0; for (const Rlist *rp = start; rp != NULL; rp = rp->next) { count++; } return count; } /*******************************************************************/ Rlist *RlistParseShown(const char *string) { Rlist *newlist = NULL, *splitlist, *rp; char value[CF_MAXVARSIZE]; /* Parse a string representation generated by ShowList and turn back into Rlist */ splitlist = RlistFromSplitString(string, ','); for (rp = splitlist; rp != NULL; rp = rp->next) { sscanf(RlistScalarValue(rp), "%*[{ '\"]%255[^'\"]", value); RlistAppendScalar(&newlist, value); } RlistDestroy(splitlist); return newlist; } /*******************************************************************/ typedef enum { ST_OPENED, ST_PRECLOSED, ST_CLOSED, ST_IO, ST_ELM1, ST_ELM2, ST_END1, ST_END2, ST_SEP, ST_ERROR } state; #define CLASS_BLANK(x) (((x)==' ')||((x)=='\t')) #define CLASS_START1(x) (((x)=='\'')) #define CLASS_START2(x) (((x)=='"')) #define CLASS_END1(x) ((CLASS_START1(x))) #define CLASS_END2(x) ((CLASS_START2(x))) #define CLASS_BRA1(x) (((x)=='{')) #define CLASS_BRA2(x) (((x)=='}')) #define CLASS_SEP(x) (((x)==',')) #define CLASS_EOL(x) (((x)=='\0')) #define CLASS_ANY0(x) ((!CLASS_BLANK(x))&&(!CLASS_BRA1(x))) #define CLASS_ANY1(x) ((!CLASS_BLANK(x))&&(!CLASS_START1(x))&&(!CLASS_START2(x))) #define CLASS_ANY2(x) ((!CLASS_END1(x))) #define CLASS_ANY3(x) ((!CLASS_END2(x))) #define CLASS_ANY4(x) ((!CLASS_BLANK(x))&&(!CLASS_SEP(x))&&(!CLASS_BRA2(x))) #define CLASS_ANY5(x) ((!CLASS_BLANK(x))&&(!CLASS_SEP(x))&&(!CLASS_BRA2(x))) #define CLASS_ANY6(x) ((!CLASS_BLANK(x))&&(!CLASS_START2(x))&&(!CLASS_START2(x))) #define CLASS_ANY7(x) ((!CLASS_BLANK(x))&&(!CLASS_EOL(x))) /** @brief parse elements in a list passed through use_module @param[in] str: is the string to parse @param[out] newlist: rlist of elements found @retval 0: successful > 0: failed */ static int LaunchParsingMachine(const char *str, Rlist **newlist) { const char *s = str; state current_state = ST_OPENED; int ret; Buffer *buf = BufferNewWithCapacity(CF_MAXVARSIZE); assert(newlist); while (current_state != ST_CLOSED && *s) { switch(current_state) { case ST_ERROR: Log(LOG_LEVEL_ERR, "Parsing error : Malformed string"); ret = 1; goto clean; case ST_OPENED: if (CLASS_BLANK(*s)) { current_state = ST_OPENED; } else if (CLASS_BRA1(*s)) { current_state = ST_IO; } else if (CLASS_ANY0(*s)) { current_state = ST_ERROR; } s++; break; case ST_IO: if (CLASS_BLANK(*s)) { current_state = ST_IO; } else if (CLASS_START1(*s)) { BufferClear(buf); current_state = ST_ELM1; } else if (CLASS_START2(*s)) { BufferClear(buf); current_state = ST_ELM2; } else if (CLASS_ANY1(*s)) { current_state = ST_ERROR; } s++; break; case ST_ELM1: if (CLASS_END1(*s)) { RlistAppendScalar(newlist, BufferData(buf)); BufferClear(buf); current_state = ST_END1; } else if (CLASS_ANY2(*s)) { BufferAppendChar(buf, *s); current_state = ST_ELM1; } s++; break; case ST_ELM2: if (CLASS_END2(*s)) { RlistAppendScalar(newlist, BufferData(buf)); BufferClear(buf); current_state = ST_END2; } else if (CLASS_ANY3(*s)) { BufferAppendChar(buf, *s); current_state = ST_ELM2; } s++; break; case ST_END1: if (CLASS_SEP(*s)) { current_state = ST_SEP; } else if (CLASS_BRA2(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_BLANK(*s)) { current_state = ST_END1; } else if (CLASS_ANY4(*s)) { current_state = ST_ERROR; } s++; break; case ST_END2: if (CLASS_SEP(*s)) { current_state = ST_SEP; } else if (CLASS_BRA2(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_BLANK(*s)) { current_state = ST_END2; } else if (CLASS_ANY5(*s)) { current_state = ST_ERROR; } s++; break; case ST_SEP: if (CLASS_BLANK(*s)) { current_state = ST_SEP; } else if (CLASS_START1(*s)) { current_state = ST_ELM1; } else if (CLASS_START2(*s)) { current_state = ST_ELM2; } else if (CLASS_ANY6(*s)) { current_state = ST_ERROR; } s++; break; case ST_PRECLOSED: if (CLASS_BLANK(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_EOL(*s)) { current_state = ST_CLOSED; } else if (CLASS_ANY7(*s)) { current_state = ST_ERROR; } s++; break; default: Log(LOG_LEVEL_ERR, "Parsing logic error: unknown state"); ret = 2; goto clean; break; } } if (current_state != ST_CLOSED && current_state != ST_PRECLOSED ) { Log(LOG_LEVEL_ERR, "Parsing error : Malformed string (unexpected end of input)"); ret = 3; goto clean; } BufferDestroy(buf); return 0; clean: BufferDestroy(buf); RlistDestroy(*newlist); assert(ret != 0); return ret; } Rlist *RlistParseString(const char *string) { Rlist *newlist = NULL; if (LaunchParsingMachine(string, &newlist)) { return NULL; } return newlist; } /*******************************************************************/ void RvalDestroy(Rval rval) { if (rval.item == NULL) { return; } switch (rval.type) { case RVAL_TYPE_SCALAR: ThreadLock(cft_lock); free(RvalScalarValue(rval)); ThreadUnlock(cft_lock); return; case RVAL_TYPE_LIST: RlistDestroy(RvalRlistValue(rval)); return; case RVAL_TYPE_FNCALL: FnCallDestroy(RvalFnCallValue(rval)); break; case RVAL_TYPE_CONTAINER: JsonDestroy(RvalContainerValue(rval)); break; case RVAL_TYPE_NOPROMISEE: return; } } /*********************************************************************/ void RlistDestroyEntry(Rlist **liststart, Rlist *entry) { if (entry != NULL) { if (entry->val.item) { free(entry->val.item); } Rlist *sp = entry->next; if (entry == *liststart) { *liststart = sp; } else { Rlist *rp = *liststart; while (rp->next != entry) { rp = rp->next; } assert(rp && rp->next == entry); rp->next = sp; } free(entry); } } /*******************************************************************/ /* Copies a -delimited unit from into a new entry in . * * \ is not counted as the separator, but copied to the new entry * as . No other escape sequences are supported. * * Returns the number of bytes read out of ; this may be more * than the length of the new entry in . The new entry is * prepended; the caller can reverse once built. */ static size_t SubStrnCopyChr(Rlist **to, const char *from, char sep) { assert(from && from[0]); const char *end = from; size_t escapes = 0; while (end && end[0] && end[0] != sep) { end = strchr(end, sep); assert(end == NULL || end[0] == sep); if (end && end > from && end[-1] == '\\') { escapes++; end++; } } size_t consume = (end == NULL) ? strlen(from) : (end - from); assert(consume >= escapes); char copy[1 + consume - escapes], *dst = copy; for (const char *src = from; src[0] != '\0' && src[0] != sep; src++) { if (src[0] == '\\' && src[1] == sep) { src++; /* Skip over the backslash so we copy the sep */ } dst++[0] = src[0]; } assert(dst + 1 == copy + sizeof(copy)); *dst = '\0'; /* Prepend to the list and reverse when done, costing O(len), * instead of appending, which costs O(len**2). */ RlistPrependRval(to, RvalCopyScalar((Rval) { copy, RVAL_TYPE_SCALAR })); return consume; } Rlist *RlistFromSplitString(const char *string, char sep) /* Splits a string on a separator - e.g. "," - into a linked list of * separate items. Supports escaping separators - e.g. "\," isn't a * separator, it contributes a simple "," in a list entry. */ { if (string == NULL || string[0] == '\0') { return NULL; } Rlist *liststart = NULL; for (const char *sp = string; *sp != '\0';) { sp += SubStrnCopyChr(&liststart, sp, sep); assert(sp - string <= strlen(string)); if (*sp) { assert(*sp == sep && (sp == string || sp[-1] != '\\')); sp++; } } RlistReverse(&liststart); return liststart; } /*******************************************************************/ Rlist *RlistFromSplitRegex(const char *string, const char *regex, size_t max_entries, bool allow_blanks) { assert(string); if (!string) { return NULL; } const char *sp = string; size_t entry_count = 0; int start = 0; int end = 0; Rlist *result = NULL; Buffer *buffer = BufferNewWithCapacity(CF_MAXVARSIZE); pcre *rx = CompileRegex(regex); if (rx) { while ((entry_count < max_entries) && StringMatchWithPrecompiledRegex(rx, sp, &start, &end)) { if (end == 0) { break; } BufferClear(buffer); BufferAppend(buffer, sp, start); if (allow_blanks || BufferSize(buffer) > 0) { RlistAppendScalar(&result, BufferData(buffer)); entry_count++; } sp += end; } pcre_free(rx); } if (entry_count < max_entries) { BufferClear(buffer); size_t remaining = strlen(sp); BufferAppend(buffer, sp, remaining); if ((allow_blanks && sp != string) || BufferSize(buffer) > 0) { RlistAppendScalar(&result, BufferData(buffer)); } } BufferDestroy(buffer); return result; } /*******************************************************************/ /* * Splits string on regex, returns a list of (at most max) fragments. * * NOTE: in contrast with RlistFromSplitRegex() this one will produce at most max number of elements; * last element will contain everything that lefts from original string (we use everything after * the (max-1)-th separator as the final list element, including any separators that may be embedded in it) */ Rlist *RlistFromRegexSplitNoOverflow(const char *string, const char *regex, int max) { Rlist *liststart = NULL; char node[CF_MAXVARSIZE]; int start, end; int count = 0; assert(max > 0); // ensured by FnCallStringSplit() before calling us assert(string != NULL); // ensured by FnCallStringSplit() before calling us const char *sp = string; // We will avoid compiling regex multiple times. pcre *pattern = CompileRegex(regex); if (pattern == NULL) { Log(LOG_LEVEL_DEBUG, "Error compiling regex from '%s'", regex); return NULL; } while (count < max - 1 && StringMatchWithPrecompiledRegex(pattern, sp, &start, &end)) { assert(start < CF_MAXVARSIZE); memcpy(node, sp, start); node[start] = '\0'; RlistAppendScalar(&liststart, node); count++; sp += end; } assert(count < max); RlistAppendScalar(&liststart, sp); pcre_free(pattern); return liststart; } Rlist *RlistLast(Rlist *start) { if (start == NULL) { return NULL; } Rlist *rp = start; while (rp->next != NULL) { rp = rp->next; } return rp; } void RlistFilter(Rlist **list, bool (*KeepPredicate)(void *, void *), void *predicate_user_data, void (*DestroyItem)(void *)) { assert(KeepPredicate); Rlist *start = *list, *prev = NULL, *next; for (Rlist *rp = start; rp; rp = next) { next = rp->next; if (KeepPredicate(RlistScalarValue(rp), predicate_user_data)) { prev = rp; } else { if (prev) { prev->next = next; } else { assert(rp == *list); *list = next; } if (DestroyItem) { DestroyItem(rp->val.item); rp->val.item = NULL; } rp->next = NULL; RlistDestroy(rp); } } } void RlistReverse(Rlist **list) { Rlist *prev = NULL; while (*list) { Rlist *tmp = *list; *list = (*list)->next; tmp->next = prev; prev = tmp; } *list = prev; } void RlistWrite(Writer *writer, const Rlist *list) { WriterWrite(writer, " {"); for (const Rlist *rp = list; rp != NULL; rp = rp->next) { WriterWriteChar(writer, '\''); RvalWrite(writer, rp->val); WriterWriteChar(writer, '\''); if (rp->next != NULL) { WriterWriteChar(writer, ','); } } WriterWriteChar(writer, '}'); } /* Note: only single quotes are escaped, as they are used in RlistWrite to delimit strings. If double quotes would be escaped, they would be mangled by RlistParseShown */ static void ScalarWrite(Writer *w, const char *s) { for (; *s; s++) { if (*s == '\'') { WriterWriteChar(w, '\\'); } WriterWriteChar(w, *s); } } void RvalWrite(Writer *writer, Rval rval) { RvalWriteParts(writer, rval.item, rval.type); } char *RvalToString(Rval rval) { Writer *w = StringWriter(); RvalWrite(w, rval); return StringWriterClose(w); } void RvalWriteParts(Writer *writer, const void* item, RvalType type) { if (item == NULL) { return; } switch (type) { case RVAL_TYPE_SCALAR: ScalarWrite(writer, item); break; case RVAL_TYPE_LIST: RlistWrite(writer, item); break; case RVAL_TYPE_FNCALL: FnCallWrite(writer, item); break; case RVAL_TYPE_NOPROMISEE: WriterWrite(writer, "(no-one)"); break; case RVAL_TYPE_CONTAINER: JsonWrite(writer, item, 0); break; } } unsigned RvalHash(Rval rval, unsigned seed, unsigned max) { switch (rval.type) { case RVAL_TYPE_SCALAR: return StringHash(RvalScalarValue(rval), seed, max); case RVAL_TYPE_FNCALL: return FnCallHash(RvalFnCallValue(rval), seed, max); case RVAL_TYPE_LIST: return RlistHash(RvalRlistValue(rval), seed, max); case RVAL_TYPE_NOPROMISEE: return (seed + 1) % max; default: ProgrammingError("Unhandled case in switch: %d", rval.type); } } unsigned RlistHash(const Rlist *list, unsigned seed, unsigned max) { unsigned hash = seed; for (const Rlist *rp = list; rp; rp = rp->next) { hash = RvalHash(rp->val, hash, max); } return hash; } static JsonElement *FnCallToJson(const FnCall *fp) { assert(fp); JsonElement *object = JsonObjectCreate(3); JsonObjectAppendString(object, "name", fp->name); JsonObjectAppendString(object, "type", "function-call"); JsonElement *argsArray = JsonArrayCreate(5); for (Rlist *rp = fp->args; rp != NULL; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: JsonArrayAppendString(argsArray, RlistScalarValue(rp)); break; case RVAL_TYPE_FNCALL: JsonArrayAppendObject(argsArray, FnCallToJson(RlistFnCallValue(rp))); break; default: assert(false && "Unknown argument type"); break; } } JsonObjectAppendArray(object, "arguments", argsArray); return object; } static JsonElement *RlistToJson(Rlist *list) { JsonElement *array = JsonArrayCreate(RlistLen(list)); for (Rlist *rp = list; rp; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: JsonArrayAppendString(array, RlistScalarValue(rp)); break; case RVAL_TYPE_LIST: JsonArrayAppendArray(array, RlistToJson(RlistRlistValue(rp))); break; case RVAL_TYPE_FNCALL: JsonArrayAppendObject(array, FnCallToJson(RlistFnCallValue(rp))); break; default: assert(false && "Unsupported item type in rlist"); break; } } return array; } JsonElement *RvalToJson(Rval rval) { assert(rval.item); switch (rval.type) { case RVAL_TYPE_SCALAR: return JsonStringCreate(RvalScalarValue(rval)); case RVAL_TYPE_LIST: return RlistToJson(RvalRlistValue(rval)); case RVAL_TYPE_FNCALL: return FnCallToJson(RvalFnCallValue(rval)); case RVAL_TYPE_CONTAINER: return JsonCopy(RvalContainerValue(rval)); case RVAL_TYPE_NOPROMISEE: assert(false); return JsonObjectCreate(1); } assert(false); return NULL; } void RlistFlatten(EvalContext *ctx, Rlist **list) { Rlist *prev = NULL, *next; for (Rlist *rp = *list; rp != NULL; rp = next) { next = rp->next; if (rp->val.type != RVAL_TYPE_SCALAR) { prev = rp; continue; } char naked[CF_BUFSIZE] = ""; if (IsNakedVar(RlistScalarValue(rp), '@')) { GetNaked(naked, RlistScalarValue(rp)); if (!IsExpandable(naked)) { VarRef *ref = VarRefParse(naked); DataType value_type = CF_DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, ref, &value_type); VarRefDestroy(ref); if (value) { switch (DataTypeToRvalType(value_type)) { case RVAL_TYPE_LIST: { RlistDestroyEntry(list, rp); for (const Rlist *srp = value; srp != NULL; srp = srp->next) { Rlist *nrp = xmalloc(sizeof(Rlist)); nrp->val = RvalCopy(srp->val); nrp->next = next; if (prev) { prev->next = nrp; } else { *list = nrp; } prev = nrp; } } continue; default: Log(LOG_LEVEL_WARNING, "Attempted to dereference variable '%s' using @ but variable did not resolve to a list", RlistScalarValue(rp)); break; } } } } prev = rp; } } cfengine-3.6.2/libpromises/expand.h0000664000175100017510000000614612411001073016772 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_EXPAND_H #define CFENGINE_EXPAND_H #include #include #include PromiseResult CommonEvalPromise(EvalContext *ctx, const Promise *pp, void *param); PromiseResult ExpandPromise(EvalContext *ctx, const Promise *pp, PromiseActuator *ActOnPromise, void *param); Rval ExpandDanglers(EvalContext *ctx, const char *ns, const char *scope, Rval rval, const Promise *pp); void MapIteratorsFromRval(EvalContext *ctx, const Bundle *bundle, Rval rval, Rlist **scalars, Rlist **lists, Rlist **containers); bool IsExpandable(const char *str); bool ExpandScalar(const EvalContext *ctx, const char *ns, const char *scope, const char *string, Buffer *out); Rval ExpandBundleReference(EvalContext *ctx, const char *ns, const char *scope, Rval rval); Rval ExpandPrivateRval(EvalContext *ctx, const char *ns, const char *scope, const void *rval_item, RvalType rval_type); Rlist *ExpandList(EvalContext *ctx, const char *ns, const char *scope, const Rlist *list, int expandnaked); Rval EvaluateFinalRval(EvalContext *ctx, const Policy *policy, const char *ns, const char *scope, Rval rval, bool forcelist, const Promise *pp); /** * @brief BundleResolve * @param ctx * @param bundle */ void BundleResolve(EvalContext *ctx, const Bundle *bundle); void PolicyResolve(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config); bool IsNakedVar(const char *str, char vtype); /** @brief Takes a variable and removes decorations. This function performs no validations, it is necessary to call the validation functions before calling this function. @remarks This function does not check for NULL pointers, that is the caller's responsability. @param s1 Buffer to store the undecorated variable. @param s2 Decorated variable */ void GetNaked(char *s1, const char *s2); /** @brief Checks if a given variable is a list or not. @remarks This function does not check for NULL pointers, it is responsability of the caller. @param variable Variable to be checked @return True if the variable is a list, False otherwise. */ bool IsVarList(const char *var); ProtocolVersion ProtocolVersionParse(const char *s); #endif cfengine-3.6.2/libpromises/mod_methods.h0000664000175100017510000000216612243421446020030 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MOD_METHODS_H #define CFENGINE_MOD_METHODS_H #include extern const PromiseTypeSyntax CF_METHOD_PROMISE_TYPES[]; #endif cfengine-3.6.2/libpromises/process_lib.h0000664000175100017510000000335212243421446020030 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROCESS_H #define CFENGINE_PROCESS_H #define PROCESS_START_TIME_UNKNOWN ((time_t)0) /* * Obtain start time of specified process. * * @return start time (Unix timestamp) of specified process * @return PROCESS_START_TIME_UNKNOWN if start time cannot be determined */ time_t GetProcessStartTime(pid_t pid); /* * Gracefully kill the process with pid #pid and start time #process_start_time. * * Under Unix this will send SIGINT, then SIGTERM and then SIGKILL if process * does not exit. * * #process_start_time may be PROCESS_START_TIME_UNKNOWN, which will disable * safety check for killing right process. * * @return true if process was killed successfully, false otherwise. */ int GracefulTerminate(pid_t pid, time_t process_start_time); #endif cfengine-3.6.2/libpromises/fncall.c0000664000175100017510000002436012411001073016743 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include /******************************************************************/ /* Argument propagation */ /******************************************************************/ /* When formal parameters are passed, they should be literal strings, i.e. values (check for this). But when the values are received the receiving body should state only variable names without literal quotes. That way we can feed in the received parameter name directly in as an lvalue e.g. access => myaccess("$(person)"), body files myaccess(user) leads to Hash Association (lval,rval) => (user,"$(person)") */ /******************************************************************/ static Rlist *NewExpArgs(EvalContext *ctx, const Policy *policy, const FnCall *fp) { { const FnCallType *fn = FnCallTypeGet(fp->name); int len = RlistLen(fp->args); if (!(fn->options & FNCALL_OPTION_VARARG)) { if (len != FnNumArgs(fn)) { Log(LOG_LEVEL_ERR, "Arguments to function '%s' do not tally. Expected %d not %d", fp->name, FnNumArgs(fn), len); PromiseRef(LOG_LEVEL_ERR, fp->caller); exit(EXIT_FAILURE); } } } Rlist *expanded_args = NULL; for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next) { Rval rval; switch (rp->val.type) { case RVAL_TYPE_FNCALL: { FnCall *subfp = RlistFnCallValue(rp); rval = FnCallEvaluate(ctx, policy, subfp, fp->caller).rval; assert(rval.item); } break; default: rval = ExpandPrivateRval(ctx, NULL, NULL, rp->val.item, rp->val.type); assert(rval.item); break; } RlistAppend(&expanded_args, rval.item, rval.type); RvalDestroy(rval); } return expanded_args; } /*******************************************************************/ bool FnCallIsBuiltIn(Rval rval) { FnCall *fp; if (rval.type != RVAL_TYPE_FNCALL) { return false; } fp = (FnCall *) rval.item; if (FnCallTypeGet(fp->name)) { return true; } else { return false; } } /*******************************************************************/ FnCall *FnCallNew(const char *name, Rlist *args) { FnCall *fp = xmalloc(sizeof(FnCall)); fp->name = xstrdup(name); fp->args = args; return fp; } /*******************************************************************/ FnCall *FnCallCopy(const FnCall *f) { return FnCallNew(f->name, RlistCopy(f->args)); } /*******************************************************************/ void FnCallDestroy(FnCall *fp) { if (fp) { free(fp->name); RlistDestroy(fp->args); } free(fp); } unsigned FnCallHash(const FnCall *fp, unsigned seed, unsigned max) { unsigned hash = StringHash(fp->name, seed, max); return RlistHash(fp->args, hash, max); } FnCall *ExpandFnCall(EvalContext *ctx, const char *ns, const char *scope, const FnCall *f) { FnCall *result = NULL; if (IsCf3VarString(f->name)) { // e.g. usebundle => $(m)(arg0, arg1); Buffer *buf = BufferNewWithCapacity(CF_MAXVARSIZE); ExpandScalar(ctx, ns, scope, f->name, buf); result = FnCallNew(BufferData(buf), ExpandList(ctx, ns, scope, f->args, false)); BufferDestroy(buf); } else { result = FnCallNew(f->name, ExpandList(ctx, ns, scope, f->args, false)); } return result; } void FnCallWrite(Writer *writer, const FnCall *call) { WriterWrite(writer, call->name); WriterWriteChar(writer, '('); for (const Rlist *rp = call->args; rp != NULL; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: WriterWrite(writer, RlistScalarValue(rp)); break; case RVAL_TYPE_FNCALL: FnCallWrite(writer, RlistFnCallValue(rp)); break; default: WriterWrite(writer, "(** Unknown argument **)\n"); break; } if (rp->next != NULL) { WriterWriteChar(writer, ','); } } WriterWriteChar(writer, ')'); } /*******************************************************************/ static FnCallResult CallFunction(EvalContext *ctx, const Policy *policy, const FnCall *fp, const Rlist *expargs) { const Rlist *rp = fp->args; const FnCallType *fncall_type = FnCallTypeGet(fp->name); int argnum = 0; for (argnum = 0; rp != NULL && fncall_type->args[argnum].pattern != NULL; argnum++) { if (rp->val.type != RVAL_TYPE_FNCALL) { /* Nested functions will not match to lval so don't bother checking */ SyntaxTypeMatch err = CheckConstraintTypeMatch(fp->name, rp->val, fncall_type->args[argnum].dtype, fncall_type->args[argnum].pattern, 1); if (err != SYNTAX_TYPE_MATCH_OK && err != SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED) { FatalError(ctx, "In function '%s', '%s'", fp->name, SyntaxTypeMatchToString(err)); } } rp = rp->next; } char output[CF_BUFSIZE]; if (argnum != RlistLen(expargs) && !(fncall_type->options & FNCALL_OPTION_VARARG)) { snprintf(output, CF_BUFSIZE, "Argument template mismatch handling function %s(", fp->name); { Writer *w = FileWriter(stderr); RlistWrite(w, expargs); FileWriterDetach(w); } fprintf(stderr, ")\n"); rp = expargs; for (int i = 0; i < argnum; i++) { printf(" arg[%d] range %s\t", i, fncall_type->args[i].pattern); if (rp != NULL) { Writer *w = FileWriter(stdout); RvalWrite(w, rp->val); FileWriterDetach(w); rp = rp->next; } else { printf(" ? "); } printf("\n"); } FatalError(ctx, "Bad arguments"); } return (*fncall_type->impl) (ctx, policy, fp, expargs); } FnCallResult FnCallEvaluate(EvalContext *ctx, const Policy *policy, FnCall *fp, const Promise *caller) { assert(ctx); assert(policy); assert(fp); fp->caller = caller; if (!EvalContextGetEvalOption(ctx, EVAL_OPTION_EVAL_FUNCTIONS)) { Log(LOG_LEVEL_VERBOSE, "Skipping function '%s', because evaluation was turned off in the evaluator", fp->name); return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } else if (caller && !EvalContextPromiseIsActive(ctx, caller)) { Log(LOG_LEVEL_VERBOSE, "Skipping function '%s', because it was excluded by classes", fp->name); return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } const FnCallType *fp_type = FnCallTypeGet(fp->name); if (!fp_type) { if (caller) { Log(LOG_LEVEL_ERR, "No such FnCall '%s' in promise '%s' near line %zd", fp->name, PromiseGetBundle(caller)->source_path, caller->offset.line); } else { Log(LOG_LEVEL_ERR, "No such FnCall '%s', context info unavailable", fp->name); } return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } Rlist *expargs = NewExpArgs(ctx, policy, fp); if (RlistIsUnresolved(expargs)) { RlistDestroy(expargs); return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } Rval cached_rval; if ((fp_type->options & FNCALL_OPTION_CACHED) && EvalContextFunctionCacheGet(ctx, fp, expargs, &cached_rval)) { Writer *w = StringWriter(); FnCallWrite(w, fp); Log(LOG_LEVEL_DEBUG, "Using previously cached result for function '%s'", StringWriterData(w)); WriterClose(w); RlistDestroy(expargs); return (FnCallResult) { FNCALL_SUCCESS, RvalCopy(cached_rval) }; } FnCallResult result = CallFunction(ctx, policy, fp, expargs); if (result.status == FNCALL_FAILURE) { RlistDestroy(expargs); return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } }; } if (fp_type->options & FNCALL_OPTION_CACHED) { Writer *w = StringWriter(); FnCallWrite(w, fp); Log(LOG_LEVEL_VERBOSE, "Caching result for function '%s'", StringWriterData(w)); WriterClose(w); EvalContextFunctionCachePut(ctx, fp, expargs, &result.rval); } RlistDestroy(expargs); return result; } /*******************************************************************/ const FnCallType *FnCallTypeGet(const char *name) { int i; for (i = 0; CF_FNCALL_TYPES[i].name != NULL; i++) { if (strcmp(CF_FNCALL_TYPES[i].name, name) == 0) { return CF_FNCALL_TYPES + i; } } return NULL; } cfengine-3.6.2/libpromises/prototypes3.h0000664000175100017510000001227512400110676020036 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROTOTYPES3_H #define CFENGINE_PROTOTYPES3_H #include #include #include bool BootstrapAllowed(void); /* Versions */ const char *Version(void); const char *NameVersion(void); /* cfparse.y */ void yyerror(const char *s); /* agent.c */ PromiseResult ScheduleAgentOperations(EvalContext *ctx, const Bundle *bp); /* Only for agent.c */ void ConnectionsInit(void); void ConnectionsCleanup(void); /* client_protocol.c */ void SetSkipIdentify(bool enabled); /* enterprise_stubs.c */ ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, Nova_Initialize, EvalContext *, ctx); ENTERPRISE_FUNC_1ARG_DECLARE(int, CfSessionKeySize, char, c); ENTERPRISE_FUNC_0ARG_DECLARE(char, CfEnterpriseOptions); ENTERPRISE_FUNC_1ARG_DECLARE(const EVP_CIPHER *, CfengineCipher, char, type); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, EnterpriseContext, EvalContext *, ctx); ENTERPRISE_FUNC_0ARG_DECLARE(const char *, GetConsolePrefix); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, LoadSlowlyVaryingObservations, EvalContext *, ctx); ENTERPRISE_FUNC_6ARG_DECLARE(char *, GetRemoteScalar, EvalContext *, ctx, char *, proto, char *, handle, char *, server, int, encrypted, char *, rcv); ENTERPRISE_FUNC_1ARG_DECLARE(const char *, PromiseID, const Promise *, pp); /* Not thread-safe */ ENTERPRISE_VOID_FUNC_3ARG_DECLARE(void, NotePromiseCompliance, const Promise *, pp, PromiseState, state, const char *, reason); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, LogTotalCompliance, const char *, version, int, background_tasks); #if defined(__MINGW32__) ENTERPRISE_FUNC_4ARG_DECLARE(int, GetRegistryValue, const char *, key, char *, name, char *, buf, int, bufSz); #endif ENTERPRISE_FUNC_6ARG_DECLARE(void *, CfLDAPValue, char *, uri, char *, dn, char *, filter, char *, name, char *, scope, char *, sec); ENTERPRISE_FUNC_6ARG_DECLARE(void *, CfLDAPList, char *, uri, char *, dn, char *, filter, char *, name, char *, scope, char *, sec); ENTERPRISE_FUNC_8ARG_DECLARE(void *, CfLDAPArray, EvalContext *, ctx, const Bundle *, caller, char *, array, char *, uri, char *, dn, char *, filter, char *, scope, char *, sec); ENTERPRISE_FUNC_8ARG_DECLARE(void *, CfRegLDAP, EvalContext *, ctx, char *, uri, char *, dn, char *, filter, char *, name, char *, scope, char *, regex, char *, sec); ENTERPRISE_VOID_FUNC_3ARG_DECLARE(void, CacheUnreliableValue, char *, caller, char *, handle, char *, buffer); ENTERPRISE_FUNC_3ARG_DECLARE(int, RetrieveUnreliableValue, char *, caller, char *, handle, char *, buffer); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, TranslatePath, char *, new, const char *, old); ENTERPRISE_VOID_FUNC_4ARG_DECLARE(void, TrackValue, char *, date, double, kept, double, repaired, double, notkept); ENTERPRISE_FUNC_4ARG_DECLARE(bool, ListHostsWithClass, EvalContext *, ctx, Rlist **, return_list, char *, class_name, char *, return_format); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, ShowPromises, const Seq *, bundles, const Seq *, bodies); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, ShowPromise, const Promise *, pp); ENTERPRISE_VOID_FUNC_3ARG_DECLARE(void, GetObservable, int, i, char *, name, char *, desc); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, SetMeasurementPromises, Item **, classlist); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, CheckAndSetHAState, const char *, workdir, EvalContext *, ctx); ENTERPRISE_VOID_FUNC_0ARG_DECLARE(void, ReloadHAConfig); /* manual.c */ void TexinfoManual(EvalContext *ctx, const char *source_dir, const char *output_file); /* modes.c */ int ParseModeString(const char *modestring, mode_t *plusmask, mode_t *minusmask); /* patches.c */ int IsPrivileged(void); char *cf_strtimestamp_local(const time_t time, char *buf); char *cf_strtimestamp_utc(const time_t time, char *buf); int cf_closesocket(int sd); #if !defined(__MINGW32__) #define OpenNetwork() /* noop */ #define CloseNetwork() /* noop */ #else void OpenNetwork(void); void CloseNetwork(void); #endif int LinkOrCopy(const char *from, const char *to, int sym); int ExclusiveLockFile(int fd); int ExclusiveUnlockFile(int fd); /* storage_tools.c */ off_t GetDiskUsage(char *file, CfSize type); /* verify_reports.c */ PromiseResult VerifyReportPromise(EvalContext *ctx, const Promise *pp); /* cf-key */ ENTERPRISE_FUNC_1ARG_DECLARE(bool, LicenseInstall, char *, path_source); #endif cfengine-3.6.2/libpromises/iteration.h0000664000175100017510000000310512243421446017516 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ITERATION_H #define CFENGINE_ITERATION_H #include #include #include typedef struct PromiseIterator_ PromiseIterator; PromiseIterator *PromiseIteratorNew(EvalContext *ctx, const Promise *pp, const Rlist *lists, const Rlist *containers); void PromiseIteratorDestroy(PromiseIterator *iter_ctx); bool PromiseIteratorHasMore(const PromiseIterator *iter_ctx); bool PromiseIteratorNext(PromiseIterator *iter_ctx); bool NullIterators(const PromiseIterator *iter_ctx); void PromiseIteratorUpdateVariable(EvalContext *ctx, const PromiseIterator *iter_ctx); #endif cfengine-3.6.2/libpromises/chflags.c0000664000175100017510000001265512243421446017134 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* BSD flags */ #include typedef struct { char *name; u_long bits; } BSDFlag; static const BSDFlag CF_BSDFLAGS[] = { {"arch", (u_long) SF_ARCHIVED}, {"archived", (u_long) SF_ARCHIVED}, {"nodump", (u_long) UF_NODUMP}, {"opaque", (u_long) UF_OPAQUE}, {"sappnd", (u_long) SF_APPEND}, {"sappend", (u_long) SF_APPEND}, {"schg", (u_long) SF_IMMUTABLE}, {"schange", (u_long) SF_IMMUTABLE}, {"simmutable", (u_long) SF_IMMUTABLE}, {"sunlnk", (u_long) SF_NOUNLINK}, {"sunlink", (u_long) SF_NOUNLINK}, {"uappnd", (u_long) UF_APPEND}, {"uappend", (u_long) UF_APPEND}, {"uchg", (u_long) UF_IMMUTABLE}, {"uchange", (u_long) UF_IMMUTABLE}, {"uimmutable", (u_long) UF_IMMUTABLE}, {"uunlnk", (u_long) UF_NOUNLINK}, {"uunlink", (u_long) UF_NOUNLINK}, {NULL, (u_long) 0} }; /***************************************************************/ static u_long ConvertBSDBits(const char *s); /***************************************************************/ int ParseFlagString(Rlist *bitlist, u_long *plusmask, u_long *minusmask) { if (bitlist == NULL) { return true; } *plusmask = 0; *minusmask = 0; for (const Rlist *rp = bitlist; rp != NULL; rp = rp->next) { const char *flag = RlistScalarValue(rp); char op = *RlistScalarValue(rp); switch (op) { case '-': *minusmask |= ConvertBSDBits(flag + 1); break; case '+': *plusmask |= ConvertBSDBits(flag + 1); break; default: *plusmask |= ConvertBSDBits(flag); break; } } Log(LOG_LEVEL_DEBUG, "ParseFlagString: [PLUS = %lo] [MINUS = %lo]", *plusmask, *minusmask); return true; } /***************************************************************/ static u_long ConvertBSDBits(const char *s) { int i; for (i = 0; CF_BSDFLAGS[i].name != NULL; i++) { if (strcmp(s, CF_BSDFLAGS[i].name) == 0) { return CF_BSDFLAGS[i].bits; } } return 0; } /* CHFLAGS(1) FreeBSD General Commands Manual CHFLAGS(1) NAME chflags - change file flags SYNOPSIS chflags [-R [-H | -L | -P]] flags file ... DESCRIPTION The chflags utility modifies the file flags of the listed files as speci- fied by the flags operand. The options are as follows: -H If the -R option is specified, symbolic links on the command line are followed. (Symbolic links encountered in the tree traversal are not followed.) -L If the -R option is specified, all symbolic links are followed. -P If the -R option is specified, no symbolic links are followed. -R Change the file flags for the file hierarchies rooted in the files instead of just the files themselves. Flags are a comma separated list of keywords. The following keywords are currently defined: arch set the archived flag (super-user only) dump set the dump flag sappnd set the system append-only flag (super-user only) schg set the system immutable flag (super-user only) sunlnk set the system undeletable flag (super-user only) uappnd set the user append-only flag (owner or super-user only) uchg set the user immutable flag (owner or super-user only) uunlnk set the user undeletable flag (owner or super-user only) archived, sappend, schange, simmutable, uappend, uchange, uimmutable, sunlink, uunlink aliases for the above Putting the letters ``no'' before an option causes the flag to be turned off. For example: nodump the file should never be dumped Symbolic links do not have flags, so unless the -H or -L option is set, chflags on a symbolic link always succeeds and has no effect. The -H, -L and -P options are ignored unless the -R option is specified. In addi- tion, these options override each other and the command's actions are de- termined by the last one specified. You can use "ls -lo" to see the flags of existing files. The chflags utility exits 0 on success, and >0 if an error occurs. SEE ALSO ls(1), chflags(2), stat(2), fts(3), symlink(7) HISTORY The chflags command first appeared in 4.4BSD. BSD March 31, 1994 1 */ cfengine-3.6.2/libpromises/locks.c0000664000175100017510000006436212411001073016625 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CFLOGSIZE 1048576 /* Size of lock-log before rotation */ #define CF_LOCKHORIZON ((time_t)(SECONDS_PER_WEEK * 4)) #define CF_CRITIAL_SECTION "CF_CRITICAL_SECTION" static char CFLOCK[CF_BUFSIZE] = ""; /* GLOBAL_X */ static char CFLAST[CF_BUFSIZE] = ""; /* GLOBAL_X */ static char CFLOG[CF_BUFSIZE] = ""; /* GLOBAL_X */ static pthread_once_t lock_cleanup_once = PTHREAD_ONCE_INIT; /* GLOBAL_X */ #ifdef LMDB static void GenerateMd5Hash(const char *istring, char *ohash) { if (!strcmp(istring, "CF_CRITICAL_SECTION")) { strcpy(ohash, istring); return; } unsigned char digest[EVP_MAX_MD_SIZE + 1]; HashString(istring, strlen(istring), digest, HASH_METHOD_MD5); const char lookup[]="0123456789abcdef"; for (int i=0; i<16; i++) { ohash[i*2] = lookup[digest[i] >> 4]; ohash[i*2+1] = lookup[digest[i] & 0xf]; } ohash[16*2] = '\0'; if (!strncmp(istring, "lock.track_license_bundle.track_license", 39)) { ohash[0] = 'X'; } } #endif static bool WriteLockData(CF_DB *dbp, const char *lock_id, LockData *lock_data) { #ifdef LMDB unsigned char digest2[EVP_MAX_MD_SIZE*2 + 1]; if (!strcmp(lock_id, "CF_CRITICAL_SECTION")) { strcpy(digest2, lock_id); } else { GenerateMd5Hash(lock_id, digest2); } if(WriteDB(dbp, digest2, lock_data, sizeof(LockData))) #else if(WriteDB(dbp, lock_id, lock_data, sizeof(LockData))) #endif { return true; } else { return false; } } static bool WriteLockDataCurrent(CF_DB *dbp, const char *lock_id) { LockData lock_data = { .pid = getpid(), .time = time(NULL), .process_start_time = GetProcessStartTime(getpid()), }; return WriteLockData(dbp, lock_id, &lock_data); } time_t FindLockTime(const char *name) { CF_DB *dbp; LockData entry = { .process_start_time = PROCESS_START_TIME_UNKNOWN, }; if ((dbp = OpenLock()) == NULL) { return -1; } #ifdef LMDB unsigned char ohash[EVP_MAX_MD_SIZE*2 + 1]; GenerateMd5Hash(name, ohash); if (ReadDB(dbp, ohash, &entry, sizeof(entry))) #else if (ReadDB(dbp, name, &entry, sizeof(entry))) #endif { CloseLock(dbp); return entry.time; } else { CloseLock(dbp); return -1; } } static void RemoveDates(char *s) { int i, a = 0, b = 0, c = 0, d = 0; char *dayp = NULL, *monthp = NULL, *sp; char *days[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; // Canonifies or blanks our times/dates for locks where there would be an explosion of state if (strlen(s) < strlen("Fri Oct 1 15:15:23 EST 2010")) { // Probably not a full date return; } for (i = 0; i < 7; i++) { if ((dayp = strstr(s, days[i]))) { *dayp = 'D'; *(dayp + 1) = 'A'; *(dayp + 2) = 'Y'; break; } } for (i = 0; i < 12; i++) { if ((monthp = strstr(s, months[i]))) { *monthp = 'M'; *(monthp + 1) = 'O'; *(monthp + 2) = 'N'; break; } } if (dayp && monthp) // looks like a full date { sscanf(monthp + 4, "%d %d:%d:%d", &a, &b, &c, &d); if (a * b * c * d == 0) { // Probably not a date return; } for (sp = monthp + 4; *sp != '\0'; sp++) { if (sp > monthp + 15) { break; } if (isdigit((int)*sp)) { *sp = 't'; } } } } static int RemoveLock(const char *name) { CF_DB *dbp; if ((dbp = OpenLock()) == NULL) { return -1; } ThreadLock(cft_lock); #ifdef LMDB unsigned char digest2[EVP_MAX_MD_SIZE*2 + 1]; if (!strcmp(name, "CF_CRITICAL_SECTION")) { strcpy(digest2, name); } else { GenerateMd5Hash(name, digest2); } DeleteDB(dbp, digest2); #else DeleteDB(dbp, name); #endif ThreadUnlock(cft_lock); CloseLock(dbp); return 0; } void WaitForCriticalSection(const char *section_id) { time_t now = time(NULL), then = FindLockTime(section_id); /* Another agent has been waiting more than a minute, it means there is likely crash detritus to clear up... After a minute we take our chances ... */ while ((then != -1) && (now - then < 60)) { sleep(1); now = time(NULL); then = FindLockTime(section_id); } WriteLock(section_id); } void ReleaseCriticalSection(const char *section_id) { RemoveLock(section_id); } static time_t FindLock(char *last) { time_t mtime; if ((mtime = FindLockTime(last)) == -1) { /* Do this to prevent deadlock loops from surviving if IfElapsed > T_sched */ if (WriteLock(last) == -1) { Log(LOG_LEVEL_ERR, "Unable to lock %s", last); return 0; } return 0; } else { return mtime; } } static pid_t FindLockPid(char *name) { CF_DB *dbp; LockData entry = { .process_start_time = PROCESS_START_TIME_UNKNOWN, }; if ((dbp = OpenLock()) == NULL) { return -1; } #ifdef LMDB unsigned char ohash[EVP_MAX_MD_SIZE*2 + 1]; GenerateMd5Hash(name, ohash); if (ReadDB(dbp, ohash, &entry, sizeof(entry))) #else if (ReadDB(dbp, name, &entry, sizeof(entry))) #endif { CloseLock(dbp); return entry.pid; } else { CloseLock(dbp); return -1; } } static void LogLockCompletion(char *cflog, int pid, char *str, char *op, char *operand) { FILE *fp; char buffer[CF_MAXVARSIZE]; time_t tim; if (cflog == NULL) { return; } if ((fp = fopen(cflog, "a")) == NULL) { Log(LOG_LEVEL_ERR, "Can't open lock-log file '%s'. (fopen: %s)", cflog, GetErrorStr()); exit(EXIT_FAILURE); } if ((tim = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_DEBUG, "Couldn't read system clock"); } snprintf(buffer, sizeof(buffer), "%s", ctime(&tim)); if (Chop(buffer, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } fprintf(fp, "%s:%s:pid=%d:%s:%s\n", buffer, str, pid, op, operand); fclose(fp); } static void LocksCleanup(void) { if (strlen(CFLOCK) > 0) { CfLock best_guess = { .lock = xstrdup(CFLOCK), .last = xstrdup(CFLAST), .log = xstrdup(CFLOG) }; YieldCurrentLock(best_guess); } } static void RegisterLockCleanup(void) { RegisterAtExitFunction(&LocksCleanup); } static char *BodyName(const Promise *pp) { char *name, *sp; int size = 0; /* Return a type template for the promise body for lock-type identification */ name = xmalloc(CF_MAXVARSIZE); sp = pp->parent_promise_type->name; if (size + strlen(sp) < CF_MAXVARSIZE - CF_BUFFERMARGIN) { strcpy(name, sp); strcat(name, "."); size += strlen(sp); } for (size_t i = 0; (i < 5) && i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, "args") == 0) /* Exception for args, by symmetry, for locking */ { continue; } if (size + strlen(cp->lval) < CF_MAXVARSIZE - CF_BUFFERMARGIN) { strcat(name, cp->lval); strcat(name, "."); size += strlen(cp->lval); } } return name; } #ifdef __MINGW32__ static bool KillLockHolder(ARG_UNUSED const char *lock) { Log(LOG_LEVEL_VERBOSE, "Process is not running - ignoring lock (Windows does not support graceful processes termination)"); return true; } #else static bool KillLockHolder(const char *lock) { CF_DB *dbp = OpenLock(); if (dbp == NULL) { Log(LOG_LEVEL_ERR, "Unable to open locks database"); return false; } LockData lock_data = { .process_start_time = PROCESS_START_TIME_UNKNOWN, }; #ifdef LMDB unsigned char ohash[EVP_MAX_MD_SIZE*2 + 1]; GenerateMd5Hash(lock, ohash); if (!ReadDB(dbp, ohash, &lock_data, sizeof(lock_data))) #else if (!ReadDB(dbp, lock, &lock_data, sizeof(lock_data))) #endif { /* No lock found */ CloseLock(dbp); return true; } CloseLock(dbp); return GracefulTerminate(lock_data.pid, lock_data.process_start_time); } #endif void PromiseRuntimeHash(const Promise *pp, const char *salt, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type) { static const char PACK_UPIFELAPSED_SALT[] = "packageuplist"; EVP_MD_CTX context; int md_len; const EVP_MD *md = NULL; Rlist *rp; FnCall *fp; char *noRvalHash[] = { "mtime", "atime", "ctime", NULL }; int doHash; md = EVP_get_digestbyname(HashNameFromId(type)); EVP_DigestInit(&context, md); // multiple packages (promisers) may share same package_list_update_ifelapsed lock if ( (!salt) || strcmp(salt, PACK_UPIFELAPSED_SALT) ) { EVP_DigestUpdate(&context, pp->promiser, strlen(pp->promiser)); } if (pp->comment) { EVP_DigestUpdate(&context, pp->comment, strlen(pp->comment)); } if (pp->parent_promise_type && pp->parent_promise_type->parent_bundle) { if (pp->parent_promise_type->parent_bundle->ns) { EVP_DigestUpdate(&context, pp->parent_promise_type->parent_bundle->ns, strlen(pp->parent_promise_type->parent_bundle->ns)); } if (pp->parent_promise_type->parent_bundle->name) { EVP_DigestUpdate(&context, pp->parent_promise_type->parent_bundle->name, strlen(pp->parent_promise_type->parent_bundle->name)); } } // Unused: pp start, end, and line attributes (describing source position). if (salt) { EVP_DigestUpdate(&context, salt, strlen(salt)); } for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); EVP_DigestUpdate(&context, cp->lval, strlen(cp->lval)); // don't hash rvals that change (e.g. times) doHash = true; for (int j = 0; noRvalHash[j] != NULL; j++) { if (strcmp(cp->lval, noRvalHash[j]) == 0) { doHash = false; break; } } if (!doHash) { continue; } switch (cp->rval.type) { case RVAL_TYPE_SCALAR: EVP_DigestUpdate(&context, cp->rval.item, strlen(cp->rval.item)); break; case RVAL_TYPE_LIST: for (rp = cp->rval.item; rp != NULL; rp = rp->next) { EVP_DigestUpdate(&context, RlistScalarValue(rp), strlen(RlistScalarValue(rp))); } break; case RVAL_TYPE_FNCALL: /* Body or bundle */ fp = (FnCall *) cp->rval.item; EVP_DigestUpdate(&context, fp->name, strlen(fp->name)); for (rp = fp->args; rp != NULL; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: EVP_DigestUpdate(&context, RlistScalarValue(rp), strlen(RlistScalarValue(rp))); break; case RVAL_TYPE_FNCALL: EVP_DigestUpdate(&context, RlistFnCallValue(rp)->name, strlen(RlistFnCallValue(rp)->name)); break; default: ProgrammingError("Unhandled case in switch"); break; } } break; default: break; } } EVP_DigestFinal(&context, digest, &md_len); /* Digest length stored in md_len */ } static CfLock CfLockNew(const char *last, const char *lock, const char *log, bool is_dummy) { return (CfLock) { .last = last ? xstrdup(last) : NULL, .lock = lock ? xstrdup(lock) : NULL, .log = log ? xstrdup(log) : NULL, .is_dummy = is_dummy }; } static CfLock CfLockNull(void) { return (CfLock) { .last = NULL, .lock = NULL, .log = NULL, .is_dummy = false }; } CfLock AcquireLock(EvalContext *ctx, const char *operand, const char *host, time_t now, TransactionContext tc, const Promise *pp, bool ignoreProcesses) { if (now == 0) { return CfLockNull(); } unsigned char digest[EVP_MAX_MD_SIZE + 1]; PromiseRuntimeHash(pp, operand, digest, CF_DEFAULT_DIGEST); char str_digest[CF_HOSTKEY_STRING_SIZE]; HashPrintSafe(str_digest, sizeof(str_digest), digest, CF_DEFAULT_DIGEST, true); if (EvalContextPromiseLockCacheContains(ctx, str_digest)) { Log(LOG_LEVEL_DEBUG, "This promise has already been verified"); return CfLockNull(); } EvalContextPromiseLockCachePut(ctx, str_digest); // Finally if we're supposed to ignore locks ... do the remaining stuff if (EvalContextIsIgnoringLocks(ctx)) { return CfLockNew(NULL, "dummy", NULL, true); } char *promise = BodyName(pp); char cc_operator[CF_BUFSIZE], cc_operand[CF_BUFSIZE]; snprintf(cc_operator, CF_MAXVARSIZE - 1, "%s-%s", promise, host); strlcpy(cc_operand, operand, CF_BUFSIZE); CanonifyNameInPlace(cc_operand); RemoveDates(cc_operand); free(promise); Log(LOG_LEVEL_DEBUG, "AcquireLock(%s,%s), ExpireAfter = %d, IfElapsed = %d", cc_operator, cc_operand, tc.expireafter, tc.ifelapsed); int sum = 0; for (int i = 0; cc_operator[i] != '\0'; i++) { sum = (CF_MACROALPHABET * sum + cc_operator[i]) % CF_HASHTABLESIZE; } for (int i = 0; cc_operand[i] != '\0'; i++) { sum = (CF_MACROALPHABET * sum + cc_operand[i]) % CF_HASHTABLESIZE; } char cflog[CF_BUFSIZE] = ""; snprintf(cflog, CF_BUFSIZE, "%s/cf3.%.40s.runlog", GetLogDir(), host); char cflock[CF_BUFSIZE] = ""; snprintf(cflock, CF_BUFSIZE, "lock.%.100s.%s.%.100s_%d_%s", PromiseGetBundle(pp)->name, cc_operator, cc_operand, sum, str_digest); char cflast[CF_BUFSIZE] = ""; snprintf(cflast, CF_BUFSIZE, "last.%.100s.%s.%.100s_%d_%s", PromiseGetBundle(pp)->name, cc_operator, cc_operand, sum, str_digest); Log(LOG_LEVEL_DEBUG, "Log for bundle '%s', '%s'", PromiseGetBundle(pp)->name, cflock); // Now see if we can get exclusivity to edit the locks WaitForCriticalSection(CF_CRITIAL_SECTION); // Look for non-existent (old) processes time_t lastcompleted = FindLock(cflast); time_t elapsedtime = (time_t) (now - lastcompleted) / 60; if (elapsedtime < 0) { Log(LOG_LEVEL_VERBOSE, "XX Another cf-agent seems to have done this since I started (elapsed=%jd)", (intmax_t) elapsedtime); ReleaseCriticalSection(CF_CRITIAL_SECTION); return CfLockNull(); } if (elapsedtime < tc.ifelapsed) { Log(LOG_LEVEL_VERBOSE, "XX Nothing promised here [%.40s] (%jd/%u minutes elapsed)", cflast, (intmax_t) elapsedtime, tc.ifelapsed); ReleaseCriticalSection(CF_CRITIAL_SECTION); return CfLockNull(); } // Look for existing (current) processes lastcompleted = FindLock(cflock); if (!ignoreProcesses) { elapsedtime = (time_t) (now - lastcompleted) / 60; if (lastcompleted != 0) { if (elapsedtime >= tc.expireafter) { Log(LOG_LEVEL_INFO, "Lock %s expired (after %jd/%u minutes)", cflock, (intmax_t) elapsedtime, tc.expireafter); pid_t pid = FindLockPid(cflock); if (KillLockHolder(cflock)) { LogLockCompletion(cflog, pid, "Lock expired, process killed", cc_operator, cc_operand); unlink(cflock); } else { Log(LOG_LEVEL_ERR, "Unable to kill expired process %d from lock %s", (int)pid, cflock); } } else { ReleaseCriticalSection(CF_CRITIAL_SECTION); Log(LOG_LEVEL_VERBOSE, "Couldn't obtain lock for %s (already running!)", cflock); return CfLockNull(); } } int ret = WriteLock(cflock); if (ret != -1) { /* Register a cleanup handler *after* having opened the DB, so that * CloseAllDB() atexit() handler is registered in advance, and it is * called after removing this lock. * There is a small race condition here that we'll leave a stale lock * if we exit before the following line. */ pthread_once(&lock_cleanup_once, &RegisterLockCleanup); } } ReleaseCriticalSection(CF_CRITIAL_SECTION); // Keep this as a global for signal handling strcpy(CFLOCK, cflock); strcpy(CFLAST, cflast); strcpy(CFLOG, cflog); return CfLockNew(cflast, cflock, cflog, false); } void YieldCurrentLock(CfLock lock) { if (lock.is_dummy) { free(lock.lock); /* allocated in AquireLock as a special case */ return; } if (lock.lock == (char *) CF_UNDEFINED) { return; } Log(LOG_LEVEL_DEBUG, "Yielding lock '%s'", lock.lock); if (RemoveLock(lock.lock) == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to remove lock %s", lock.lock); free(lock.last); free(lock.lock); free(lock.log); return; } if (WriteLock(lock.last) == -1) { Log(LOG_LEVEL_ERR, "Unable to create '%s'. (creat: %s)", lock.last, GetErrorStr()); free(lock.last); free(lock.lock); free(lock.log); return; } /* This lock has ben yield'ed, don't try to yield it again in case process * is terminated abnormally. */ strcpy(CFLOCK, ""); strcpy(CFLAST, ""); strcpy(CFLOG, ""); LogLockCompletion(lock.log, getpid(), "Lock removed normally ", lock.lock, ""); free(lock.last); free(lock.lock); free(lock.log); } void GetLockName(char *lockname, const char *locktype, const char *base, const Rlist *params) { int max_sample, count = 0; for (const Rlist *rp = params; rp != NULL; rp = rp->next) { count++; } if (count) { max_sample = CF_BUFSIZE / (2 * count); } else { max_sample = 0; } strncpy(lockname, locktype, CF_BUFSIZE / 10); strcat(lockname, "_"); strncat(lockname, base, CF_BUFSIZE / 10); strcat(lockname, "_"); for (const Rlist *rp = params; rp != NULL; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: strncat(lockname, RlistScalarValue(rp), max_sample); break; case RVAL_TYPE_FNCALL: strncat(lockname, RlistFnCallValue(rp)->name, max_sample); break; default: ProgrammingError("Unhandled case in switch %d", rp->val.type); break; } } } static void CopyLockDatabaseAtomically(const char *from, const char *to, const char *from_pretty_name, const char *to_pretty_name) { char *tmp_file_name; xasprintf(&tmp_file_name, "%s.tmp", to); int from_fd = open(from, O_RDONLY | O_BINARY); if (from_fd < 0) { Log(LOG_LEVEL_WARNING, "Could not open %s. (open: '%s')", from_pretty_name, GetErrorStr()); goto cleanup_1; } int to_fd = open(tmp_file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); if (to_fd < 0) { Log(LOG_LEVEL_WARNING, "Could not open %s temporary file. (open: '%s')", to_pretty_name, GetErrorStr()); goto cleanup_2; } char data[CF_BUFSIZE]; while (1) { int read_status = read(from_fd, data, sizeof(data)); if (read_status < 0) { Log(LOG_LEVEL_WARNING, "Could not read from %s. (read: '%s')", from_pretty_name, GetErrorStr()); goto cleanup_4; } else if (read_status == 0) { break; } int write_status = write(to_fd, data, read_status); if (write_status < 0) { Log(LOG_LEVEL_WARNING, "Could not write to %s. (write: '%s')", to_pretty_name, GetErrorStr()); goto cleanup_4; } else if (write_status == 0) { Log(LOG_LEVEL_WARNING, "Could not write to %s. (write: 'Unknown error')", to_pretty_name); goto cleanup_4; } } // Make sure changes are persistent on disk, so database cannot get corrupted at system crash. if (fsync(to_fd) != 0) { Log(LOG_LEVEL_WARNING, "Could not sync %s file to disk. (fsync: '%s')", to_pretty_name, GetErrorStr()); goto cleanup_4; } close(to_fd); if (rename(tmp_file_name, to) != 0) { Log(LOG_LEVEL_WARNING, "Could not move %s into place. (rename: '%s')", to_pretty_name, GetErrorStr()); goto cleanup_3; } // Finished. goto cleanup_3; cleanup_4: close(to_fd); cleanup_3: unlink(tmp_file_name); cleanup_2: close(from_fd); cleanup_1: free(tmp_file_name); } void BackupLockDatabase(void) { WaitForCriticalSection(CF_CRITIAL_SECTION); char *db_path = DBIdToPath(GetWorkDir(), dbid_locks); char *db_path_backup; xasprintf(&db_path_backup, "%s.backup", db_path); CopyLockDatabaseAtomically(db_path, db_path_backup, "lock database", "lock database backup"); free(db_path); free(db_path_backup); ReleaseCriticalSection(CF_CRITIAL_SECTION); } static void RestoreLockDatabase(void) { // We don't do any locking here (since we can't trust the database), but // this should be right after bootup, so we should be the only one. // Worst case someone else will just copy the same file to the same // location. char *db_path = DBIdToPath(GetWorkDir(), dbid_locks); char *db_path_backup; xasprintf(&db_path_backup, "%s.backup", db_path); CopyLockDatabaseAtomically(db_path_backup, db_path, "lock database backup", "lock database"); free(db_path); free(db_path_backup); } void PurgeLocks(void) { CF_DBC *dbcp; char *key; int ksize, vsize; LockData lock_horizon; LockData *entry = NULL; time_t now = time(NULL); CF_DB *dbp = OpenLock(); if(!dbp) { return; } memset(&lock_horizon, 0, sizeof(lock_horizon)); if (ReadDB(dbp, "lock_horizon", &lock_horizon, sizeof(lock_horizon))) { if (now - lock_horizon.time < SECONDS_PER_WEEK * 4) { Log(LOG_LEVEL_VERBOSE, "No lock purging scheduled"); CloseLock(dbp); return; } } Log(LOG_LEVEL_VERBOSE, "Looking for stale locks to purge"); if (!NewDBCursor(dbp, &dbcp)) { CloseLock(dbp); return; } while (NextDB(dbcp, &key, &ksize, (void **)&entry, &vsize)) { #ifdef LMDB if (key[0] == 'X') { continue; } #else if (strncmp(key, "last.internal_bundle.track_license.handle", strlen("last.internal_bundle.track_license.handle")) == 0) { continue; } #endif if (now - entry->time > (time_t) CF_LOCKHORIZON) { Log(LOG_LEVEL_VERBOSE, " --> Purging lock (%jd) %s", (intmax_t)(now - entry->time), key); DBCursorDeleteEntry(dbcp); } } lock_horizon.time = now; DeleteDBCursor(dbcp); WriteDB(dbp, "lock_horizon", &lock_horizon, sizeof(lock_horizon)); CloseLock(dbp); } int WriteLock(const char *name) { CF_DB *dbp; ThreadLock(cft_lock); if ((dbp = OpenLock()) == NULL) { ThreadUnlock(cft_lock); return -1; } WriteLockDataCurrent(dbp, name); CloseLock(dbp); ThreadUnlock(cft_lock); return 0; } static void VerifyThatDatabaseIsNotCorrupt_once(void) { int uptime = GetUptimeSeconds(time(NULL)); if (uptime <= 0) { Log(LOG_LEVEL_VERBOSE, "Not able to determine uptime when verifying lock database. " "Will assume the database is in order."); return; } char *db_path = DBIdToPath(GetWorkDir(), dbid_locks); struct stat statbuf; if (stat(db_path, &statbuf) == 0) { if (statbuf.st_mtime < time(NULL) - uptime) { // We have rebooted since the database was last updated. // Restore it from our backup. RestoreLockDatabase(); } } free(db_path); } static void VerifyThatDatabaseIsNotCorrupt(void) { static pthread_once_t uptime_verified = PTHREAD_ONCE_INIT; pthread_once(&uptime_verified, &VerifyThatDatabaseIsNotCorrupt_once); } CF_DB *OpenLock() { CF_DB *dbp; VerifyThatDatabaseIsNotCorrupt(); if (!OpenDB(&dbp, dbid_locks)) { return NULL; } return dbp; } void CloseLock(CF_DB *dbp) { if (dbp) { CloseDB(dbp); } } cfengine-3.6.2/libpromises/var_expressions.h0000664000175100017510000000471612400110676020756 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VAR_EXPRESSIONS_H #define CFENGINE_VAR_EXPRESSIONS_H #include #include #include typedef struct { size_t hash; char *ns; char *scope; char *lval; char **indices; size_t num_indices; } VarRef; VarRef *VarRefCopy(const VarRef *ref); VarRef *VarRefCopyLocalized(const VarRef *ref); VarRef *VarRefCopyIndexless(const VarRef *ref); VarRef *VarRefParse(const char *var_ref_string); /** * @brief Parse the variable reference in the context of a bundle. This means that the VarRef will inherit scope and namespace * of the bundle if these are not specified explicitly in the string. */ VarRef *VarRefParseFromBundle(const char *var_ref_string, const Bundle *bundle); VarRef *VarRefParseFromScope(const char *var_ref_string, const char *scope); VarRef *VarRefParseFromNamespaceAndScope(const char *qualified_name, const char *_ns, const char *_scope, char ns_separator, char scope_separator); VarRef VarRefConst(const char *ns, const char *scope, const char *lval); void VarRefDestroy(VarRef *ref); char *VarRefToString(const VarRef *ref, bool qualified); char *VarRefMangle(const VarRef *ref); VarRef *VarRefDeMangle(const char *mangled_var_ref); void VarRefSetMeta(VarRef *ref, bool enabled); bool VarRefIsQualified(const VarRef *ref); void VarRefQualify(VarRef *ref, const char *ns, const char *scope); void VarRefAddIndex(VarRef *ref, const char *index); int VarRefCompare(const VarRef *a, const VarRef *b); #endif cfengine-3.6.2/libpromises/files_interfaces.c0000664000175100017510000000575512411001073021020 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include int cf_lstat(const char *file, struct stat *buf, FileCopy fc, AgentConnection *conn) { if (conn == NULL) { int ret = lstat(file, buf); if (ret == -1) { Log(LOG_LEVEL_ERR, "lstat: %s", GetErrorStr()); } return ret; } else { assert(fc.servers && strcmp(fc.servers->val.item, "localhost")); return cf_remote_stat(file, buf, "link", fc.encrypt, conn); } } ssize_t CfReadLine(char **buff, size_t *size, FILE *fp) { ssize_t b = getline(buff, size, fp); assert(b != 0 && "To the best of my knowledge, getline never returns zero"); if (b > 0) { if ((*buff)[b - 1] == '\n') { (*buff)[b - 1] = '\0'; b--; } } return b; } /* ssize_t CfReadLine(char *buff, size_t size, FILE *fp) { if (fgets(buff, size, fp) == NULL) { if (ferror(fp)) { return -1; } else { return 0; } } // We have got a line here size_t line_length = strlen(buff); // Check for \n char *nl = strchr(buff, '\n'); if (nl != NULL) { // If we have found a \n, then line was read fully. *nl = '\0'; return line_length; } // Read the remainder of the line for (;;) { int c = fgetc(fp); if (c == EOF) { if (ferror(fp)) { return -1; } else { // We have reached EOF, report the length of line read so far return line_length; } } line_length++; if (c == '\n') { return line_length; } } } */ cfengine-3.6.2/cf-agent/0000775000175100017510000000000012413020723014474 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-agent/files_properties.c0000644000175100017510000001145612316547775020252 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include static Item *SUSPICIOUSLIST = NULL; /* GLOBAL_P */ void AddFilenameToListOfSuspicious(const char *pattern) { PrependItem(&SUSPICIOUSLIST, pattern, NULL); } static const char *const SKIPFILES[] = { ".", "..", "lost+found", ".cfengine.rm", NULL }; static bool ConsiderFile(const char *nodename, const char *path, struct stat *stat) { int i; const char *sp; if (strlen(nodename) < 1) { Log(LOG_LEVEL_ERR, "Empty (null) filename detected in '%s'", path); return true; } if (stat != NULL && (S_ISREG(stat->st_mode) || S_ISLNK(stat->st_mode)) && IsItemIn(SUSPICIOUSLIST, nodename)) { Log(LOG_LEVEL_ERR, "Suspicious file '%s' found in '%s'", nodename, path); return false; } if (strcmp(nodename, "...") == 0) { Log(LOG_LEVEL_VERBOSE, "Possible DFS/FS cell node detected in '%s' ...", path); return true; } for (i = 0; SKIPFILES[i] != NULL; i++) { if (strcmp(nodename, SKIPFILES[i]) == 0) { Log(LOG_LEVEL_DEBUG, "Filename '%s/%s' is classified as ignorable", path, nodename); return false; } } if ((strcmp("[", nodename) == 0) && (strcmp("/usr/bin", path) == 0)) { #if defined(__linux__) return true; #endif } for (sp = nodename; *sp != '\0'; sp++) { if ((*sp > 31) && (*sp < 127)) { break; } } for (sp = nodename; *sp != '\0'; sp++) /* Check for files like ".. ." */ { if ((*sp != '.') && (!isspace((int)*sp))) { return true; } } if (stat == NULL) { /* stat is NULL so we can't make more checks, call this function again * but pass the stat info as well. */ return true; } if ((stat->st_size == 0) && LogGetGlobalLevel() < LOG_LEVEL_INFO) /* No sense in warning about empty files */ { return false; } Log(LOG_LEVEL_ERR, "Suspicious looking file object '%s' masquerading as hidden file in '%s'", nodename, path); if (S_ISLNK(stat->st_mode)) { Log(LOG_LEVEL_INFO, "'%s' is a symbolic link", nodename); } else if (S_ISDIR(stat->st_mode)) { Log(LOG_LEVEL_INFO, "'%s' is a directory", nodename); } Log(LOG_LEVEL_VERBOSE, "'%s' has size %ld and full mode %o", nodename, (unsigned long) (stat->st_size), (unsigned int) (stat->st_mode)); return true; } bool ConsiderLocalFile(const char *filename, const char *directory) { struct stat stat; if (lstat(filename, &stat) == -1) { return ConsiderFile(filename, directory, NULL); } else { return ConsiderFile(filename, directory, &stat); } } bool ConsiderAbstractFile(const char *filename, const char *directory, FileCopy fc, AgentConnection *conn) { /* First check if the file should be avoided, e.g. ".." - before sending * anything over the network*/ if (!ConsiderFile(filename, directory, NULL)) { return false; } /* TODO this function should accept the joined path in the first place * since it's joined elsewhere as well, if split needed do it here. */ char buf[CF_BUFSIZE]; int ret = snprintf(buf, sizeof(buf), "%s/%s", directory, filename); if (ret < 0 || ret >= sizeof(buf)) { Log(LOG_LEVEL_ERR, "Filename too long! Directory '%s' filename '%s'", directory, filename); return false; } struct stat stat; if (cf_lstat(buf, &stat, fc, conn) == -1) { return false; /* stat() failed */ } else { /* Reconsider, but using stat info this time. */ return ConsiderFile(filename, directory, &stat); } } cfengine-3.6.2/cf-agent/files_select.h0000664000175100017510000000237512243421446017325 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_SELECT_H #define CFENGINE_FILES_SELECT_H #include int SelectLeaf(EvalContext *ctx, char *path, struct stat *sb, FileSelect fs); /* For implementation in Nova */ int GetOwnerName(char *path, struct stat *lstatptr, char *owner, int ownerSz); #endif cfengine-3.6.2/cf-agent/verify_services.c0000664000175100017510000002002212411001073020036 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int ServicesSanityChecks(Attributes a, const Promise *pp); static void SetServiceDefaults(Attributes *a); static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, const Promise *pp); static PromiseResult VerifyServices(EvalContext *ctx, Attributes a, const Promise *pp); /*****************************************************************************/ PromiseResult VerifyServicesPromise(EvalContext *ctx, const Promise *pp) { Attributes a = GetServicesAttributes(ctx, pp); SetServiceDefaults(&a); if (ServicesSanityChecks(a, pp)) { return VerifyServices(ctx, a, pp); } else { return PROMISE_RESULT_NOOP; } } /*****************************************************************************/ static int ServicesSanityChecks(Attributes a, const Promise *pp) { Rlist *dep; switch (a.service.service_policy) { case SERVICE_POLICY_START: break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: case SERVICE_POLICY_RESTART: case SERVICE_POLICY_RELOAD: if (strcmp(a.service.service_autostart_policy, "none") != 0) { Log(LOG_LEVEL_ERR, "!! Autostart policy of service promiser '%s' needs to be 'none' when service policy is not 'start', but is '%s'", pp->promiser, a.service.service_autostart_policy); PromiseRef(LOG_LEVEL_ERR, pp); return false; } break; default: Log(LOG_LEVEL_ERR, "Invalid service policy for service '%s'", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return false; } for (dep = a.service.service_depend; dep != NULL; dep = dep->next) { if (strcmp(pp->promiser, RlistScalarValue(dep)) == 0) { Log(LOG_LEVEL_ERR, "Service promiser '%s' has itself as dependency", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return false; } } if (a.service.service_type == NULL) { Log(LOG_LEVEL_ERR, "Service type for service '%s' is not known", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return false; } #ifdef __MINGW32__ if (strcmp(a.service.service_type, "windows") != 0) { Log(LOG_LEVEL_ERR, "Service type for promiser '%s' must be 'windows' on this system, but is '%s'", pp->promiser, a.service.service_type); PromiseRef(LOG_LEVEL_ERR, pp); return false; } #endif /* __MINGW32__ */ return true; } /*****************************************************************************/ static void SetServiceDefaults(Attributes *a) { if (a->service.service_autostart_policy == NULL) { a->service.service_autostart_policy = "none"; } if (a->service.service_depend_chain == NULL) { a->service.service_depend_chain = "ignore"; } // default service type to "windows" on windows platforms #ifdef __MINGW32__ if (a->service.service_type == NULL) { a->service.service_type = "windows"; } #else if (a->service.service_type == NULL) { a->service.service_type = "bundle"; } #endif /* __MINGW32__ */ } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static PromiseResult VerifyServices(EvalContext *ctx, Attributes a, const Promise *pp) { CfLock thislock; thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } PromiseBanner(pp); PromiseResult result = PROMISE_RESULT_SKIPPED; if (strcmp(a.service.service_type, "windows") == 0) { #ifdef __MINGW32__ result = PromiseResultUpdate(result, VerifyWindowsService(ctx, a, pp)); #else Log(LOG_LEVEL_INFO, "Service type windows not supported on this platform."); #endif } else { result = PromiseResultUpdate(result, DoVerifyServices(ctx, a, pp)); } YieldCurrentLock(thislock); return result; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static FnCall *DefaultServiceBundleCall(const Promise *pp, ServicePolicy service_policy) { Rlist *args = NULL; switch (service_policy) { case SERVICE_POLICY_START: RlistAppend(&args, pp->promiser, RVAL_TYPE_SCALAR); RlistAppend(&args, "start", RVAL_TYPE_SCALAR); break; case SERVICE_POLICY_RESTART: RlistAppend(&args, pp->promiser, RVAL_TYPE_SCALAR); RlistAppend(&args, "restart", RVAL_TYPE_SCALAR); break; case SERVICE_POLICY_RELOAD: RlistAppend(&args, pp->promiser, RVAL_TYPE_SCALAR); RlistAppend(&args, "restart", RVAL_TYPE_SCALAR); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: RlistAppend(&args, pp->promiser, RVAL_TYPE_SCALAR); RlistAppend(&args, "stop", RVAL_TYPE_SCALAR); break; } FnCall *call = FnCallNew("standard_services", args); return call; } static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, const Promise *pp) { Rval call; { const Constraint *cp = PromiseGetConstraint(pp, "service_bundle"); if (cp) { call = RvalCopy(cp->rval); } else { call = (Rval) { DefaultServiceBundleCall(pp, a.service.service_policy), RVAL_TYPE_FNCALL }; } } a.havebundle = true; switch (a.service.service_policy) { case SERVICE_POLICY_START: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "start", CF_DATA_TYPE_STRING, "source=promise"); break; case SERVICE_POLICY_RESTART: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "restart", CF_DATA_TYPE_STRING, "source=promise"); break; case SERVICE_POLICY_RELOAD: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "reload", CF_DATA_TYPE_STRING, "source=promise"); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "stop", CF_DATA_TYPE_STRING, "source=promise"); break; } PromiseResult result = PROMISE_RESULT_NOOP; result = PromiseResultUpdate(result, VerifyMethod(ctx, call, a, pp)); // Send list of classes to set privately? RvalDestroy(call); return result; } cfengine-3.6.2/cf-agent/promiser_regex_resolver.c0000644000175100017510000001700012352557236021627 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* * This module provides functionality of resolving regular expressions in * promisers, such as in featured by files promise type and storage promise * type. */ #include #include #include #include #include #include #include #include #include #include #include #include PromiseResult LocateFilePromiserGroup(EvalContext *ctx, char *wildpath, const Promise *pp, PromiseResult (*fnptr) (EvalContext *ctx, char *path, const Promise *ptr)) { Item *path, *ip, *remainder = NULL; char pbuffer[CF_BUFSIZE]; struct stat statbuf; int count = 0, lastnode = false, expandregex = false; uid_t agentuid = getuid(); int create = PromiseGetConstraintAsBoolean(ctx, "create", pp); char *pathtype = PromiseGetConstraintAsRval(pp, "pathtype", RVAL_TYPE_SCALAR); /* Do a search for promiser objects matching wildpath */ if ((!IsPathRegex(wildpath)) || (pathtype && (strcmp(pathtype, "literal") == 0))) { Log(LOG_LEVEL_VERBOSE, "Using literal pathtype for '%s'", wildpath); return (*fnptr) (ctx, wildpath, pp); } else { Log(LOG_LEVEL_VERBOSE, "Using regex pathtype for '%s' (see pathtype)", wildpath); } pbuffer[0] = '\0'; path = SplitString(wildpath, '/'); // require forward slash in regex on all platforms PromiseResult result = PROMISE_RESULT_SKIPPED; for (ip = path; ip != NULL; ip = ip->next) { if ((ip->name == NULL) || (strlen(ip->name) == 0)) { continue; } if (ip->next == NULL) { lastnode = true; } /* No need to chdir as in recursive descent, since we know about the path here */ if (IsRegex(ip->name)) { remainder = ip->next; expandregex = true; break; } else { expandregex = false; } if (!JoinPath(pbuffer, ip->name)) { Log(LOG_LEVEL_ERR, "Buffer has limited size in LocateFilePromiserGroup"); return result; } if (stat(pbuffer, &statbuf) != -1) { if ((S_ISDIR(statbuf.st_mode)) && ((statbuf.st_uid) != agentuid) && ((statbuf.st_uid) != 0)) { Log(LOG_LEVEL_INFO, "Directory '%s' in search path '%s' is controlled by another user (uid %ju) - trusting its content is potentially risky (possible race condition)", pbuffer, wildpath, (uintmax_t)statbuf.st_uid); PromiseRef(LOG_LEVEL_INFO, pp); } } } if (expandregex) /* Expand one regex link and hand down */ { char nextbuffer[CF_BUFSIZE], nextbufferOrig[CF_BUFSIZE], regex[CF_BUFSIZE]; const struct dirent *dirp; Dir *dirh; strlcpy(regex, ip->name, CF_BUFSIZE); if ((dirh = DirOpen(pbuffer)) == NULL) { // Could be a dummy directory to be created so this is not an error. Log(LOG_LEVEL_VERBOSE, "Using best-effort expanded (but non-existent) file base path '%s'", wildpath); result = PromiseResultUpdate(result, (*fnptr) (ctx, wildpath, pp)); DeleteItemList(path); return result; } else { count = 0; for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!ConsiderLocalFile(dirp->d_name, pbuffer)) { continue; } if ((!lastnode) && (!S_ISDIR(statbuf.st_mode))) { Log(LOG_LEVEL_DEBUG, "Skipping non-directory '%s'", dirp->d_name); continue; } if (FullTextMatch(ctx, regex, dirp->d_name)) { Log(LOG_LEVEL_DEBUG, "Link '%s' matched regex '%s'", dirp->d_name, regex); } else { continue; } count++; strlcpy(nextbuffer, pbuffer, CF_BUFSIZE); AddSlash(nextbuffer); strcat(nextbuffer, dirp->d_name); for (ip = remainder; ip != NULL; ip = ip->next) { AddSlash(nextbuffer); strcat(nextbuffer, ip->name); } /* The next level might still contain regexs, so go again as long as expansion is not nullpotent */ if ((!lastnode) && (strcmp(nextbuffer, wildpath) != 0)) { result = PromiseResultUpdate(result, LocateFilePromiserGroup(ctx, nextbuffer, pp, fnptr)); } else { Promise *pcopy; Log(LOG_LEVEL_VERBOSE, "Using expanded file base path '%s'", nextbuffer); /* Now need to recompute any back references to get the complete path */ snprintf(nextbufferOrig, sizeof(nextbufferOrig), "%s", nextbuffer); MapNameForward(nextbuffer); if (!FullTextMatch(ctx, pp->promiser, nextbuffer)) { Log(LOG_LEVEL_DEBUG, "Error recomputing references for '%s' in '%s'", pp->promiser, nextbuffer); } /* If there were back references there could still be match.x vars to expand */ bool excluded = false; pcopy = ExpandDeRefPromise(ctx, pp, &excluded); if (excluded) { result = PromiseResultUpdate(result, PROMISE_RESULT_SKIPPED); } else { result = PromiseResultUpdate(result, (*fnptr) (ctx, nextbufferOrig, pcopy)); } PromiseDestroy(pcopy); } } DirClose(dirh); } } else { Log(LOG_LEVEL_VERBOSE, "Using file base path '%s'", pbuffer); result = PromiseResultUpdate(result, (*fnptr) (ctx, pbuffer, pp)); } if (count == 0) { Log(LOG_LEVEL_VERBOSE, "No promiser file objects matched as regular expression '%s'", wildpath); if (create) { result = PromiseResultUpdate(result, (*fnptr)(ctx, pp->promiser, pp)); } } DeleteItemList(path); return result; } cfengine-3.6.2/cf-agent/verify_databases.h0000644000175100017510000000222112316547775020202 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_DATABASES_H #define CFENGINE_VERIFY_DATABASES_H #include PromiseResult VerifyDatabasePromises(EvalContext *ctx, const Promise *pp); #endif cfengine-3.6.2/cf-agent/vercmp_internal.h0000664000175100017510000000226112243421446020046 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERCMP_INTERNAL_H #define CFENGINE_VERCMP_INTERNAL_H #include VersionCmpResult ComparePackageVersionsInternal(const char *v1, const char *v2, PackageVersionComparator cmp); #endif cfengine-3.6.2/cf-agent/files_editxml.c0000664000175100017510000026420412411001073017473 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include enum editxmltypesequence { elx_vars, elx_classes, elx_delete, elx_insert, elx_none }; static const char *const EDITXMLTYPESEQUENCE[] = { "vars", "classes", "build_xpath", "delete_tree", "insert_tree", "delete_attribute", "set_attribute", "delete_text", "set_text", "insert_text", "reports", NULL }; static PromiseResult KeepEditXmlPromise(EvalContext *ctx, const Promise *pp, void *param); #ifdef HAVE_LIBXML2 static bool VerifyXPathBuild(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static PromiseResult VerifyTreeDeletions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyTreeInsertions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyAttributeDeletions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyAttributeSet(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyTextDeletions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyTextSet(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyTextInsertions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext); static bool XmlSelectNode(EvalContext *ctx, char *xpath, xmlDocPtr doc, xmlNodePtr *docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool BuildXPathInFile(EvalContext *ctx, char xpath[CF_BUFSIZE], xmlDocPtr doc, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool BuildXPathInNode(EvalContext *ctx, char xpath[CF_BUFSIZE], xmlDocPtr doc, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool DeleteTreeInNode(EvalContext *ctx, char *tree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool InsertTreeInFile(EvalContext *ctx, char *root, xmlDocPtr doc, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool InsertTreeInNode(EvalContext *ctx, char *tree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool DeleteAttributeInNode(EvalContext *ctx, char *attrname, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool SetAttributeInNode(EvalContext *ctx, char *attrname, char *attrvalue, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool DeleteTextInNode(EvalContext *ctx, char *tree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool SetTextInNode(EvalContext *ctx, char *tree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool InsertTextInNode(EvalContext *ctx, char *tree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static bool SanityCheckXPathBuild(EvalContext *ctx, Attributes a, const Promise *pp, PromiseResult *result); static bool SanityCheckTreeDeletions(Attributes a); static bool SanityCheckTreeInsertions(Attributes a, EditContext *edcontext); static bool SanityCheckAttributeDeletions(Attributes a); static bool SanityCheckAttributeSet(Attributes a); static bool SanityCheckTextDeletions(Attributes a); static bool SanityCheckTextSet(Attributes a); static bool SanityCheckTextInsertions(Attributes a); static bool XmlDocsEqualMem(xmlDocPtr doc1, xmlDocPtr doc2); static bool XmlNodesCompare(xmlNodePtr node1, xmlNodePtr node2, Attributes a, const Promise *pp); static bool XmlNodesCompareAttributes(xmlNodePtr node1, xmlNodePtr node2); static bool XmlNodesCompareNodes(xmlNodePtr node1, xmlNodePtr node2, Attributes a, const Promise *pp); static bool XmlNodesCompareTags(const xmlNodePtr node1, const xmlNodePtr node2); static bool XmlNodesCompareText(xmlNodePtr node1, xmlNodePtr node2); static bool XmlNodesSubset(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp); static bool XmlNodesSubsetOfAttributes(const xmlNodePtr node1, const xmlNodePtr node2); static bool XmlNodesSubsetOfNodes(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp); static bool XmlNodesSubstringOfText(const xmlNodePtr node1, const xmlNodePtr node2); static xmlAttrPtr XmlVerifyAttributeInNode(const xmlChar *attrname, xmlChar *attrvalue, xmlNodePtr node); static bool XmlVerifyTextInNodeExact(const xmlChar *text, const xmlNodePtr node); static bool XmlVerifyTextInNodeSubstring(const xmlChar *text, xmlNodePtr node); static bool XmlVerifyNodeInNodeExact(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp); static xmlNodePtr XmlVerifyNodeInNodeSubset(xmlNodePtr node1, xmlNodePtr node2, Attributes a, const Promise *pp); //xpath build functionality static xmlNodePtr PredicateExtractNode(char predicate[CF_BUFSIZE]); static bool PredicateRemoveHead(char xpath[CF_BUFSIZE]); static xmlNodePtr XPathHeadExtractNode(EvalContext *ctx, char xpath[CF_BUFSIZE], Attributes a, const Promise *pp, PromiseResult *result); static xmlNodePtr XPathTailExtractNode(EvalContext *ctx, char xpath[CF_BUFSIZE], Attributes a, const Promise *pp, PromiseResult *result); static xmlNodePtr XPathSegmentExtractNode(char segment[CF_BUFSIZE]); static char* XPathGetTail(char xpath[CF_BUFSIZE]); static bool XPathRemoveHead(char xpath[CF_BUFSIZE]); static bool XPathRemoveTail(char xpath[CF_BUFSIZE]); //verification using PCRE - ContainsRegex static bool PredicateHasTail(char *predicate); static bool PredicateHeadContainsAttribute(char *predicate); static bool PredicateHeadContainsNode(char *predicate); static bool XPathHasTail(char *head); static bool XPathHeadContainsNode(char *head); static bool XPathHeadContainsPredicate(char *head); static bool XPathVerifyBuildSyntax(EvalContext *ctx, const char* xpath, Attributes a, const Promise *pp, PromiseResult *result); static bool XPathVerifyConvergence(const char* xpath); //helper functions static xmlChar *CharToXmlChar(char c[CF_BUFSIZE]); static bool ContainsRegex(const char* rawstring, const char* regex); static int XmlAttributeCount(const xmlNodePtr node); #endif /*****************************************************************************/ /* Level */ /*****************************************************************************/ int ScheduleEditXmlOperations(EvalContext *ctx, const Bundle *bp, Attributes a, const Promise *parentp, EditContext *edcontext) { enum editxmltypesequence type; char lockname[CF_BUFSIZE]; CfLock thislock; int pass; snprintf(lockname, CF_BUFSIZE - 1, "masterfilelock-%s", edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, parentp, true); if (thislock.lock == NULL) { return false; } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_EDIT, "filename", edcontext->filename, CF_DATA_TYPE_STRING, "source=promise"); for (pass = 1; pass < CF_DONEPASSES; pass++) { for (type = 0; EDITXMLTYPESEQUENCE[type] != NULL; type++) { const PromiseType *sp = BundleGetPromiseType(bp, EDITXMLTYPESEQUENCE[type]); if (!sp) { continue; } BannerSubPromiseType(ctx, bp->name, sp->name); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepEditXmlPromise, edcontext); if (Abort(ctx)) { YieldCurrentLock(thislock); EvalContextStackPopFrame(ctx); return false; } } EvalContextStackPopFrame(ctx); } } YieldCurrentLock(thislock); return true; } /***************************************************************************/ /* Level */ /***************************************************************************/ static PromiseResult KeepEditXmlPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { PromiseBanner(pp); if (strcmp("classes", pp->parent_promise_type->name) == 0) { return VerifyClassPromise(ctx, pp, NULL); } else if (strcmp("build_xpath", pp->parent_promise_type->name) == 0) { Attributes a = GetInsertionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = PROMISE_RESULT_NOOP; VerifyXPathBuild(ctx, a, pp, edcontext, &result); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2."); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("delete_tree", pp->parent_promise_type->name) == 0) { Attributes a = GetDeletionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyTreeDeletions(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("insert_tree", pp->parent_promise_type->name) == 0) { Attributes a = GetInsertionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyTreeInsertions(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("delete_attribute", pp->parent_promise_type->name) == 0) { Attributes a = GetDeletionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyAttributeDeletions(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("set_attribute", pp->parent_promise_type->name) == 0) { Attributes a = GetInsertionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyAttributeSet(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("delete_text", pp->parent_promise_type->name) == 0) { Attributes a = GetDeletionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyTextDeletions(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("set_text", pp->parent_promise_type->name) == 0) { Attributes a = GetInsertionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyTextSet(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("insert_text", pp->parent_promise_type->name) == 0) { Attributes a = GetInsertionAttributes(ctx, pp); #ifdef HAVE_LIBXML2 EditContext *edcontext = param; PromiseResult result = VerifyTextInsertions(ctx, a, pp, edcontext); return result; #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); return PROMISE_RESULT_FAIL; #endif } else if (strcmp("reports", pp->parent_promise_type->name) == 0) { return VerifyReportPromise(ctx, pp); } return PROMISE_RESULT_NOOP; } /***************************************************************************/ #ifdef HAVE_LIBXML2 /***************************************************************************/ static bool VerifyXPathBuild(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlDocPtr doc = NULL; CfLock thislock; char lockname[CF_BUFSIZE], rawxpath[CF_BUFSIZE] = { 0 }; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; if (a.xml.havebuildxpath) { strcpy(rawxpath, a.xml.build_xpath); } else { strcpy(rawxpath, pp->promiser); } if (!SanityCheckXPathBuild(ctx, a, pp, result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath build: '%s', breaks its own promises", rawxpath); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } snprintf(lockname, CF_BUFSIZE - 1, "buildxpath-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return false; } //build XPath in an empty file if (!xmlDocGetRootElement(doc)) { if (BuildXPathInFile(ctx, rawxpath, doc, a, pp, edcontext, result)) { (edcontext->num_edits)++; } } //build XPath in a nonempty file else if (BuildXPathInNode(ctx, rawxpath, doc, a, pp, edcontext, result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return true; } /***************************************************************************/ static PromiseResult VerifyTreeDeletions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; if (!SanityCheckTreeDeletions(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree deletion '%s' is inconsistent", pp->promiser); return PROMISE_RESULT_INTERRUPTED; } PromiseResult result = PROMISE_RESULT_NOOP; if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (!XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s)", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "deletetree-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } if (DeleteTreeInNode(ctx, pp->promiser, doc, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyTreeInsertions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; PromiseResult result = PROMISE_RESULT_NOOP; if (!SanityCheckTreeInsertions(a, edcontext)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree insertion '%s' breaks its own promises", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } //if file is not empty: select an edit node, for tree insertion if (a.xml.haveselectxpath && !XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s'", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "inserttree-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } //insert tree into empty file or selected node if (!a.xml.haveselectxpath) { if (InsertTreeInFile(ctx, pp->promiser, doc, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } } else if (InsertTreeInNode(ctx, pp->promiser, doc, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyAttributeDeletions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; PromiseResult result = PROMISE_RESULT_NOOP; if (!SanityCheckAttributeDeletions(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised attribute deletion '%s', is inconsistent", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (!XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s'", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "deleteattribute-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } if (DeleteAttributeInNode(ctx, pp->promiser, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyAttributeSet(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; PromiseResult result = PROMISE_RESULT_NOOP; if (!SanityCheckAttributeSet(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised attribute set '%s', breaks its own promises", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (!XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s'", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "setattribute-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } if (SetAttributeInNode(ctx, pp->promiser, a.xml.attribute_value, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyTextDeletions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; PromiseResult result = PROMISE_RESULT_NOOP; if (!SanityCheckTextDeletions(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised text deletion '%s' is inconsistent", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (!XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s'", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "deletetext-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } if (DeleteTextInNode(ctx, pp->promiser, doc, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyTextSet(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; PromiseResult result = PROMISE_RESULT_NOOP; if (!SanityCheckTextSet(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised text set '%s' breaks its own promises", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (!XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s'", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "settext-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } if (SetTextInNode(ctx, pp->promiser, doc, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyTextInsertions(EvalContext *ctx, Attributes a, const Promise *pp, EditContext *edcontext) { xmlDocPtr doc = NULL; xmlNodePtr docnode = NULL; CfLock thislock; char lockname[CF_BUFSIZE]; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; PromiseResult result = PROMISE_RESULT_NOOP; if (!SanityCheckTextInsertions(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised text insertion '%s' breaks its own promises", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (a.xml.havebuildxpath && !VerifyXPathBuild(ctx, a, pp, edcontext, &result)) { return result; } if ((doc = edcontext->xmldoc) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to load XML document"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (!XmlSelectNode(ctx, a.xml.select_xpath, doc, &docnode, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT successful when selecting an edit node, in XML document '%s'", a.xml.select_xpath, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "inserttext-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return result; } if (InsertTextInNode(ctx, pp->promiser, doc, docnode, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ /* This should provide pointers to the edit node within the XML document. It returns true if a match was identified, else false. If no such node matches, docnode should point to NULL */ static bool XmlSelectNode(EvalContext *ctx, char *rawxpath, xmlDocPtr doc, xmlNodePtr *docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr cur = NULL; xmlXPathContextPtr xpathCtx = NULL; xmlXPathObjectPtr xpathObj = NULL; xmlNodeSetPtr nodes = NULL; const xmlChar* xpathExpr = NULL; int i, size = 0; bool valid = true; *docnode = NULL; if (!XPathVerifyConvergence(rawxpath)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "select_xpath expression '%s', is NOT convergent", rawxpath); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if ((xpathExpr = CharToXmlChar(rawxpath)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to create new XPath expression '%s'", rawxpath); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if ((xpathCtx = xmlXPathNewContext(doc)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to create new XPath context '%s'", rawxpath); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if ((xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to evaluate XPath expression '%s'", xpathExpr); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); xmlXPathFreeContext(xpathCtx); return false; } nodes = xpathObj->nodesetval; if ((size = nodes ? nodes->nodeNr : 0) == 0) { valid = false; } if (size > 1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Current select_xpath expression '%s', returns (%d) edit nodes in XML document '%s', please modify expression to select a unique edit node", xpathExpr, size, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); valid = false; } //select first matching node if (valid) { for (i = 0; i < size; ++i) { if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) { cur = nodes->nodeTab[i]; break; } } if (cur == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath pattern '%s', was NOT found when selecting an edit node, in XML document '%s'", xpathExpr, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); valid = false; } } *docnode = cur; xmlXPathFreeContext(xpathCtx); xmlXPathFreeObject(xpathObj); return valid; } /***************************************************************************/ static bool BuildXPathInFile(EvalContext *ctx, char rawxpath[CF_BUFSIZE], xmlDocPtr doc, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr docnode = NULL, head = NULL; char copyxpath[CF_BUFSIZE] = { 0 }; strcpy(copyxpath, rawxpath); if (xmlDocGetRootElement(doc)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised XML document '%s' already exists and contains a root element (promise kept)", edcontext->filename); return false; } //set rootnode if ((docnode = XPathHeadExtractNode(ctx, copyxpath, a, pp, result)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to extract root node from XPath '%s', to be inserted into an empty XML document '%s'", rawxpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if (docnode == NULL || (docnode->name) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The extracted root node, from XPath '%s', to be inserted into an empty XML document '%s', is empty", rawxpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //insert the content into new XML document, beginning from root node cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Building XPath '%s', into an empty XML document '%s'", rawxpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if (xmlDocSetRootElement(doc, docnode) != NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised XPath '%s' was NOT built successfully into an empty XML document '%s'", rawxpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } XPathRemoveHead(copyxpath); //extract and insert nodes from tail while ((strlen(copyxpath) > 0) && ((head = XPathHeadExtractNode(ctx, copyxpath, a, pp, result)) != NULL)) { xmlAddChild(docnode, head); docnode = head; XPathRemoveHead(copyxpath); } return true; } /***************************************************************************/ static bool BuildXPathInNode(EvalContext *ctx, char rawxpath[CF_BUFSIZE], xmlDocPtr doc, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr docnode = NULL, head = NULL, tail = NULL; char copyxpath[CF_BUFSIZE] = { 0 }; strcpy(copyxpath, rawxpath); //build XPath from tail while locating insertion node while ((strlen(copyxpath) > 0) && (!XmlSelectNode(ctx, copyxpath, doc, &docnode, a, pp, edcontext, result))) { if (XPathHasTail (copyxpath)) { head = XPathTailExtractNode(ctx, copyxpath, a, pp, result); XPathRemoveTail(copyxpath); } else { head = XPathHeadExtractNode(ctx, copyxpath, a, pp, result); XPathRemoveHead(copyxpath); } if (head && tail) { xmlAddChild(head, tail); } tail = head; } //insert the new tree into selected node in XML document cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Building XPath '%s', in XML document '%s'", rawxpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if (docnode != NULL) { xmlAddChild(docnode, tail); } //insert the new tree into root, in the case where unique node was not found, in XML document else { docnode = xmlDocGetRootElement(doc); xmlAddChild(docnode, tail); } return true; } /***************************************************************************/ static bool InsertTreeInFile(EvalContext *ctx, char *rawtree, xmlDocPtr doc, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr treenode = NULL, rootnode = NULL; xmlChar *buf = NULL; //for parsing subtree from memory if ((buf = CharToXmlChar(rawtree)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Tree to be inserted '%s' into an empty XML document '%s', was NOT successfully loaded into an XML buffer", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //parse the subtree if (xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, buf, &treenode) != 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Tree to be inserted '%s' into an empty XML document '%s', was NOT parsed successfully", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if (treenode == NULL || (treenode->name) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree to be inserted '%s' into an empty XML document '%s', is empty", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify treenode does not already exist inside docnode if ((rootnode = xmlDocGetRootElement(doc)) != NULL) { if (!XmlNodesCompare(treenode, rootnode, a, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree '%s' is to be inserted into an empty XML document '%s'," " however XML document is NOT empty and tree to be inserted does NOT match existing content." " If you would like to insert into a non-empty XML document, please specify select_xpath expression", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised XML document '%s' already exists and contains a root element (promise kept)", edcontext->filename); } return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to insert the promised tree '%s' into an empty XML document '%s' - but only a warning was promised", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //insert the content into new XML document cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Inserting tree '%s' into an empty XML document '%s'", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if (xmlDocSetRootElement(doc, treenode) != NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree '%s' was NOT inserted successfully, into an empty XML document '%s'", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify node was inserted if (((rootnode = xmlDocGetRootElement(doc)) == NULL) || !XmlNodesCompare(treenode, rootnode, a, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree '%s' was NOT inserted successfully, into an empty XML document '%s'", rawtree, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool DeleteTreeInNode(EvalContext *ctx, char *rawtree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { //for parsing subtree from memory const xmlChar *buf = CharToXmlChar(rawtree); if (!buf) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Tree to be deleted '%s' at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //parse the subtree xmlNodePtr treenode = NULL; if (xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, buf, &treenode) != 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Tree to be deleted '%s' at XPath '%s' in XML document '%s', was NOT parsed successfully", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); xmlFreeNode(treenode); return false; } //verify treenode exists inside docnode xmlNodePtr deletetree = NULL; if ((deletetree = XmlVerifyNodeInNodeSubset(treenode, docnode, a, pp)) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised tree to be deleted '%s' does NOT exist, at XPath '%s' in XML document '%s' (promise kept)", rawtree, a.xml.select_xpath, edcontext->filename); xmlFreeNode(treenode); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to delete the promised tree '%s' at XPath '%s' in XML document '%s' - but only a warning was promised", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); xmlFreeNode(treenode); xmlFreeNode(deletetree); return true; } //remove the subtree from XML document cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Deleting tree '%s' at XPath '%s' in XML document '%s'", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); xmlUnlinkNode(deletetree); xmlFreeNode(deletetree); //verify treenode no longer exists inside docnode { xmlNodePtr ret = XmlVerifyNodeInNodeSubset(treenode, docnode, a, pp); if (ret) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree to be deleted '%s' was NOT successfully deleted, at XPath '%s' in XML document '%s'", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); xmlFreeNode(treenode); xmlFreeNode(ret); return false; } } xmlFreeNode(treenode); return true; } /***************************************************************************/ static bool InsertTreeInNode(EvalContext *ctx, char *rawtree, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr treenode = NULL; xmlChar *buf = NULL; //for parsing subtree from memory if ((buf = CharToXmlChar(rawtree)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Tree to be inserted '%s' at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //parse the subtree if (xmlParseBalancedChunkMemory(doc, NULL, NULL, 0, buf, &treenode) != 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Tree to be inserted '%s' at XPath '%s' in XML document '%s', was NOT parsed successfully", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if (treenode == NULL || (treenode->name) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree to be inserted '%s' at XPath '%s' in XML document '%s', is empty", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify treenode does not already exist inside docnode if (XmlVerifyNodeInNodeSubset(treenode, docnode, a, pp)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised tree to be inserted '%s' already exists, at XPath '%s' in XML document '%s' (promise kept)", rawtree, a.xml.select_xpath, edcontext->filename); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to insert the promised tree '%s' at XPath '%s' in XML document '%s' - but only a warning was promised", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //insert the subtree into XML document cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Inserting tree '%s' at XPath '%s' in XML document '%s'", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if (!xmlAddChild(docnode, treenode)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree '%s' was NOT inserted successfully, at XPath '%s' in XML document '%s'", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify node was inserted if (!XmlVerifyNodeInNodeSubset(treenode, docnode, a, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised tree '%s' was NOT inserted successfully, at XPath '%s' in XML document '%s'", rawtree, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool DeleteAttributeInNode(EvalContext *ctx, char *rawname, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlAttrPtr attr = NULL; xmlChar *name = NULL; if ((name = CharToXmlChar(rawname)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Name of attribute to be deleted '%s', at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawname, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify attribute exists inside docnode if ((attr = xmlHasProp(docnode, name)) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised attribute to be deleted '%s', does NOT exist, at XPath '%s' in XML document '%s' (promise kept)", rawname, a.xml.select_xpath, edcontext->filename); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to delete the promised attribute '%s', at XPath '%s' in XML document '%s' - but only a warning was promised", rawname, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //delete attribute from docnode cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Deleting attribute '%s', at XPath '%s' in XML document '%s'", rawname, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if ((xmlRemoveProp(attr)) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised attribute to be deleted '%s', was NOT deleted successfully, at XPath '%s' in XML document '%s'.", rawname, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify attribute no longer exists inside docnode if ((attr = xmlHasProp(docnode, name)) != NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised attribute to be deleted '%s', was NOT deleted successfully, at XPath '%s' in XML document '%s'", rawname, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool SetAttributeInNode(EvalContext *ctx, char *rawname, char *rawvalue, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlAttrPtr attr = NULL; xmlChar *name = NULL; xmlChar *value = NULL; if ((name = CharToXmlChar(rawname)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Name of attribute to be set '%s', at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawname, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if ((value = CharToXmlChar(rawvalue)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Value of attribute to be set '%s', at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawvalue, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify attribute does not already exist inside docnode if ((attr = XmlVerifyAttributeInNode(name, value, docnode)) != NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised attribute to be set, with name '%s' and value '%s', already exists, at XPath '%s' in XML document '%s' (promise kept)", rawname, rawvalue, a.xml.select_xpath, edcontext->filename); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to set the promised attribute, with name '%s' and value '%s', at XPath '%s' in XML document '%s' - but only a warning was promised", rawname, rawvalue, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //set attribute in docnode cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Setting attribute with name '%s' and value '%s', at XPath '%s' in XML document '%s'", rawname, rawvalue, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if ((attr = xmlSetProp(docnode, name, value)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised attribute to be set, with name '%s' and value '%s', was NOT successfully set, at XPath '%s' in XML document '%s'", rawname, rawvalue, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify attribute was inserted if ((attr = XmlVerifyAttributeInNode(name, value, docnode)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised attribute to be set, with name '%s' and value '%s', was NOT successfully set, at XPath '%s' in XML document '%s'", rawname, rawvalue, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool DeleteTextInNode(EvalContext *ctx, char *rawtext, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr elemnode, copynode; xmlChar *text = NULL; if ((text = CharToXmlChar(rawtext)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Text to be deleted '%s' at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify text exists inside docnode if (!XmlVerifyTextInNodeSubstring(text, docnode)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised text to be deleted '%s' does NOT exist, at XPath '%s' in XML document '%s' (promise kept)", rawtext, a.xml.select_xpath, edcontext->filename); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to delete the promised text '%s' at XPath '%s' in XML document '%s' - but only a warning was promised", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //delete text from docnode cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Deleting text '%s' at XPath '%s' in XML document '%s'", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); //node contains text if (xmlNodeIsText(docnode->children)) { xmlNodeSetContent(docnode->children, ""); } //node does not contain text else { //remove and set aside the elements in the node elemnode = xmlFirstElementChild(docnode); copynode = xmlDocCopyNodeList(doc, elemnode); xmlNodeSetContent(docnode, ""); //re-insert elements after the inserted text xmlAddChildList(docnode, copynode); } //verify text no longer exists inside docnode if (XmlVerifyTextInNodeSubstring(text, docnode)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised text '%s' was NOT deleted successfully, at XPath '%s' in XML document '%s'", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool SetTextInNode(EvalContext *ctx, char *rawtext, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr elemnode, copynode; xmlChar *text = NULL; if ((text = CharToXmlChar(rawtext)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Text to be set '%s' at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify text does not exist inside docnode if (XmlVerifyTextInNodeExact(text, docnode)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised text to be set '%s' already exists, at XPath '%s' in XML document '%s' (promise kept)", rawtext, a.xml.select_xpath, edcontext->filename); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to set the promised text '%s' at XPath '%s' in XML document '%s' - but only a warning was promised", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //set text in docnode cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Setting text '%s' at XPath '%s' in XML document '%s'", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); //node already contains text if (xmlNodeIsText(docnode->children)) { xmlNodeSetContent(docnode->children, text); } //node does not contain text else { //remove and set aside the elements in the node elemnode = xmlFirstElementChild(docnode); copynode = xmlDocCopyNodeList(doc, elemnode); xmlNodeSetContent(docnode, text); //re-insert elements after the inserted text xmlAddChildList(docnode, copynode); } //verify text was inserted if (!XmlVerifyTextInNodeExact(text, docnode)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised text '%s' was NOT set successfully, at XPath '%s' in XML document '%s'", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool InsertTextInNode(EvalContext *ctx, char *rawtext, xmlDocPtr doc, xmlNodePtr docnode, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { xmlNodePtr elemnode, copynode; xmlChar *text = NULL; if ((text = CharToXmlChar(rawtext)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Text to be inserted '%s' at XPath '%s' in XML document '%s', was NOT successfully loaded into an XML buffer", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } //verify text does not exist inside docnode if (XmlVerifyTextInNodeSubstring(text, docnode)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "The promised text to be inserted '%s' already exists, at XPath '%s' in XML document '%s' (promise kept)", rawtext, a.xml.select_xpath, edcontext->filename); return false; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to insert the promised text '%s' at XPath '%s' in XML document '%s' - but only a warning was promised", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } //insert text into docnode cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Inserting text '%s' at XPath '%s' in XML document '%s'", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); //node already contains text if (xmlNodeIsText(docnode->children)) { xmlNodeAddContent(docnode->children, text); } //node does not contain text else { //remove and set aside the elements in the node elemnode = xmlFirstElementChild(docnode); copynode = xmlDocCopyNodeList(doc, elemnode); xmlNodeSetContent(docnode, ""); xmlNodeAddContent(docnode, text); //re-insert elements after the inserted text xmlAddChildList(docnode, copynode); } //verify text was inserted if (!XmlVerifyTextInNodeSubstring(text, docnode)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised text '%s' was NOT inserted successfully, at XPath '%s' in XML document '%s'", rawtext, a.xml.select_xpath, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /***************************************************************************/ static bool SanityCheckXPathBuild(EvalContext *ctx, Attributes a, const Promise *pp, PromiseResult *result) { char rawxpath[CF_BUFSIZE] = { 0 }; if (a.xml.havebuildxpath) { strcpy(rawxpath, a.xml.build_xpath); } else { strcpy(rawxpath, pp->promiser); } if ((strcmp("build_xpath", pp->parent_promise_type->name) == 0) && (a.xml.havebuildxpath)) { Log(LOG_LEVEL_ERR, "Attribute: build_xpath is not allowed within bundle: build_xpath"); return false; } if (a.xml.haveselectxpath && !a.xml.havebuildxpath) { Log(LOG_LEVEL_ERR, "XPath build does not require select_xpath to be specified"); return false; } if (!XPathVerifyBuildSyntax(ctx, rawxpath, a, pp, result)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckTreeDeletions(Attributes a) { if (!a.xml.haveselectxpath) { Log(LOG_LEVEL_ERR, "Tree deletion requires select_xpath to be specified"); return false; } if (!XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckTreeInsertions(Attributes a, EditContext *edcontext) { if ((a.xml.haveselectxpath && !a.xml.havebuildxpath && !xmlDocGetRootElement(edcontext->xmldoc))) { Log(LOG_LEVEL_ERR, "Tree insertion into an empty file, using select_xpath, does not make sense"); return false; } else if ((!a.xml.haveselectxpath && a.xml.havebuildxpath)) { Log(LOG_LEVEL_ERR, "Tree insertion requires select_xpath to be specified, unless inserting into an empty file"); return false; } if (a.xml.haveselectxpath && !XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckAttributeDeletions(Attributes a) { if (!(a.xml.haveselectxpath)) { Log(LOG_LEVEL_ERR, "Attribute deletion requires select_xpath to be specified"); return false; } if (!XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckAttributeSet(Attributes a) { if (!(a.xml.haveselectxpath)) { Log(LOG_LEVEL_ERR, "Attribute insertion requires select_xpath to be specified"); return false; } if (!XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckTextDeletions(Attributes a) { if (!(a.xml.haveselectxpath)) { Log(LOG_LEVEL_ERR, "Tree insertion requires select_xpath to be specified"); return false; } if (!XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckTextSet(Attributes a) { if (!(a.xml.haveselectxpath)) { Log(LOG_LEVEL_ERR, "Tree insertion requires select_xpath to be specified"); return false; } if (!XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ static bool SanityCheckTextInsertions(Attributes a) { if (!(a.xml.haveselectxpath)) { Log(LOG_LEVEL_ERR, "Tree insertion requires select_xpath to be specified"); return false; } if (!XPathVerifyConvergence(a.xml.select_xpath)) { return false; } return true; } /***************************************************************************/ int XmlCompareToFile(xmlDocPtr doc, char *file, EditDefaults edits) /* returns true if XML on disk is identical to XML in memory */ { struct stat statbuf; xmlDocPtr cmpdoc = NULL; if (stat(file, &statbuf) == -1) { return false; } if (doc == NULL && statbuf.st_size == 0) { return true; } if (doc == NULL) { return false; } if (!LoadFileAsXmlDoc(&cmpdoc, file, edits)) { return false; } if (!XmlDocsEqualMem(cmpdoc, doc)) { xmlFreeDoc(cmpdoc); return false; } xmlFreeDoc(cmpdoc); return true; } /*********************************************************************/ static bool XmlDocsEqualMem(xmlDocPtr doc1, xmlDocPtr doc2) { xmlChar *mem1; xmlChar *mem2; int memsize1; int memsize2; int equal = true; if (!doc1 && !doc2) { return true; } if (!doc1 || !doc2) { return false; } xmlDocDumpMemory(doc1, &mem1, &memsize1); xmlDocDumpMemory(doc2, &mem2, &memsize2); if (!xmlStrEqual(mem1, mem2)) { equal = false; } xmlFree(mem1); xmlFree(mem2); return equal; } /***************************************************************************/ static bool XmlNodesCompare(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp) /* Does node1 contain all content(tag/attributes/text/nodes) found in node2? */ { int compare = true; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } if (!XmlNodesCompareTags(node1, node2)) { compare = false; } if (compare && !XmlNodesCompareAttributes(node1, node2)) { compare = false; } if (compare && !XmlNodesCompareText(node1, node2)) { compare = false; } if (compare && !XmlNodesCompareNodes(node1, node2, a, pp)) { compare = false; } return compare; } /*********************************************************************/ static bool XmlNodesCompareAttributes(const xmlNodePtr node1, const xmlNodePtr node2) /* Does node1 contain same attributes found in node2? */ { xmlAttrPtr attr1 = NULL; xmlAttrPtr attr2 = NULL; xmlChar *value = NULL; int count1, count2; int compare = true; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } if ((node1->properties) == NULL && (node2->properties) == NULL) { return true; } if ((node1->properties) == NULL || (node2->properties) == NULL) { return false; } count1 = XmlAttributeCount(node1); count2 = XmlAttributeCount(node2); if (count1 != count2) { return false; } //get attribute list from node1 and node2 attr1 = node1->properties; attr2 = node2->properties; //check that each attribute in node1 is in node2 while (attr1) { value = xmlNodeGetContent(attr1->children); if ((XmlVerifyAttributeInNode(attr1->name, value, node2)) == NULL) { xmlFree(value); compare = false; break; } xmlFree(value); attr1 = attr1->next; attr2 = attr2->next; } return compare; } /*********************************************************************/ static bool XmlNodesCompareNodes(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp) /* Does node1 contain same nodes found in node2? */ { int count1, count2, compare = true; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } count1 = xmlChildElementCount(node1); count2 = xmlChildElementCount(node2); if (count1 != count2) { return false; } //get node list from node1 and node2 xmlNodePtr child1 = xmlFirstElementChild(node1); while (child1) { if (!XmlVerifyNodeInNodeExact(child1, node2, a, pp)) { compare = false; break; } child1 = xmlNextElementSibling(node1); } xmlFreeNode(child1); return compare; } /*********************************************************************/ static bool XmlNodesCompareTags(const xmlNodePtr node1, const xmlNodePtr node2) /* Does node1 contain same tag found in node2? */ { int compare = true; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } if ((node1->name) == NULL && (node2->name) == NULL) { return true; } if ((node1->name) == NULL || (node2->name) == NULL) { return false; } //check tag in node1 is the same as tag in node2 if (!xmlStrEqual(node1->name, node2->name)) { compare = false; } return compare; } /*********************************************************************/ static bool XmlNodesCompareText(xmlNodePtr node1, xmlNodePtr node2) /* Does node1 contain same text found in node2? */ { xmlChar *text1 = NULL, *text2 = NULL; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } //get text from nodes text1 = xmlNodeGetContent(node1->children); text2 = xmlNodeGetContent(node2->children); if (!text1 && !text2) { return true; } if (!text2) { return false; } //check text in node1 is the same as text in node2 if (!xmlStrEqual(text1, text2)) { return false; } return true; } /*********************************************************************/ static bool XmlNodesSubset(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp) /* Does node1 contain matching subset of content(tag/attributes/text/nodes) found in node2? */ { int subset = true; if (!node1 && !node2) { return true; } if (!node2) { return false; } if (!XmlNodesCompareTags(node1, node2)) { subset = false; } if (subset && !XmlNodesSubsetOfAttributes(node1, node2)) { subset = false; } if (subset && !XmlNodesSubstringOfText(node1, node2)) { subset = false; } if (subset && !XmlNodesSubsetOfNodes(node1, node2, a, pp)) { subset = false; } return subset; } /*********************************************************************/ static bool XmlNodesSubsetOfAttributes(const xmlNodePtr node1, const xmlNodePtr node2) /* Does node1 contain matching subset of attributes found in node2? */ { xmlAttrPtr attr1 = NULL; int subset = true; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } if ((node1->properties) == NULL && (node2->properties) == NULL) { return true; } if ((node2->properties) == NULL) { return false; } //get attribute list from node1 attr1 = node1->properties; //check that each attribute in node1 is in node2 while (attr1) { xmlChar *value = xmlNodeGetContent(attr1->children); if ((XmlVerifyAttributeInNode(attr1->name, value, node2)) == NULL) { subset = false; xmlFree(value); break; } attr1 = attr1->next; xmlFree(value); } return subset; } /*********************************************************************/ static bool XmlNodesSubsetOfNodes(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp) /* Does node1 contain matching subset of nodes found in node2? */ { xmlNodePtr child1 = NULL; int subset = true; if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } //get node list from node1 and node2 child1 = xmlFirstElementChild(node1); while (child1) { if (!XmlVerifyNodeInNodeExact(child1, node2, a, pp)) { subset = false; break; } child1 = xmlNextElementSibling(node1); } return subset; } /*********************************************************************/ static bool XmlNodesSubstringOfText(const xmlNodePtr node1, const xmlNodePtr node2) /* Does node1 contain matching substring of text found in node2? */ { if (!node1 && !node2) { return true; } if (!node1 || !node2) { return false; } xmlChar *text1 = xmlNodeGetContent(node1->children); if (!text1) { return true; } xmlChar *text2 = xmlNodeGetContent(node2->children); if (!text2) { xmlFree(text1); return false; } if (!xmlStrstr(text2, text1)) { xmlFree(text1); xmlFree(text2); return false; } xmlFree(text1); xmlFree(text2); return true; } /*********************************************************************/ xmlAttrPtr XmlVerifyAttributeInNode(const xmlChar *name, xmlChar *value, const xmlNodePtr node) /* Does node contain an attribute with given name and value? Returns a pointer to attribute found in node or NULL */ { xmlAttrPtr attr2 = NULL; xmlChar *value2 = NULL; if ((node == NULL) || (name == NULL) || (node->properties == NULL)) { return NULL; } //get attribute with matching name from node, if it exists if ((attr2 = xmlHasProp(node, name)) == NULL) { return NULL; } //compare values value2 = xmlNodeGetContent(attr2->children); if (!xmlStrEqual(value, value2)) { xmlFree(value2); return NULL; } xmlFree(value2); return attr2; } /*********************************************************************/ bool XmlVerifyTextInNodeExact(const xmlChar *text, const xmlNodePtr node) /* Does node contain: text content exactly matching the givin string text? Returns a pointer to text content in node or NULL */ { if (node == NULL) { return false; } xmlChar *text2 = xmlNodeGetContent(node->children); if (!xmlStrEqual(text2, text)) { xmlFree(text2); return false; } xmlFree(text2); return true; } /*********************************************************************/ bool XmlVerifyTextInNodeSubstring(const xmlChar *text, xmlNodePtr node) /* Does node contain: text content, contains substring, matching the given string of text? Returns a pointer to text content in node or NULL */ { if (!node) { return false; } xmlChar *text2 = xmlNodeGetContent(node->children); if (!xmlStrstr(text2, text)) { xmlFree(text2); return false; } xmlFree(text2); return true; } /*********************************************************************/ static bool XmlVerifyNodeInNodeExact(const xmlNodePtr node1, const xmlNodePtr node2, Attributes a, const Promise *pp) /* Does node2 contain a node with content matching all content in node1? Returns a pointer to node found in node2 or NULL */ { xmlNodePtr comparenode = NULL; if ((node1 == NULL) || (node2 == NULL)) { return false; } if ((comparenode = xmlFirstElementChild(node2)) == NULL) { return false; } while (comparenode) { if (XmlNodesCompare(node1, comparenode, a, pp)) { return true; } comparenode = xmlNextElementSibling(comparenode); } return true; } /*********************************************************************/ xmlNodePtr XmlVerifyNodeInNodeSubset(xmlNodePtr node1, xmlNodePtr node2, Attributes a, const Promise *pp) /* Does node2 contain: node with subset of content matching all content in node1? Returns a pointer to node found in node2 or NULL */ { if ((node1 == NULL) || (node2 == NULL)) { return NULL; } xmlNodePtr comparenode = xmlFirstElementChild(node2); if (!comparenode) { return NULL; } while (comparenode) { if (XmlNodesSubset(node1, comparenode, a, pp)) { return comparenode; } comparenode = xmlNextElementSibling(comparenode); } xmlFree(comparenode); return NULL; } /*********************************************************************/ xmlNodePtr PredicateExtractNode(char predicate[CF_BUFSIZE]) { xmlNodePtr node = NULL; xmlChar *name = NULL; xmlChar *value = NULL; char rawname[CF_BUFSIZE] = { 0 }, rawvalue[CF_BUFSIZE] = { 0 }, *tok; char *running_start = xstrdup(predicate); char *running = running_start; //extract node name tok = strsep(&running, "| \"\'="); while (strcmp(tok, "") == 0) { tok = strsep(&running, "| \"\'="); } strcpy(rawname, tok); name = CharToXmlChar(rawname); //extract node value tok = strsep(&running, " \"\'="); while (strcmp(tok, "") == 0) { tok = strsep(&running, " \"\'="); } strcpy(rawvalue, tok); value = CharToXmlChar(rawvalue); //create a new node with name and value node = xmlNewNode(NULL, name); xmlNodeSetContent(node, value); free(running_start); return node; } /*********************************************************************/ static bool PredicateRemoveHead(char predicate[CF_BUFSIZE]) { char copypred[CF_BUFSIZE] = { 0 }, *tail = NULL; strcpy(copypred, predicate); memset(predicate, 0, sizeof(char)*CF_BUFSIZE); if (PredicateHasTail(copypred)) { tail = strchr(copypred+1, '|'); strcpy(predicate, tail); } return true; } /*********************************************************************/ xmlNodePtr XPathHeadExtractNode(EvalContext *ctx, char xpath[CF_BUFSIZE], Attributes a, const Promise *pp, PromiseResult *result) { xmlNodePtr node = NULL; char head[CF_BUFSIZE] = {0}, *tok = NULL; char *running_start = xstrdup(xpath); char *running = running_start; //extract head substring from xpath tok = strsep(&running, "/"); while (strcmp(tok, "") == 0) { tok = strsep(&running, "/"); } strcpy(head, tok); if ((node = XPathSegmentExtractNode(head)) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Could not extract node '%s'", head); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); } free(running_start); return node; } /*********************************************************************/ xmlNodePtr XPathTailExtractNode(EvalContext *ctx, char xpath[CF_BUFSIZE], Attributes a, const Promise *pp, PromiseResult *result) { xmlNodePtr node = NULL; char copyxpath[CF_BUFSIZE] = {0}, tail[CF_BUFSIZE] = {0}, *tok = NULL; strcpy(copyxpath, xpath); //extract tail substring from xpath tok = XPathGetTail(copyxpath); strcpy(tail, tok); if ((node = XPathSegmentExtractNode(tail)) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Could not extract node '%s'", tail); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); } return node; } /*********************************************************************/ xmlNodePtr XPathSegmentExtractNode(char segment[CF_BUFSIZE]) { xmlNodePtr node = NULL, prednode = NULL; xmlChar *name = NULL, *attrname = NULL, *attrvalue = NULL; char predicate[CF_BUFSIZE] = { 0 }, rawname[CF_BUFSIZE] = { 0 }, rawvalue[CF_BUFSIZE] = { 0 }, *tok; int hasname = false; char *running_start = xstrdup(segment); char *running = running_start; //extract name and predicate substrings from segment if (XPathHeadContainsNode(segment)) { //extract node name tok = strsep(&running, " []"); while (strcmp(tok, "") == 0) { tok = strsep(&running, " []"); } strcpy(rawname, tok); name = CharToXmlChar(rawname); //create a new node with name node = xmlNewNode(NULL, name); hasname = true; } //extract attributes and nodes from predicate if (hasname && XPathHeadContainsPredicate(segment)) { //extract predicate tok = strsep(&running, "[]"); while (strcmp(tok, "") == 0) { tok = strsep(&running, "[]"); } strcpy(predicate, tok); while (strlen(predicate) > 0) { if (PredicateHeadContainsNode(predicate)) { //create a new node within node prednode = PredicateExtractNode(predicate); xmlAddChild(node, prednode); } else if (PredicateHeadContainsAttribute(predicate)) { char *running_start2 = xstrdup(predicate); char *running2 = running_start2; //extract attribute name tok = strsep(&running2, "| @\"\'="); while (strcmp(tok, "") == 0) { tok = strsep(&running2, "| @\"\'="); } strcpy(rawname, tok); attrname = CharToXmlChar(rawname); //extract attribute value tok = strsep(&running2, "| @\"\'="); while (strcmp(tok, "") == 0) { tok = strsep(&running2, "| @\"\'="); } strcpy(rawvalue, tok); attrvalue = CharToXmlChar(rawvalue); //create a new attribute within node xmlNewProp(node, attrname, attrvalue); free(running_start2); } if (PredicateHasTail(predicate)) { PredicateRemoveHead(predicate); } else { memset(predicate, 0, sizeof(char)*CF_BUFSIZE); } } } free(running_start); return node; } /*********************************************************************/ char* XPathGetTail(char xpath[CF_BUFSIZE]) { char tmpstr[CF_BUFSIZE] = {0}, *tok = NULL; char *running_start = xstrdup(xpath); char *running = running_start; memset(xpath, 0, sizeof(char)*CF_BUFSIZE); if (XPathHasTail(running)) { //extract and discard xpath head tok = strsep(&running, "/"); while (strcmp(tok, "") == 0) { tok = strsep(&running, "/"); } //extract xpath tail while ((tok = strsep(&running, "/")) != NULL) { while (strcmp(tok, "") == 0) { tok = strsep(&running, "/"); } if (tok) { strcpy(tmpstr, tok); } } strcpy(xpath, tmpstr); } free(running_start); return xpath; } /*********************************************************************/ static bool XPathRemoveHead(char xpath[CF_BUFSIZE]) { char copyxpath[CF_BUFSIZE] = { 0 }, *tail = NULL; strcpy(copyxpath, xpath); memset(xpath, 0, sizeof(char)*CF_BUFSIZE); if (XPathHasTail(copyxpath)) { tail = strchr(copyxpath+1, '/'); strcpy(xpath, tail); } return true; } /*********************************************************************/ static bool XPathRemoveTail(char xpath[CF_BUFSIZE]) { char copyxpath[CF_BUFSIZE] = { 0 }, *tail = NULL; int len = 0; strcpy(copyxpath, xpath); memset(xpath, 0, sizeof(char)*CF_BUFSIZE); if (XPathHasTail(copyxpath)) { tail = strrchr(copyxpath, '/'); len = tail-copyxpath; copyxpath[len] = '\0'; strcpy(xpath, copyxpath); } return true; } /*********************************************************************/ static bool PredicateHasTail(char *predicate) { const char *regexp = "^\\s*\\[?\\s*@?\\s*(\\w|-|\\.)+\\s*=\\s*(\"|\')?(\\w|-|\\.)+(\"|\')?\\s*\\|"; return (ContainsRegex(predicate, regexp)); } /*********************************************************************/ static bool PredicateHeadContainsAttribute(char *predicate) { const char *regexp = "^\\s*\\[?\\|?(\\s*@\\s*(\\w|-|\\.)+\\s*=\\s*(\"|\')?(\\w|-|\\.)+(\"|\')?)(\\s*(\\||\\]))?"; // i.e. @name='value' or @name = value or @name ="value" return (ContainsRegex(predicate, regexp)); } /*********************************************************************/ static bool PredicateHeadContainsNode(char *predicate) { const char *regexp = "^\\s*\\[?\\|?(\\s*(\\w|-|\\.)+\\s*=\\s*(\"|\')?(\\w|-|\\.)+(\"|\')?)(\\s*(\\||\\]))?"; // i.e. name='value' or name = value or name ="value" return (ContainsRegex(predicate, regexp)); } /*********************************************************************/ static bool XPathHasTail(char *head) { const char *regexp = "^\\s*\\/?\\s*(\\w|-|\\.)+(\\s*::\\s*(\\w|-|\\.)+\\s*)*\\s*(\\[[^\\[\\]\\/]*\\])?\\s*\\/"; return (ContainsRegex(head, regexp)); } /*********************************************************************/ static bool XPathHeadContainsNode(char *head) { const char *regexp = "^(\\/)?(\\w|-|\\.)+((\\s*::\\s*)?(\\w|-|\\.)+)*"; return (ContainsRegex(head, regexp)); } /*********************************************************************/ static bool XPathHeadContainsPredicate(char *head) { const char *regexp = "^\\s*\\/?\\s*(\\w|-|\\.)+(\\s*::\\s*(\\w|-|\\.)+)*\\s*\\" // name // [ name='value' | @name = "value" | name = value] "[\\s*@?\\s*(\\w|-|\\.)+\\s*=\\s*(\"|\')?(\\w|-|\\.)+(\"|\')?\\s*(\\s*\\|\\s*)?(\\s*@?\\s*(\\w|-|\\.)+\\s*=\\s*(\"|\')?(\\w|-|\\.)+(\"|\')?\\s*)*\\]"; return (ContainsRegex(head, regexp)); } /*********************************************************************/ static bool XPathVerifyBuildSyntax(EvalContext *ctx, const char* xpath, Attributes a, const Promise *pp, PromiseResult *result) /*verify that XPath does not specify position wrt sibling-axis (such as):[#] [last()] [position()] following-sibling:: preceding-sibling:: */ { char regexp[CF_BUFSIZE] = {'\0'}; //check for convergence if (!XPathVerifyConvergence(xpath)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Promiser expression (%s) is not convergent", xpath); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } // /name[ name = value | @name='value'| . . . | @name = "value" ]/. . . strcpy (regexp, "^(\\/(( |\\t)*(\\w|-|\\.)+( |\\t)*)" "(\\[( |\\t)*@?(\\w|-|\\.)+( |\\t)*=( |\\t)*(\'|\")?(\\w|-|\\.)+(\'|\")?( |\\t)*" "(\\|( |\\t)*@?(\\w|-|\\.)+( |\\t)*=( |\\t)*(\'|\")?(\\w|-|\\.)+(\'|\")?( |\\t)*)*\\])?)*$"); if (!ContainsRegex(xpath, regexp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Promiser expression '%s' contains syntax that is not supported for xpath_build. " "Please refer to users manual for supported syntax specifications.", xpath); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } return true; } /*********************************************************************/ static bool XPathVerifyConvergence(const char* xpath) /*verify that XPath does not specify position wrt sibling-axis (such as):[#] [last()] [position()] following-sibling:: preceding-sibling:: */ { char regexp[CF_BUFSIZE] = {'\0'}; //check in predicate strcpy (regexp, "\\[\\s*([^\\[\\]]*\\s*(\\||(or)|(and)))?\\s*" // [ (stuff) (|/or/and) // position() (=/!=//>=) "((position)\\s*\\(\\s*\\)\\s*((=)|(!=)|(<)|(<=)|(>)|(>=))\\s*)?\\s*" // (number) | (number) (+/-/*/div/mod) (number) | last() | last() (+/-/*/div/mod) (number) "(((\\d+)\\s*|((last)\\s*\\(\\s*\\)\\s*))(((\\+)|(-)|(\\*)|(div)|(mod))\\s*(\\d+)\\s*)*)\\s*" // (|/or/and) (stuff) ] "((\\||(or)|(and))[^\\[\\]]*)?\\]" // following:: preceding:: following-sibling:: preceding-sibling:: "|((following)|(preceding))(-sibling)?\\s*(::)"); if (ContainsRegex(xpath, regexp)) { return false; } return true; } /*********************************************************************/ xmlChar *CharToXmlChar(char c[CF_BUFSIZE]) { return BAD_CAST c; } /*********************************************************************/ static bool ContainsRegex(const char* rawstring, const char* regex) { int ovector[OVECCOUNT], rc; const char *errorstr; int erroffset; pcre *rx = pcre_compile(regex, 0, &errorstr, &erroffset, NULL); if ((rc = pcre_exec(rx, NULL, rawstring, strlen(rawstring), 0, 0, ovector, OVECCOUNT)) >= 0) { pcre_free(rx); return true; } pcre_free(rx); return false; } /*********************************************************************/ static int XmlAttributeCount(const xmlNodePtr node) { if (!node) { return 0; } xmlAttrPtr attr = node->properties; int count = 0; while (attr) { count++; attr = attr->next; } return count; } /*********************************************************************/ #endif cfengine-3.6.2/cf-agent/verify_services.h0000644000175100017510000000221612316547775020102 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_SERVICES_H #define CFENGINE_VERIFY_SERVICES_H #include PromiseResult VerifyServicesPromise(EvalContext *ctx, const Promise *pp); #endif cfengine-3.6.2/cf-agent/verify_exec.h0000644000175100017510000000220212316547775017176 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_EXEC_H #define CFENGINE_VERIFY_EXEC_H #include PromiseResult VerifyExecPromise(EvalContext *ctx, const Promise *pp); #endif cfengine-3.6.2/cf-agent/verify_storage.h0000644000175100017510000000250712316547775017726 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_STORAGE_H #define CFENGINE_VERIFY_STORAGE_H #include extern bool CF_MOUNTALL; PromiseResult FindAndVerifyStoragePromises(EvalContext *ctx, const Promise *pp); PromiseResult VerifyStoragePromise(EvalContext *ctx, char *path, const Promise *pp); Seq *GetGlobalMountedFSList(void); void DeleteStorageContext(void); #endif cfengine-3.6.2/cf-agent/verify_files.c0000664000175100017510000006353212411001073017332 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void LoadSetuid(void); static void SaveSetuid(void); static PromiseResult FindFilePromiserObjects(EvalContext *ctx, const Promise *pp); static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp); /*****************************************************************************/ static int FileSanityChecks(char *path, Attributes a, const Promise *pp) { if ((a.havelink) && (a.havecopy)) { Log(LOG_LEVEL_ERR, "Promise constraint conflicts - '%s' file cannot both be a copy of and a link to the source", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } /* We can't do this verification during parsing as we did not yet read the * body, so we can't distinguish between link and copy source. In * post-verification all bodies are already expanded, so we don't have the * information either */ if ((a.havelink) && (!a.link.source)) { Log(LOG_LEVEL_ERR, "Promise to establish a link at '%s' has no source", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.haveeditline) && (a.haveeditxml)) { Log(LOG_LEVEL_ERR, "Promise constraint conflicts - '%s' editing file as both line and xml makes no sense", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.havedepthsearch) && (a.haveedit)) { Log(LOG_LEVEL_ERR, "Recursive depth_searches are not compatible with general file editing"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.havedelete) && ((a.create) || (a.havecopy) || (a.haveedit) || (a.haverename))) { Log(LOG_LEVEL_ERR, "Promise constraint conflicts - '%s' cannot be deleted and exist at the same time", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.haverename) && ((a.create) || (a.havecopy) || (a.haveedit))) { Log(LOG_LEVEL_ERR, "Promise constraint conflicts - '%s' cannot be renamed/moved and exist there at the same time", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.havedelete) && (a.havedepthsearch) && (!a.haveselect)) { Log(LOG_LEVEL_ERR, "Dangerous or ambiguous promise - '%s' specifies recursive deletion but has no file selection criteria", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.haveselect) && (!a.select.result)) { Log(LOG_LEVEL_ERR, "File select constraint body promised no result (check body definition)"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.havedelete) && (a.haverename)) { Log(LOG_LEVEL_ERR, "File '%s' cannot promise both deletion and renaming", path); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.havecopy) && (a.havedepthsearch) && (a.havedelete)) { Log(LOG_LEVEL_WARNING, "depth_search of '%s' applies to both delete and copy, but these refer to different searches (source/destination)", pp->promiser); PromiseRef(LOG_LEVEL_INFO, pp); } if ((a.transaction.background) && (a.transaction.audit)) { Log(LOG_LEVEL_ERR, "Auditing cannot be performed on backgrounded promises (this might change)."); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if (((a.havecopy) || (a.havelink)) && (a.transformer)) { Log(LOG_LEVEL_ERR, "File object(s) '%s' cannot both be a copy of source and transformed simultaneously", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.haveselect) && (a.select.result == NULL)) { Log(LOG_LEVEL_ERR, "Missing file_result attribute in file_select body"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((a.havedepthsearch) && (a.change.report_diffs)) { Log(LOG_LEVEL_ERR, "Difference reporting is not allowed during a depth_search"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } return true; } static bool AttrHasNoAction(Attributes attr) { /* Hopefully this includes all "actions" for a files promise. See struct * Attributes for reference. */ if (!(attr.transformer || attr.haverename || attr.havedelete || attr.havecopy || attr.create || attr.touch || attr.havelink || attr.haveperms || attr.havechange || attr.acl.acl_entries || attr.haveedit || attr.haveeditline || attr.haveeditxml)) { return true; } else { return false; } } /* * Expands source in-place. */ static char *ExpandThisPromiserScalar(EvalContext *ctx, const char *ns, const char *scope, const char *source) { if (!source) { return NULL; } Buffer *expanded = BufferNew(); ExpandScalar(ctx, ns, scope, source, expanded); char *result = strdup(BufferData(expanded)); BufferDestroy(expanded); return result; } /* * Overwrite non-specific attributes with expanded this.promiser. */ Attributes GetExpandedAttributes(EvalContext *ctx, const Promise *pp, const Attributes *attr) { const char *namespace = PromiseGetBundle(pp)->ns; const char *scope = PromiseGetBundle(pp)->name; Attributes a = *attr; // shallow copy a.classes.change = ExpandList(ctx, namespace, scope, attr->classes.change, true); a.classes.failure = ExpandList(ctx, namespace, scope, attr->classes.failure, true); a.classes.denied = ExpandList(ctx, namespace, scope, attr->classes.denied, true); a.classes.timeout = ExpandList(ctx, namespace, scope, attr->classes.timeout, true); a.classes.kept = ExpandList(ctx, namespace, scope, attr->classes.kept, true); a.classes.del_change = ExpandList(ctx, namespace, scope, attr->classes.del_change, true); a.classes.del_kept = ExpandList(ctx, namespace, scope, attr->classes.del_kept, true); a.classes.del_notkept = ExpandList(ctx, namespace, scope, attr->classes.del_notkept, true); a.transaction.log_string = ExpandThisPromiserScalar(ctx, namespace, scope, attr->transaction.log_string); a.transaction.log_kept = ExpandThisPromiserScalar(ctx, namespace, scope, attr->transaction.log_kept); a.transaction.log_repaired = ExpandThisPromiserScalar(ctx, namespace, scope, attr->transaction.log_repaired); a.transaction.log_failed = ExpandThisPromiserScalar(ctx, namespace, scope, attr->transaction.log_failed); a.transaction.measure_id = ExpandThisPromiserScalar(ctx, namespace, scope, attr->transaction.measure_id); // a.transformer = ExpandThisPromiserScalar(ctx, namespace, scope, attr->transformer); a.edit_template = ExpandThisPromiserScalar(ctx, namespace, scope, attr->edit_template); return a; } void ClearExpandedAttributes(Attributes *a) { free(a->transaction.log_string); a->transaction.log_string = NULL; free(a->transaction.log_kept); a->transaction.log_kept = NULL; free(a->transaction.log_repaired); a->transaction.log_repaired = NULL; free(a->transaction.log_failed); a->transaction.log_failed = NULL; free(a->transaction.measure_id); a->transaction.measure_id = NULL; free(a->edit_template); a->edit_template = NULL; ClearFilesAttributes(a); } static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp) { struct stat osb, oslb, dsb; CfLock thislock; int exists; Attributes attr = GetFilesAttributes(ctx, pp); if (!FileSanityChecks(path, attr, pp)) { ClearFilesAttributes(&attr); return PROMISE_RESULT_NOOP; } thislock = AcquireLock(ctx, path, VUQNAME, CFSTARTTIME, attr.transaction, pp, false); if (thislock.lock == NULL) { ClearFilesAttributes(&attr); return PROMISE_RESULT_SKIPPED; } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", path, CF_DATA_TYPE_STRING, "source=promise"); Attributes a = GetExpandedAttributes(ctx, pp, &attr); LoadSetuid(); PromiseResult result = PROMISE_RESULT_NOOP; if (lstat(path, &oslb) == -1) /* Careful if the object is a link */ { if ((a.create) || (a.touch)) { if (!CfCreateFile(ctx, path, pp, a, &result)) { goto exit; } else { exists = (lstat(path, &oslb) != -1); } } exists = false; } else { if ((a.create) || (a.touch)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' exists as promised", path); } exists = true; } if ((a.havedelete) && (!exists)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "File '%s' does not exist as promised", path); goto exit; } if (!a.havedepthsearch) /* if the search is trivial, make sure that we are in the parent dir of the leaf */ { char basedir[CF_BUFSIZE]; Log(LOG_LEVEL_DEBUG, "Direct file reference '%s', no search implied", path); snprintf(basedir, sizeof(basedir), "%s", path); if (strcmp(ReadLastNode(basedir), ".") == 0) { // Handle /. notation for deletion of directories ChopLastNode(basedir); ChopLastNode(path); } ChopLastNode(basedir); if (safe_chdir(basedir)) { Log(LOG_LEVEL_ERR, "Failed to chdir into '%s'. (chdir: '%s')", basedir, GetErrorStr()); } } /* If file or directory exists but it is not selected by body file_select * (if we have one) then just exit. But continue if it's a directory and * depth_search is on, so that we can file_select into it. */ if (exists && (a.haveselect && !SelectLeaf(ctx, path, &oslb, a.select)) && !(a.havedepthsearch && S_ISDIR(oslb.st_mode))) { goto exit; } if (stat(path, &osb) == -1) { if ((a.create) || (a.touch)) { if (!CfCreateFile(ctx, path, pp, a, &result)) { goto exit; } else { exists = true; } } else { exists = false; } } else { if (!S_ISDIR(osb.st_mode)) { if (a.havedepthsearch) { Log(LOG_LEVEL_WARNING, "depth_search (recursion) is promised for a base object '%s' that is not a directory", path); goto exit; } } exists = true; } if (a.link.link_children) { if (stat(a.link.source, &dsb) != -1) { if (!S_ISDIR(dsb.st_mode)) { Log(LOG_LEVEL_ERR, "Cannot promise to link the children of '%s' as it is not a directory!", a.link.source); goto exit; } } } /* Phase 1 - */ if (exists && ((a.havedelete) || (a.haverename) || (a.haveperms) || (a.havechange) || (a.transformer))) { lstat(path, &oslb); /* if doesn't exist have to stat again anyway */ DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result); /* normally searches do not include the base directory */ if (a.recursion.include_basedir) { int save_search = a.havedepthsearch; /* Handle this node specially */ a.havedepthsearch = false; DepthSearch(ctx, path, &oslb, 0, a, pp, oslb.st_dev, &result); a.havedepthsearch = save_search; } else { /* unless child nodes were repaired, set a promise kept class */ if (!IsDefinedClass(ctx, "repaired")) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Basedir '%s' not promising anything", path); } } } /* Phase 2a - copying is potentially threadable if no followup actions */ if (a.havecopy) { result = PromiseResultUpdate(result, ScheduleCopyOperation(ctx, path, a, pp)); } /* Phase 2b link after copy in case need file first */ if ((a.havelink) && (a.link.link_children)) { result = PromiseResultUpdate(result, ScheduleLinkChildrenOperation(ctx, path, a.link.source, 1, a, pp)); } else if (a.havelink) { result = PromiseResultUpdate(result, ScheduleLinkOperation(ctx, path, a.link.source, a, pp)); } /* Phase 3 - content editing */ if (a.haveedit) { if (exists) { result = PromiseResultUpdate(result, ScheduleEditOperation(ctx, path, a, pp)); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to edit '%s', but file does not exist", path); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } // Once more in case a file has been created as a result of editing or copying exists = (stat(path, &osb) != -1); if (exists && (S_ISREG(osb.st_mode)) && (!a.haveselect || SelectLeaf(ctx, path, &osb, a.select))) { VerifyFileLeaf(ctx, path, &osb, a, pp, &result); } if (!exists && a.havechange) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised to monitor '%s' for changes, but file does not exist", path); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } exit: if (AttrHasNoAction(a)) { Log(LOG_LEVEL_INFO, "No action was requested for file '%s'. Maybe a typo in the policy?", path); } SaveSetuid(); YieldCurrentLock(thislock); ClearExpandedAttributes(&a); EvalContextVariableRemoveSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser"); return result; } /*****************************************************************************/ static PromiseResult RenderTemplateCFEngine(EvalContext *ctx, const Promise *pp, const Rlist *bundle_args, Attributes a, EditContext *edcontext) { PromiseResult result = PROMISE_RESULT_NOOP; Policy *tmp_policy = PolicyNew(); Bundle *bp = NULL; if ((bp = MakeTemporaryBundleFromTemplate(ctx, tmp_policy, a, pp, &result))) { BannerSubBundle(bp, bundle_args); a.haveeditline = true; EvalContextStackPushBundleFrame(ctx, bp, bundle_args, a.edits.inherit); BundleResolve(ctx, bp); ScheduleEditLineOperations(ctx, bp, a, pp, edcontext); EvalContextStackPopFrame(ctx); if (edcontext->num_edits == 0) { edcontext->num_edits++; } } PolicyDestroy(tmp_policy); return result; } static bool SaveBufferCallback(const char *dest_filename, void *param, NewLineMode new_line_mode) { FILE *fp = safe_fopen(dest_filename, (new_line_mode == NewLineMode_Native) ? "wt" : "w"); if (!fp) { Log(LOG_LEVEL_ERR, "Unable to open destination file '%s' for writing. (fopen: %s)", dest_filename, GetErrorStr()); return false; } Buffer *output_buffer = param; size_t bytes_written = fwrite(BufferData(output_buffer), sizeof(char), BufferSize(output_buffer), fp); if (bytes_written != BufferSize(output_buffer)) { Log(LOG_LEVEL_ERR, "Error writing to output file '%s' when writing. %zd bytes written but expected %d. (fclose: %s)", dest_filename, bytes_written, BufferSize(output_buffer), GetErrorStr()); fclose(fp); return false; } if (fclose(fp) == -1) { Log(LOG_LEVEL_ERR, "Unable to close file '%s' after writing. (fclose: %s)", dest_filename, GetErrorStr()); return false; } return true; } static PromiseResult RenderTemplateMustache(EvalContext *ctx, const Promise *pp, Attributes a, EditContext *edcontext) { PromiseResult result = PROMISE_RESULT_NOOP; if (!FileCanOpen(a.edit_template, "r")) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Template file '%s' could not be opened for reading", a.edit_template); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } unsigned char existing_output_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; if (access(pp->promiser, R_OK) == 0) { HashFile(pp->promiser, existing_output_digest, CF_DEFAULT_DIGEST); } int template_fd = safe_open(a.edit_template, O_RDONLY | O_TEXT); Writer *template_writer = NULL; if (template_fd >= 0) { template_writer = FileReadFromFd(template_fd, SIZE_MAX, NULL); close(template_fd); } if (!template_writer) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Could not read template file '%s'", a.edit_template); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } JsonElement *default_template_data = NULL; if (!a.template_data) { a.template_data = default_template_data = DefaultTemplateData(ctx); } Buffer *output_buffer = BufferNew(); if (MustacheRender(output_buffer, StringWriterData(template_writer), a.template_data)) { unsigned char rendered_output_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; HashString(BufferData(output_buffer), BufferSize(output_buffer), rendered_output_digest, CF_DEFAULT_DIGEST); if (!HashesMatch(existing_output_digest, rendered_output_digest, CF_DEFAULT_DIGEST)) { if (SaveAsFile(SaveBufferCallback, output_buffer, edcontext->filename, a, edcontext->new_line_mode)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Updated rendering of '%s' from template mustache template '%s'", pp->promiser, a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Updated rendering of '%s' from template mustache template '%s'", pp->promiser, a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } JsonDestroy(default_template_data); WriterClose(template_writer); BufferDestroy(output_buffer); return result; } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error rendering mustache template '%s'", a.edit_template); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); JsonDestroy(default_template_data); WriterClose(template_writer); BufferDestroy(output_buffer); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } PromiseResult ScheduleEditOperation(EvalContext *ctx, char *filename, Attributes a, const Promise *pp) { void *vp; FnCall *fp; Rlist *args = NULL; char edit_bundle_name[CF_BUFSIZE], lockname[CF_BUFSIZE]; CfLock thislock; snprintf(lockname, CF_BUFSIZE - 1, "fileedit-%s", filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } EditContext *edcontext = NewEditContext(filename, a); PromiseResult result = PROMISE_RESULT_NOOP; if (edcontext == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "File '%s' was marked for editing but could not be opened", filename); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); goto exit; } const Policy *policy = PolicyFromPromise(pp); if (a.haveeditline) { if ((vp = PromiseGetConstraintAsRval(pp, "edit_line", RVAL_TYPE_FNCALL))) { fp = (FnCall *) vp; strcpy(edit_bundle_name, fp->name); args = fp->args; } else if ((vp = PromiseGetConstraintAsRval(pp, "edit_line", RVAL_TYPE_SCALAR))) { strcpy(edit_bundle_name, (char *) vp); args = NULL; } else { goto exit; } Log(LOG_LEVEL_VERBOSE, "Handling file edits in edit_line bundle '%s'", edit_bundle_name); const Bundle *bp = EvalContextResolveBundleExpression(ctx, policy, edit_bundle_name, "edit_line"); if (bp) { BannerSubBundle(bp, args); EvalContextStackPushBundleFrame(ctx, bp, args, a.edits.inherit); BundleResolve(ctx, bp); ScheduleEditLineOperations(ctx, bp, a, pp, edcontext); EvalContextStackPopFrame(ctx); } else { Log(LOG_LEVEL_ERR, "Did not find bundle '%s' for edit operation", edit_bundle_name); } } if (a.haveeditxml) { if ((vp = PromiseGetConstraintAsRval(pp, "edit_xml", RVAL_TYPE_FNCALL))) { fp = (FnCall *) vp; strcpy(edit_bundle_name, fp->name); args = fp->args; } else if ((vp = PromiseGetConstraintAsRval(pp, "edit_xml", RVAL_TYPE_SCALAR))) { strcpy(edit_bundle_name, (char *) vp); args = NULL; } else { goto exit; } Log(LOG_LEVEL_VERBOSE, "Handling file edits in edit_xml bundle '%s'", edit_bundle_name); const Bundle *bp = EvalContextResolveBundleExpression(ctx, policy, edit_bundle_name, "edit_xml"); if (bp) { BannerSubBundle(bp, args); EvalContextStackPushBundleFrame(ctx, bp, args, a.edits.inherit); BundleResolve(ctx, bp); ScheduleEditXmlOperations(ctx, bp, a, pp, edcontext); EvalContextStackPopFrame(ctx); } } if (a.edit_template) { Log(LOG_LEVEL_VERBOSE, "Rendering '%s' using template '%s' with method '%s'", filename, a.edit_template, a.template_method ? a.template_method : "cfengine"); if (!a.template_method || strcmp("cfengine", a.template_method) == 0) { PromiseResult render_result = RenderTemplateCFEngine(ctx, pp, args, a, edcontext); result = PromiseResultUpdate(result, render_result); } else if (strcmp("mustache", a.template_method) == 0) { PromiseResult render_result = RenderTemplateMustache(ctx, pp, a, edcontext); result = PromiseResultUpdate(result, render_result); } } exit: FinishEditContext(ctx, edcontext, a, pp, &result); YieldCurrentLock(thislock); return result; } /*****************************************************************************/ PromiseResult FindAndVerifyFilesPromises(EvalContext *ctx, const Promise *pp) { PromiseBanner(pp); return FindFilePromiserObjects(ctx, pp); } /*****************************************************************************/ static PromiseResult FindFilePromiserObjects(EvalContext *ctx, const Promise *pp) { char *val = PromiseGetConstraintAsRval(pp, "pathtype", RVAL_TYPE_SCALAR); int literal = (PromiseGetConstraintAsBoolean(ctx, "copy_from", pp)) || ((val != NULL) && (strcmp(val, "literal") == 0)); /* Check if we are searching over a regular expression */ PromiseResult result = PROMISE_RESULT_SKIPPED; if (literal) { // Prime the promiser temporarily, may override later result = PromiseResultUpdate(result, VerifyFilePromise(ctx, pp->promiser, pp)); } else // Default is to expand regex paths { result = PromiseResultUpdate(result, LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyFilePromise)); } return result; } static void LoadSetuid(void) { char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "%s/cfagent.%s.log", GetLogDir(), VSYSNAME.nodename); MapName(filename); VSETUIDLIST = RawLoadItemList(filename); } /*********************************************************************/ static void SaveSetuid(void) { char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "%s/cfagent.%s.log", GetLogDir(), VSYSNAME.nodename); MapName(filename); PurgeItemList(&VSETUIDLIST, "SETUID/SETGID"); Item *current = RawLoadItemList(filename); if (!ListsCompare(VSETUIDLIST, current)) { RawSaveItemList(VSETUIDLIST, filename, NewLineMode_Unix); } DeleteItemList(VSETUIDLIST); VSETUIDLIST = NULL; } cfengine-3.6.2/cf-agent/verify_users.h0000644000175100017510000000250312352022221017365 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_USERS_H #define CFENGINE_VERIFY_USERS_H #include PromiseResult VerifyUsersPromise(EvalContext *ctx, const Promise *pp); void VerifyOneUsersPromise (const char *puser, User u, PromiseResult *result, enum cfopaction action, EvalContext *ctx, const Attributes *a, const Promise *pp); #endif cfengine-3.6.2/cf-agent/files_editline.c0000664000175100017510000021426112411001073017620 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CF_MAX_REPLACE 20 /*****************************************************************************/ enum editlinetypesequence { elp_vars, elp_classes, elp_delete, elp_columns, elp_insert, elp_replace, elp_reports, elp_none }; static const char *const EDITLINETYPESEQUENCE[] = { "vars", "classes", "delete_lines", "field_edits", "insert_lines", "replace_patterns", "reports", NULL }; static PromiseResult KeepEditLinePromise(EvalContext *ctx, const Promise *pp, void *param); static PromiseResult VerifyLineDeletions(EvalContext *ctx, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyColumnEdits(EvalContext *ctx, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyPatterns(EvalContext *ctx, const Promise *pp, EditContext *edcontext); static PromiseResult VerifyLineInsertions(EvalContext *ctx, const Promise *pp, EditContext *edcontext); static int InsertMultipleLinesToRegion(EvalContext *ctx, Item **start, Item *begin_ptr, Item *end_ptr, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int InsertMultipleLinesAtLocation(EvalContext *ctx, Item **start, Item *begin_ptr, Item *end_ptr, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int DeletePromisedLinesMatching(EvalContext *ctx, Item **start, Item *begin, Item *end, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int InsertLineAtLocation(EvalContext *ctx, char *newline, Item **start, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int InsertCompoundLineAtLocation(EvalContext *ctx, char *newline, Item **start, Item *begin_ptr, Item *end_ptr, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int ReplacePatterns(EvalContext *ctx, Item *start, Item *end, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int EditColumns(EvalContext *ctx, Item *file_start, Item *file_end, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int EditLineByColumn(EvalContext *ctx, Rlist **columns, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int DoEditColumn(Rlist **columns, Attributes a, EditContext *edcontext); static int SanityCheckInsertions(Attributes a); static int SanityCheckDeletions(Attributes a, const Promise *pp); static int SelectLine(EvalContext *ctx, const char *line, Attributes a); static int NotAnchored(char *s); static int SelectRegion(EvalContext *ctx, Item *start, Item **begin_ptr, Item **end_ptr, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); static int MultiLineString(char *s); static int InsertFileAtLocation(EvalContext *ctx, Item **start, Item *begin_ptr, Item *end_ptr, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result); /*****************************************************************************/ /* Level */ /*****************************************************************************/ int ScheduleEditLineOperations(EvalContext *ctx, const Bundle *bp, Attributes a, const Promise *parentp, EditContext *edcontext) { enum editlinetypesequence type; char lockname[CF_BUFSIZE]; CfLock thislock; int pass; assert(strcmp(bp->type, "edit_line") == 0); snprintf(lockname, CF_BUFSIZE - 1, "masterfilelock-%s", edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, parentp, true); if (thislock.lock == NULL) { return false; } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_EDIT, "filename", edcontext->filename, CF_DATA_TYPE_STRING, "source=promise"); for (pass = 1; pass < CF_DONEPASSES; pass++) { for (type = 0; EDITLINETYPESEQUENCE[type] != NULL; type++) { const PromiseType *sp = BundleGetPromiseType(bp, EDITLINETYPESEQUENCE[type]); if (!sp) { continue; } BannerSubPromiseType(ctx, bp->name, sp->name); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepEditLinePromise, edcontext); if (Abort(ctx)) { YieldCurrentLock(thislock); EvalContextStackPopFrame(ctx); return false; } } EvalContextStackPopFrame(ctx); } } YieldCurrentLock(thislock); return true; } /*****************************************************************************/ Bundle *MakeTemporaryBundleFromTemplate(EvalContext *ctx, Policy *policy, Attributes a, const Promise *pp, PromiseResult *result) { FILE *fp = NULL; if ((fp = safe_fopen(a.edit_template, "rt" )) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Unable to open template file '%s' to make '%s'", a.edit_template, pp->promiser); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return NULL; } Bundle *bp = NULL; { char bundlename[CF_MAXVARSIZE]; snprintf(bundlename, CF_MAXVARSIZE, "temp_cf_bundle_%s", CanonifyName(a.edit_template)); bp = PolicyAppendBundle(policy, "default", bundlename, "edit_line", NULL, NULL); } assert(bp); { PromiseType *tp = BundleAppendPromiseType(bp, "insert_lines"); Promise *np = NULL; Item *lines = NULL; Item *stack = NULL; char context[CF_BUFSIZE] = "any"; int lineno = 0; size_t level = 0; size_t buffer_size = CF_BUFSIZE; char *buffer = xmalloc(buffer_size); for (;;) { if (getline(&buffer, &buffer_size, fp) == -1) { if (!feof(fp)) { Log(LOG_LEVEL_ERR, "While constructing template for '%s', error reading. (getline %s)", pp->promiser, GetErrorStr()); break; } else /* feof */ { break; } } lineno++; // Check closing syntax // Get Action operator if (strncmp(buffer, "[%CFEngine", strlen("[%CFEngine")) == 0) { char op[CF_BUFSIZE], brack[CF_SMALLBUF]; sscanf(buffer+strlen("[%CFEngine"), "%1024s %s", op, brack); if (strcmp(brack, "%]") != 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Template file '%s' syntax error, missing close \"%%]\" at line %d", a.edit_template, lineno); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return NULL; } if (strcmp(op, "BEGIN") == 0) { PrependItem(&stack, context, NULL); if (++level > 1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Template file '%s' contains nested blocks which are not allowed, near line %d", a.edit_template, lineno); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return NULL; } continue; } if (strcmp(op, "END") == 0) { level--; if (stack != NULL) { strcpy(context, stack->name); DeleteItem(&stack, stack); } } if (strcmp(op + strlen(op)-2, "::") == 0) { *(op + strlen(op)-2) = '\0'; strcpy(context, op); continue; } size_t size = 0; for (const Item *ip = lines; ip != NULL; ip = ip->next) { size += strlen(ip->name); } char *promiser = NULL; char *sp = promiser = xcalloc(1, size+1); for (const Item *ip = lines; ip != NULL; ip = ip->next) { const int len = strlen(ip->name); memcpy(sp, ip->name, len); sp += len; } *(sp-1) = '\0'; // StripTrailingNewline(promiser) and terminate np = PromiseTypeAppendPromise(tp, promiser, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, context); np->offset.line = lineno; PromiseAppendConstraint(np, "insert_type", RvalNew("preserve_all_lines", RVAL_TYPE_SCALAR), false); DeleteItemList(lines); free(promiser); lines = NULL; } else { if (IsDefinedClass(ctx, context)) { if (level > 0) { AppendItem(&lines, buffer, context); } else { //install independent promise line StripTrailingNewline(buffer, buffer_size); np = PromiseTypeAppendPromise(tp, buffer, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, context); np->offset.line = lineno; PromiseAppendConstraint(np, "insert_type", RvalNew("preserve_all_lines", RVAL_TYPE_SCALAR), false); } } } } free(buffer); } fclose(fp); return bp; } /***************************************************************************/ /* Level */ /***************************************************************************/ static PromiseResult KeepEditLinePromise(EvalContext *ctx, const Promise *pp, void *param) { EditContext *edcontext = param; PromiseBanner(pp); if (strcmp("classes", pp->parent_promise_type->name) == 0) { return VerifyClassPromise(ctx, pp, NULL); } else if (strcmp("delete_lines", pp->parent_promise_type->name) == 0) { return VerifyLineDeletions(ctx, pp, edcontext); } else if (strcmp("field_edits", pp->parent_promise_type->name) == 0) { return VerifyColumnEdits(ctx, pp, edcontext); } else if (strcmp("insert_lines", pp->parent_promise_type->name) == 0) { return VerifyLineInsertions(ctx, pp, edcontext); } else if (strcmp("replace_patterns", pp->parent_promise_type->name) == 0) { return VerifyPatterns(ctx, pp, edcontext); } else if (strcmp("reports", pp->parent_promise_type->name) == 0) { return VerifyReportPromise(ctx, pp); } return PROMISE_RESULT_NOOP; } /***************************************************************************/ /* Level */ /***************************************************************************/ static PromiseResult VerifyLineDeletions(EvalContext *ctx, const Promise *pp, EditContext *edcontext) { Item **start = &(edcontext->file_start); Item *begin_ptr, *end_ptr; CfLock thislock; char lockname[CF_BUFSIZE]; Attributes a = GetDeletionAttributes(ctx, pp); a.transaction.ifelapsed = CF_EDIT_IFELAPSED; if (!SanityCheckDeletions(a, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised line deletion '%s' is inconsistent", pp->promiser); return PROMISE_RESULT_INTERRUPTED; } /* Are we working in a restricted region? */ PromiseResult result = PROMISE_RESULT_NOOP; if (!a.haveregion) { begin_ptr = CF_UNDEFINED_ITEM; end_ptr = CF_UNDEFINED_ITEM; } else if (!SelectRegion(ctx, *start, &begin_ptr, &end_ptr, a, pp, edcontext, &result)) { if (a.region.include_end || a.region.include_start) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised line deletion '%s' could not select an edit region in '%s' (this is a good thing, as policy suggests deleting the markers)", pp->promiser, edcontext->filename); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised line deletion '%s' could not select an edit region in '%s' (but the delimiters were expected in the file)", pp->promiser, edcontext->filename); } result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "deleteline-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } if (DeletePromisedLinesMatching(ctx, start, begin_ptr, end_ptr, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyColumnEdits(EvalContext *ctx, const Promise *pp, EditContext *edcontext) { Item **start = &(edcontext->file_start); Item *begin_ptr, *end_ptr; CfLock thislock; char lockname[CF_BUFSIZE]; Attributes a = GetColumnAttributes(ctx, pp); a.transaction.ifelapsed = CF_EDIT_IFELAPSED; if (a.column.column_separator == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "No field_separator in promise to edit by column for '%s'", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_WARN; } if (a.column.select_column <= 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "No select_field in promise to edit '%s'", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_WARN; } if (!a.column.column_value) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "No field_value is promised to column_edit '%s'", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_WARN; } /* Are we working in a restricted region? */ PromiseResult result = PROMISE_RESULT_NOOP; if (!a.haveregion) { begin_ptr = *start; end_ptr = NULL; // EndOfList(*start); } else if (!SelectRegion(ctx, *start, &begin_ptr, &end_ptr, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised column edit '%s' could not select an edit region in '%s'", pp->promiser, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } /* locate and split line */ snprintf(lockname, CF_BUFSIZE - 1, "column-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } if (EditColumns(ctx, begin_ptr, end_ptr, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } YieldCurrentLock(thislock); return result; } /***************************************************************************/ static PromiseResult VerifyPatterns(EvalContext *ctx, const Promise *pp, EditContext *edcontext) { Item **start = &(edcontext->file_start); Item *begin_ptr, *end_ptr; CfLock thislock; char lockname[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "Looking at pattern '%s'", pp->promiser); /* Are we working in a restricted region? */ Attributes a = GetReplaceAttributes(ctx, pp); a.transaction.ifelapsed = CF_EDIT_IFELAPSED; if (!a.replace.replace_value) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised pattern replace '%s' had no replacement string", pp->promiser); return PROMISE_RESULT_INTERRUPTED; } PromiseResult result = PROMISE_RESULT_NOOP; if (!a.haveregion) { begin_ptr = *start; end_ptr = NULL; //EndOfList(*start); } else if (!SelectRegion(ctx, *start, &begin_ptr, &end_ptr, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised pattern replace '%s' could not select an edit region in '%s'", pp->promiser, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } snprintf(lockname, CF_BUFSIZE - 1, "replace-%s-%s", pp->promiser, edcontext->filename); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } /* Make sure back references are expanded */ if (ReplacePatterns(ctx, begin_ptr, end_ptr, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } EvalContextVariableClearMatch(ctx); YieldCurrentLock(thislock); return result; } /***************************************************************************/ static int SelectNextItemMatching(EvalContext *ctx, const char *regexp, Item *begin, Item *end, Item **match, Item **prev) { Item *ip_prev = CF_UNDEFINED_ITEM; *match = CF_UNDEFINED_ITEM; *prev = CF_UNDEFINED_ITEM; for (Item *ip = begin; ip != end; ip = ip->next) { if (ip->name == NULL) { continue; } if (FullTextMatch(ctx, regexp, ip->name)) { *match = ip; *prev = ip_prev; return true; } ip_prev = ip; } return false; } /***************************************************************************/ static int SelectLastItemMatching(EvalContext *ctx, const char *regexp, Item *begin, Item *end, Item **match, Item **prev) { Item *ip, *ip_last = NULL, *ip_prev = CF_UNDEFINED_ITEM; *match = CF_UNDEFINED_ITEM; *prev = CF_UNDEFINED_ITEM; for (ip = begin; ip != end; ip = ip->next) { if (ip->name == NULL) { continue; } if (FullTextMatch(ctx, regexp, ip->name)) { *prev = ip_prev; ip_last = ip; } ip_prev = ip; } if (ip_last) { *match = ip_last; return true; } return false; } /***************************************************************************/ static int SelectItemMatching(EvalContext *ctx, Item *start, char *regex, Item *begin_ptr, Item *end_ptr, Item **match, Item **prev, char *fl) { Item *ip; int ret = false; *match = CF_UNDEFINED_ITEM; *prev = CF_UNDEFINED_ITEM; if (regex == NULL) { return false; } if (fl && (strcmp(fl, "first") == 0)) { if (SelectNextItemMatching(ctx, regex, begin_ptr, end_ptr, match, prev)) { ret = true; } } else { if (SelectLastItemMatching(ctx, regex, begin_ptr, end_ptr, match, prev)) { ret = true; } } if ((*match != CF_UNDEFINED_ITEM) && (*prev == CF_UNDEFINED_ITEM)) { for (ip = start; (ip != NULL) && (ip != *match); ip = ip->next) { *prev = ip; } } return ret; } /***************************************************************************/ static PromiseResult VerifyLineInsertions(EvalContext *ctx, const Promise *pp, EditContext *edcontext) { Item **start = &(edcontext->file_start), *match, *prev; Item *begin_ptr, *end_ptr; CfLock thislock; char lockname[CF_BUFSIZE]; Attributes a = GetInsertionAttributes(ctx, pp); int allow_multi_lines = a.sourcetype && strcmp(a.sourcetype, "preserve_all_lines") == 0; a.transaction.ifelapsed = CF_EDIT_IFELAPSED; if (!SanityCheckInsertions(a)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised line insertion '%s' breaks its own promises", pp->promiser); return PROMISE_RESULT_INTERRUPTED; } /* Are we working in a restricted region? */ PromiseResult result = PROMISE_RESULT_NOOP; if (!a.haveregion) { begin_ptr = *start; end_ptr = NULL; //EndOfList(*start); } else if (!SelectRegion(ctx, *start, &begin_ptr, &end_ptr, a, pp, edcontext, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised line insertion '%s' could not select an edit region in '%s'", pp->promiser, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } if (allow_multi_lines) { // promise to insert duplicates on first pass only snprintf(lockname, CF_BUFSIZE - 1, "insertline-%s-%s-%lu", pp->promiser, edcontext->filename, (long unsigned int) pp->offset.line); } else { snprintf(lockname, CF_BUFSIZE - 1, "insertline-%s-%s", pp->promiser, edcontext->filename); } thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, true); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } /* Are we looking for an anchored line inside the region? */ if (a.location.line_matching == NULL) { if (InsertMultipleLinesToRegion(ctx, start, begin_ptr, end_ptr, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } } else { if (!SelectItemMatching(ctx, *start, a.location.line_matching, begin_ptr, end_ptr, &match, &prev, a.location.first_last)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised line insertion '%s' could not select a locator matching regex '%s' in '%s'", pp->promiser, a.location.line_matching, edcontext->filename); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); YieldCurrentLock(thislock); return result; } if (InsertMultipleLinesAtLocation(ctx, start, begin_ptr, end_ptr, match, prev, a, pp, edcontext, &result)) { (edcontext->num_edits)++; } } YieldCurrentLock(thislock); return result; } /***************************************************************************/ /* Level */ /***************************************************************************/ static int SelectRegion(EvalContext *ctx, Item *start, Item **begin_ptr, Item **end_ptr, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) /* This should provide pointers to the first and last line of text that include the delimiters, since we need to include those in case they are being deleted, etc. It returns true if a match was identified, else false. If no such region matches, begin_ptr and end_ptr should point to CF_UNDEFINED_ITEM */ { Item *ip, *beg = CF_UNDEFINED_ITEM, *end = CF_UNDEFINED_ITEM; for (ip = start; ip != NULL; ip = ip->next) { if (a.region.select_start) { if (beg == CF_UNDEFINED_ITEM && FullTextMatch(ctx, a.region.select_start, ip->name)) { if (!a.region.include_start) { if (ip->next == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised start pattern '%s' found an empty region at the end of file '%s'", a.region.select_start, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } } beg = ip; continue; } } if (a.region.select_end && beg != CF_UNDEFINED_ITEM) { if (end == CF_UNDEFINED_ITEM && FullTextMatch(ctx, a.region.select_end, ip->name)) { end = ip; break; } } if (beg != CF_UNDEFINED_ITEM && end != CF_UNDEFINED_ITEM) { break; } } if (beg == CF_UNDEFINED_ITEM && a.region.select_start) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "The promised start pattern '%s' was not found when selecting edit region in '%s'", a.region.select_start, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if (end == CF_UNDEFINED_ITEM) { end = NULL; } *begin_ptr = beg; *end_ptr = end; return true; } /*****************************************************************************/ static int MatchRegion(EvalContext *ctx, const char *chunk, const Item *begin, const Item *end, bool regex) /* Match a region in between the selection delimiters. It is called after SelectRegion. The end delimiter will be visible here so we have to check for it. Can handle multi-line chunks */ { const Item *ip = begin; char buf[CF_BUFSIZE]; int lines = 0; for (const char *sp = chunk; sp <= chunk + strlen(chunk); sp++) { memset(buf, 0, CF_BUFSIZE); sscanf(sp, "%[^\n]", buf); sp += strlen(buf); if (ip == NULL) { return false; } if (!regex && strcmp(buf, ip->name) != 0) { return false; } if (regex && !FullTextMatch(ctx, buf, ip->name)) { return false; } lines++; // We have to manually exclude the marked terminator if (ip == end) { return false; } // Now see if there is more if (ip->next) { ip = ip->next; } else // if the region runs out before the end { if (++sp <= chunk + strlen(chunk)) { return false; } break; } } return lines; } /*****************************************************************************/ static int InsertMultipleLinesToRegion(EvalContext *ctx, Item **start, Item *begin_ptr, Item *end_ptr, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { Item *ip, *prev = CF_UNDEFINED_ITEM; int allow_multi_lines = a.sourcetype && strcmp(a.sourcetype, "preserve_all_lines") == 0; // Insert at the start of the file if (*start == NULL) { return InsertMultipleLinesAtLocation(ctx, start, begin_ptr, end_ptr, *start, prev, a, pp, edcontext, result); } // Insert at the start of the region if (a.location.before_after == EDIT_ORDER_BEFORE) { for (ip = *start; ip != NULL; ip = ip->next) { if (ip == begin_ptr) { return InsertMultipleLinesAtLocation(ctx, start, begin_ptr, end_ptr, ip, prev, a, pp, edcontext, result); } prev = ip; } } // Insert at the end of the region / else end of the file if (a.location.before_after == EDIT_ORDER_AFTER) { for (ip = *start; ip != NULL; ip = ip->next) { if (!allow_multi_lines && MatchRegion(ctx, pp->promiser, ip, end_ptr, false)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised chunk '%s' exists within selected region of %s (promise kept)", pp->promiser, edcontext->filename); return false; } if (ip->next != NULL && ip->next == end_ptr) { return InsertMultipleLinesAtLocation(ctx, start, begin_ptr, end_ptr, ip, prev, a, pp, edcontext, result); } if (ip->next == NULL) { return InsertMultipleLinesAtLocation(ctx, start, begin_ptr, end_ptr, ip, prev, a, pp, edcontext, result); } prev = ip; } } return false; } /***************************************************************************/ static int InsertMultipleLinesAtLocation(EvalContext *ctx, Item **start, Item *begin_ptr, Item *end_ptr, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) // Promises to insert a possibly multi-line promiser at the specificed location convergently, // i.e. no insertion will be made if a neighbouring line matches { int isfileinsert = a.sourcetype && (strcmp(a.sourcetype, "file") == 0 || strcmp(a.sourcetype, "file_preserve_block") == 0); if (isfileinsert) { return InsertFileAtLocation(ctx, start, begin_ptr, end_ptr, location, prev, a, pp, edcontext, result); } else { return InsertCompoundLineAtLocation(ctx, pp->promiser, start, begin_ptr, end_ptr, location, prev, a, pp, edcontext, result); } } /***************************************************************************/ static int DeletePromisedLinesMatching(EvalContext *ctx, Item **start, Item *begin, Item *end, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { Item *ip, *np = NULL, *lp, *initiator = begin, *terminator = NULL; int i, retval = false, matches, noedits = true; if (start == NULL) { return false; } // Get a pointer from before the region so we can patch the hole later if (begin == CF_UNDEFINED_ITEM) { initiator = *start; } else { if (a.region.include_start) { initiator = begin; } else { initiator = begin->next; } } if (end == CF_UNDEFINED_ITEM) { terminator = NULL; } else { if (a.region.include_end) { terminator = end->next; } else { terminator = end; } } // Now do the deletion for (ip = initiator; ip != terminator && ip != NULL; ip = np) { if (a.not_matching) { matches = !MatchRegion(ctx, pp->promiser, ip, terminator, true); } else { matches = MatchRegion(ctx, pp->promiser, ip, terminator, true); } if (matches) { Log(LOG_LEVEL_VERBOSE, "Multi-line region (%d lines) matched text in the file", matches); } else { Log(LOG_LEVEL_DEBUG, "Multi-line region didn't match text in the file"); } if (!SelectLine(ctx, ip->name, a)) // Start search from location { np = ip->next; continue; } if (matches) { Log(LOG_LEVEL_VERBOSE, "Delete chunk of %d lines", matches); if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to delete line '%s' from %s - but only a warning was promised", ip->name, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); np = ip->next; noedits = false; } else { for (i = 1; i <= matches; i++) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Deleting the promised line %d '%s' from %s", i, ip->name, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); retval = true; noedits = false; if (ip->name != NULL) { free(ip->name); } np = ip->next; free((char *) ip); lp = ip; if (ip == *start) { if (initiator == *start) { initiator = np; } *start = np; } else { if (ip == initiator) { initiator = *start; } for (lp = initiator; lp->next != ip; lp = lp->next) { } lp->next = np; } (edcontext->num_edits)++; ip = np; } } } else { np = ip->next; } } if (noedits) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No need to delete lines from %s, ok", edcontext->filename); } return retval; } /********************************************************************/ static int ReplacePatterns(EvalContext *ctx, Item *file_start, Item *file_end, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { char line_buff[CF_EXPANDSIZE]; char after[CF_BUFSIZE]; int match_len, start_off, end_off, once_only = false, retval = false; Item *ip; int notfound = true, cutoff = 1, replaced = false; if (a.replace.occurrences && (strcmp(a.replace.occurrences, "first") == 0)) { Log(LOG_LEVEL_WARNING, "Setting replace-occurrences policy to 'first' is not convergent"); once_only = true; } Buffer *replace = BufferNew(); for (ip = file_start; ip != NULL && ip != file_end; ip = ip->next) { if (ip->name == NULL) { continue; } cutoff = 1; strlcpy(line_buff, ip->name, sizeof(line_buff)); replaced = false; match_len = 0; while (BlockTextMatch(ctx, pp->promiser, line_buff, &start_off, &end_off)) { if (match_len == strlen(line_buff)) { Log(LOG_LEVEL_VERBOSE, "Improper convergent expression matches defacto convergence, so accepting"); break; } if (cutoff++ > CF_MAX_REPLACE) { Log(LOG_LEVEL_VERBOSE, "Too many replacements on this line"); break; } match_len = end_off - start_off; BufferClear(replace); ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, a.replace.replace_value, replace); Log(LOG_LEVEL_VERBOSE, "Verifying replacement of '%s' with '%s', cutoff %d", pp->promiser, BufferData(replace), cutoff); // Save portion of line after substitution: strlcpy(after, line_buff + end_off, sizeof(after)); // TODO: gripe if that truncated ! // Substitute into line_buff: snprintf(line_buff + start_off, sizeof(line_buff) - start_off, "%s%s", BufferData(replace), after); // TODO: gripe if that truncated or failed ! notfound = false; replaced = true; if (once_only) { Log(LOG_LEVEL_VERBOSE, "Replace first occurrence only (warning, this is not a convergent policy)"); break; } } if (NotAnchored(pp->promiser) && BlockTextMatch(ctx, pp->promiser, line_buff, &start_off, &end_off)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Promised replacement '%s' on line '%s' for pattern '%s' is not convergent while editing '%s'", line_buff, ip->name, pp->promiser, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); Log(LOG_LEVEL_ERR, "Because the regular expression '%s' still matches the replacement string '%s'", pp->promiser, line_buff); PromiseRef(LOG_LEVEL_ERR, pp); break; } if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_WARN, pp, a, "Need to replace line '%s' in '%s' - but only a warning was promised", pp->promiser, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); continue; } else if (replaced) { free(ip->name); ip->name = xstrdup(line_buff); cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Replaced pattern '%s' in '%s'", pp->promiser, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); (edcontext->num_edits)++; retval = true; Log(LOG_LEVEL_VERBOSE, "cutoff %d, '%s'", cutoff, ip->name); Log(LOG_LEVEL_VERBOSE, "cutoff %d, '%s'", cutoff, line_buff); if (once_only) { Log(LOG_LEVEL_VERBOSE, "Replace first occurrence only (warning, this is not a convergent policy)"); break; } if (BlockTextMatch(ctx, pp->promiser, ip->name, &start_off, &end_off)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "Promised replacement '%s' for pattern '%s' is not properly convergent while editing '%s'", ip->name, pp->promiser, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); Log(LOG_LEVEL_INFO, "Because the regular expression '%s' still matches the end-state replacement string '%s'", pp->promiser, line_buff); PromiseRef(LOG_LEVEL_INFO, pp); } } } BufferDestroy(replace); if (notfound) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No pattern '%s' in '%s'", pp->promiser, edcontext->filename); } return retval; } /********************************************************************/ static int EditColumns(EvalContext *ctx, Item *file_start, Item *file_end, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { char separator[CF_MAXVARSIZE]; int s, e, retval = false; Item *ip; Rlist *columns = NULL; if (!ValidateRegEx(pp->promiser)) { return false; } for (ip = file_start; ip != file_end; ip = ip->next) { if (ip->name == NULL) { continue; } if (!FullTextMatch(ctx, pp->promiser, ip->name)) { continue; } else { Log(LOG_LEVEL_VERBOSE, "Matched line '%s'", ip->name); } if (!BlockTextMatch(ctx, a.column.column_separator, ip->name, &s, &e)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Field edit, no fields found by promised pattern '%s' in '%s'", a.column.column_separator, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } if (e - s > CF_MAXVARSIZE / 2) { Log(LOG_LEVEL_ERR, "Line split criterion matches a huge part of the line, seems to be in error"); return false; } strlcpy(separator, ip->name + s, e - s + 1); columns = RlistFromSplitRegex(ip->name, a.column.column_separator, CF_INFINITY, a.column.blanks_ok); retval = EditLineByColumn(ctx, &columns, a, pp, edcontext, result); if (retval) { free(ip->name); ip->name = Rlist2String(columns, separator); } RlistDestroy(columns); } return retval; } /***************************************************************************/ static int SanityCheckInsertions(Attributes a) { long not = 0; long with = 0; long ok = true; Rlist *rp; InsertMatchType opt; int exact = false, ignore_something = false; int preserve_block = a.sourcetype && strcmp(a.sourcetype, "preserve_block") == 0; if (a.line_select.startwith_from_list) { with++; } if (a.line_select.not_startwith_from_list) { not++; } if (a.line_select.match_from_list) { with++; } if (a.line_select.not_match_from_list) { not++; } if (a.line_select.contains_from_list) { with++; } if (a.line_select.not_contains_from_list) { not++; } if (not > 1) { Log(LOG_LEVEL_ERR, "Line insertion selection promise is meaningless - the alternatives are mutually exclusive (only one is allowed)"); ok = false; } if (with && not) { Log(LOG_LEVEL_ERR, "Line insertion selection promise is meaningless - cannot mix positive and negative constraints"); ok = false; } for (rp = a.insert_match; rp != NULL; rp = rp->next) { opt = InsertMatchTypeFromString(RlistScalarValue(rp)); switch (opt) { case INSERT_MATCH_TYPE_EXACT: exact = true; break; default: ignore_something = true; if (preserve_block) { Log(LOG_LEVEL_ERR, "Line insertion should not use whitespace policy with preserve_block"); ok = false; } break; } } if (exact && ignore_something) { Log(LOG_LEVEL_ERR, "Line insertion selection promise is meaningless - cannot mix exact_match with other ignore whitespace options"); ok = false; } return ok; } /***************************************************************************/ static int SanityCheckDeletions(Attributes a, const Promise *pp) { if (MultiLineString(pp->promiser)) { if (a.not_matching) { Log(LOG_LEVEL_ERR, "Makes no sense to promise multi-line delete with not_matching. Cannot be satisfied for all lines as a block."); } } return true; } /***************************************************************************/ static int MatchPolicy(EvalContext *ctx, const char *camel, const char *haystack, Rlist *insert_match, const Promise *pp) { Rlist *rp; char *sp, *spto, *firstchar, *lastchar; InsertMatchType opt; char work[CF_BUFSIZE], final[CF_BUFSIZE]; Item *list = SplitString(camel, '\n'), *ip; int direct_cmp = false, ok = false, escaped = false; //Split into separate lines first for (ip = list; ip != NULL; ip = ip->next) { ok = false; direct_cmp = (strcmp(camel, haystack) == 0); if (insert_match == NULL) { // No whitespace policy means exact_match ok = ok || direct_cmp; break; } strlcpy(final, ip->name, CF_BUFSIZE); for (rp = insert_match; rp != NULL; rp = rp->next) { opt = InsertMatchTypeFromString(RlistScalarValue(rp)); /* Exact match can be done immediately */ if (opt == INSERT_MATCH_TYPE_EXACT) { if ((rp->next != NULL) || (rp != insert_match)) { Log(LOG_LEVEL_ERR, "Multiple policies conflict with \"exact_match\", using exact match"); PromiseRef(LOG_LEVEL_ERR, pp); } ok = ok || direct_cmp; break; } if (!escaped) { // Need to escape the original string once here in case it contains regex chars when non-exact match EscapeRegexChars(ip->name, final, CF_BUFSIZE - 1); escaped = true; } if (opt == INSERT_MATCH_TYPE_IGNORE_EMBEDDED) { memset(work, 0, CF_BUFSIZE); // Strip initial and final first for (firstchar = final; isspace((int)*firstchar); firstchar++) { } for (lastchar = final + strlen(final) - 1; (lastchar > firstchar) && (isspace((int)*lastchar)); lastchar--) { } for (sp = final, spto = work; *sp != '\0'; sp++) { if ((sp > firstchar) && (sp < lastchar)) { if (isspace((int)*sp)) { while (isspace((int)*(sp + 1))) { sp++; } strcat(spto, "\\s+"); spto += 3; } else { *spto++ = *sp; } } else { *spto++ = *sp; } } strcpy(final, work); } if (opt == INSERT_MATCH_TYPE_IGNORE_LEADING) { if (strncmp(final, "\\s*", 3) != 0) { for (sp = final; isspace((int)*sp); sp++) { } strcpy(work, sp); snprintf(final, CF_BUFSIZE, "\\s*%s", work); } } if (opt == INSERT_MATCH_TYPE_IGNORE_TRAILING) { if (strncmp(final + strlen(final) - 4, "\\s*", 3) != 0) { strcpy(work, final); snprintf(final, CF_BUFSIZE, "%s\\s*", work); } } ok = ok || (FullTextMatch(ctx, final, haystack)); } if (!ok) // All lines in region need to match to avoid insertions { break; } } DeleteItemList(list); return ok; } static int IsItemInRegion(EvalContext *ctx, const char *item, const Item *begin_ptr, const Item *end_ptr, Rlist *insert_match, const Promise *pp) { for (const Item *ip = begin_ptr; ((ip != end_ptr) && (ip != NULL)); ip = ip->next) { if (MatchPolicy(ctx, item, ip->name, insert_match, pp)) { return true; } } return false; } /***************************************************************************/ static int InsertFileAtLocation(EvalContext *ctx, Item **start, Item *begin_ptr, Item *end_ptr, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { FILE *fin; char buf[CF_BUFSIZE]; int retval = false; Item *loc = NULL; int preserve_block = a.sourcetype && strcmp(a.sourcetype, "file_preserve_block") == 0; if ((fin = safe_fopen(pp->promiser, "rt")) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Could not read file '%s'. (fopen: %s)", pp->promiser, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } loc = location; Buffer *exp = BufferNew(); for(;;) { if (fgets(buf, sizeof(buf), fin) == NULL) { if (ferror(fin)) { if (errno == EISDIR) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Could not read file %s: Is a directory", pp->promiser); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); break; } else { UnexpectedError("Failed to read line from stream"); break; } } else /* feof */ { break; } } if (StripTrailingNewline(buf, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "StripTrailingNewline was called on an overlong string"); } if (feof(fin) && strlen(buf) == 0) { break; } BufferClear(exp); if (a.expandvars) { ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, buf, exp); } else { BufferAppend(exp, buf, strlen(buf)); } if (!SelectLine(ctx, BufferData(exp), a)) { continue; } if (!preserve_block && IsItemInRegion(ctx, BufferData(exp), begin_ptr, end_ptr, a.insert_match, pp)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised file line '%s' exists within file %s (promise kept)", BufferData(exp), edcontext->filename); continue; } // Need to call CompoundLine here in case ExpandScalar has inserted \n into a string retval |= InsertCompoundLineAtLocation(ctx, BufferGet(exp), start, begin_ptr, end_ptr, loc, prev, a, pp, edcontext, result); if (preserve_block && prev == CF_UNDEFINED_ITEM) { // If we are inserting a preserved block before, need to flip the implied order after the first insertion // to get the order of the block right //a.location.before_after = cfe_after; } if (prev && prev != CF_UNDEFINED_ITEM) { prev = prev->next; } else { prev = *start; } if (loc) { loc = loc->next; } else { location = *start; } } fclose(fin); BufferDestroy(exp); return retval; } /***************************************************************************/ static int InsertCompoundLineAtLocation(EvalContext *ctx, char *chunk, Item **start, Item *begin_ptr, Item *end_ptr, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { bool retval = false; char buf[CF_EXPANDSIZE]; char *sp; int preserve_all_lines = a.sourcetype && strcmp(a.sourcetype, "preserve_all_lines") == 0; int preserve_block = a.sourcetype && (preserve_all_lines || strcmp(a.sourcetype, "preserve_block") == 0 || strcmp(a.sourcetype, "file_preserve_block") == 0); if (!preserve_all_lines && MatchRegion(ctx, chunk, location, NULL, false)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised chunk '%s' exists within selected region of %s (promise kept)", pp->promiser, edcontext->filename); return false; } // Iterate over any lines within the chunk for (sp = chunk; sp <= chunk + strlen(chunk); sp++) { memset(buf, 0, CF_BUFSIZE); StringNotMatchingSetCapped(sp, CF_BUFSIZE, "\n", buf); sp += strlen(buf); if (!SelectLine(ctx, buf, a)) { continue; } if (!preserve_block && IsItemInRegion(ctx, buf, begin_ptr, end_ptr, a.insert_match, pp)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised chunk '%s' exists within selected region of %s (promise kept)", pp->promiser, edcontext->filename); continue; } retval |= InsertLineAtLocation(ctx, buf, start, location, prev, a, pp, edcontext, result); if (preserve_block && a.location.before_after == EDIT_ORDER_BEFORE && location == NULL && prev == CF_UNDEFINED_ITEM) { // If we are inserting a preserved block before, need to flip the implied order after the first insertion // to get the order of the block right // a.location.before_after = cfe_after; location = *start; } if (prev && prev != CF_UNDEFINED_ITEM) { prev = prev->next; } else { prev = *start; } if (location) { location = location->next; } else { location = *start; } } return retval; } static int NeighbourItemMatches(EvalContext *ctx, const Item *file_start, const Item *location, const char *string, EditOrder pos, Rlist *insert_match, const Promise *pp) { /* Look for a line matching proposed insert before or after location */ for (const Item *ip = file_start; ip != NULL; ip = ip->next) { if (pos == EDIT_ORDER_BEFORE) { if ((ip->next) && (ip->next == location)) { if (MatchPolicy(ctx, string, ip->name, insert_match, pp)) { return true; } else { return false; } } } if (pos == EDIT_ORDER_AFTER) { if (ip == location) { if ((ip->next) && (MatchPolicy(ctx, string, ip->next->name, insert_match, pp))) { return true; } else { return false; } } } } return false; } static int InsertLineAtLocation(EvalContext *ctx, char *newline, Item **start, Item *location, Item *prev, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) /* Check line neighbourhood in whole file to avoid edge effects, iff we are not preseving block structure */ { int preserve_block = a.sourcetype && strcmp(a.sourcetype, "preserve_block") == 0; if (prev == CF_UNDEFINED_ITEM) /* Insert at first line */ { if (a.location.before_after == EDIT_ORDER_BEFORE) { if (*start == NULL) { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to insert the promised line '%s' in %s - but only a warning was promised", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } else { PrependItemList(start, newline); (edcontext->num_edits)++; cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Inserting the promised line '%s' into %s", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } if (strcmp((*start)->name, newline) != 0) { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to prepend the promised line '%s' to %s - but only a warning was promised", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } else { PrependItemList(start, newline); (edcontext->num_edits)++; cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Prepending the promised line '%s' to %s", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised line '%s' exists at start of file %s (promise kept)", newline, edcontext->filename); return false; } } } if (a.location.before_after == EDIT_ORDER_BEFORE) { if (!preserve_block && NeighbourItemMatches(ctx, *start, location, newline, EDIT_ORDER_BEFORE, a.insert_match, pp)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised line '%s' exists before locator in (promise kept)", newline); return false; } else { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to insert line '%s' into '%s' but only a warning was promised", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } else { InsertAfter(start, prev, newline); (edcontext->num_edits)++; cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Inserting the promised line '%s' into '%s' before locator", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } } else { if (!preserve_block && NeighbourItemMatches(ctx, *start, location, newline, EDIT_ORDER_AFTER, a.insert_match, pp)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Promised line '%s' exists after locator (promise kept)", newline); return false; } else { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to insert line '%s' in '%s' but only a warning was promised", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return true; } else { InsertAfter(start, location, newline); cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Inserting the promised line '%s' into '%s' after locator", newline, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); (edcontext->num_edits)++; return true; } } } } /***************************************************************************/ static int EditLineByColumn(EvalContext *ctx, Rlist **columns, Attributes a, const Promise *pp, EditContext *edcontext, PromiseResult *result) { Rlist *rp, *this_column = NULL; char sep[CF_MAXVARSIZE]; int i, count = 0, retval = false; /* Now break up the line into a list - not we never remove an item/column */ for (rp = *columns; rp != NULL; rp = rp->next) { count++; if (count == a.column.select_column) { Log(LOG_LEVEL_VERBOSE, "Stopped at field %d", count); break; } } if (a.column.select_column > count) { if (!a.column.extend_columns) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "The file %s has only %d fields, but there is a promise for field %d", edcontext->filename, count, a.column.select_column); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); return false; } else { for (i = 0; i < (a.column.select_column - count); i++) { RlistAppendScalar(columns, ""); } count = 0; for (rp = *columns; rp != NULL; rp = rp->next) { count++; if (count == a.column.select_column) { Log(LOG_LEVEL_VERBOSE, "Stopped at column/field %d", count); break; } } } } if (a.column.value_separator != '\0') { /* internal separator, single char so split again */ if (strstr(RlistScalarValue(rp), a.column.column_value) || strcmp(RlistScalarValue(rp), a.column.column_value) != 0) { this_column = RlistFromSplitString(RlistScalarValue(rp), a.column.value_separator); retval = DoEditColumn(&this_column, a, edcontext); } else { retval = false; } if (retval) { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to edit field in %s but only warning promised", edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); retval = false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Edited field inside file object %s", edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); (edcontext->num_edits)++; free(RlistScalarValue(rp)); sep[0] = a.column.value_separator; sep[1] = '\0'; rp->val.item = Rlist2String(this_column, sep); } } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No need to edit field in %s", edcontext->filename); } RlistDestroy(this_column); return retval; } else { /* No separator, so we set the whole field to the value */ if (a.column.column_operation && strcmp(a.column.column_operation, "delete") == 0) { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to delete field field value %s in %s but only a warning was promised", RlistScalarValue(rp), edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Deleting column field value %s in %s", RlistScalarValue(rp), edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); (edcontext->num_edits)++; free(rp->val.item); rp->val.item = xstrdup(""); return true; } } else { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to set column field value %s to %s in %s but only a warning was promised", RlistScalarValue(rp), a.column.column_value, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Setting whole column field value %s to %s in %s", RlistScalarValue(rp), a.column.column_value, edcontext->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); free(rp->val.item); rp->val.item = xstrdup(a.column.column_value); (edcontext->num_edits)++; return true; } } } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No need to edit column field value %s in %s", a.column.column_value, edcontext->filename); return false; } /***************************************************************************/ static int SelectLine(EvalContext *ctx, const char *line, Attributes a) { Rlist *rp, *c; int s, e; char *selector; if ((c = a.line_select.startwith_from_list)) { for (rp = c; rp != NULL; rp = rp->next) { selector = RlistScalarValue(rp); if (strncmp(selector, line, strlen(selector)) == 0) { return true; } } return false; } if ((c = a.line_select.not_startwith_from_list)) { for (rp = c; rp != NULL; rp = rp->next) { selector = RlistScalarValue(rp); if (strncmp(selector, line, strlen(selector)) == 0) { return false; } } return true; } if ((c = a.line_select.match_from_list)) { for (rp = c; rp != NULL; rp = rp->next) { selector = RlistScalarValue(rp); if (FullTextMatch(ctx, selector, line)) { return true; } } return false; } if ((c = a.line_select.not_match_from_list)) { for (rp = c; rp != NULL; rp = rp->next) { selector = RlistScalarValue(rp); if (FullTextMatch(ctx, selector, line)) { return false; } } return true; } if ((c = a.line_select.contains_from_list)) { for (rp = c; rp != NULL; rp = rp->next) { selector = RlistScalarValue(rp); if (BlockTextMatch(ctx, selector, line, &s, &e)) { return true; } } return false; } if ((c = a.line_select.not_contains_from_list)) { for (rp = c; rp != NULL; rp = rp->next) { selector = RlistScalarValue(rp); if (BlockTextMatch(ctx, selector, line, &s, &e)) { return false; } } return true; } return true; } /***************************************************************************/ /* Level */ /***************************************************************************/ static int DoEditColumn(Rlist **columns, Attributes a, EditContext *edcontext) { Rlist *rp, *found; int retval = false; if (a.column.column_operation && (strcmp(a.column.column_operation, "delete") == 0)) { while ((found = RlistKeyIn(*columns, a.column.column_value))) { Log(LOG_LEVEL_INFO, "Deleting column field sub-value '%s' in '%s'", a.column.column_value, edcontext->filename); RlistDestroyEntry(columns, found); retval = true; } return retval; } if (a.column.column_operation && strcmp(a.column.column_operation, "set") == 0) { int length = RlistLen(*columns); if (length == 1 && strcmp(RlistScalarValue(*columns), a.column.column_value) == 0) { Log(LOG_LEVEL_VERBOSE, "Field sub-value set as promised"); return false; } else if (length == 0 && strcmp("", a.column.column_value) == 0) { Log(LOG_LEVEL_VERBOSE, "Empty field sub-value set as promised"); return false; } Log(LOG_LEVEL_INFO, "Setting field sub-value '%s' in '%s'", a.column.column_value, edcontext->filename); RlistDestroy(*columns); *columns = NULL; RlistPrependScalarIdemp(columns, a.column.column_value); return true; } if (a.column.column_operation && strcmp(a.column.column_operation, "prepend") == 0) { if (RlistPrependScalarIdemp(columns, a.column.column_value)) { Log(LOG_LEVEL_INFO, "Prepending field sub-value '%s' in '%s'", a.column.column_value, edcontext->filename); return true; } else { return false; } } if (a.column.column_operation && strcmp(a.column.column_operation, "alphanum") == 0) { if (RlistPrependScalarIdemp(columns, a.column.column_value)) { retval = true; } rp = AlphaSortRListNames(*columns); *columns = rp; return retval; } /* default operation is append */ if (RlistAppendScalarIdemp(columns, a.column.column_value)) { return true; } else { return false; } return false; } /********************************************************************/ static int NotAnchored(char *s) { if (*s != '^') { return true; } if (*(s + strlen(s) - 1) != '$') { return true; } return false; } /********************************************************************/ static int MultiLineString(char *s) { return (strchr(s, '\n') != NULL); } cfengine-3.6.2/cf-agent/findhub.h0000664000175100017510000000220112243421446016267 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FINDHUB_H #define CFENGINE_FINDHUB_H #include #include int ListHubs(List **list); void PrintList(List *list); #endif cfengine-3.6.2/cf-agent/verify_processes.c0000664000175100017510000003002412411001073020224 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static PromiseResult VerifyProcesses(EvalContext *ctx, Attributes a, const Promise *pp); static bool ProcessSanityChecks(Attributes a, const Promise *pp); static PromiseResult VerifyProcessOp(EvalContext *ctx, Item *procdata, Attributes a, const Promise *pp); static int FindPidMatches(Item *procdata, Item **killlist, Attributes a, const char *promiser); PromiseResult VerifyProcessesPromise(EvalContext *ctx, const Promise *pp) { Attributes a = GetProcessAttributes(ctx, pp); ProcessSanityChecks(a, pp); return VerifyProcesses(ctx, a, pp); } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static bool ProcessSanityChecks(Attributes a, const Promise *pp) { int promised_zero, ret = true; promised_zero = ((a.process_count.min_range == 0) && (a.process_count.max_range == 0)); if (a.restart_class) { if ((RlistKeyIn(a.signals, "term")) || (RlistKeyIn(a.signals, "kill"))) { Log(LOG_LEVEL_WARNING, "Promise '%s' kills then restarts - never strictly converges", pp->promiser); PromiseRef(LOG_LEVEL_INFO, pp); } if (a.haveprocess_count) { Log(LOG_LEVEL_ERR, "process_count and restart_class should not be used in the same promise as this makes no sense"); PromiseRef(LOG_LEVEL_INFO, pp); ret = false; } } if (promised_zero && (a.restart_class)) { Log(LOG_LEVEL_ERR, "Promise constraint conflicts - '%s' processes cannot have zero count if restarted", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); ret = false; } if ((a.haveselect) && (!a.process_select.process_result)) { Log(LOG_LEVEL_ERR, "Process select constraint body promised no result (check body definition)"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } return ret; } /*****************************************************************************/ static PromiseResult VerifyProcesses(EvalContext *ctx, Attributes a, const Promise *pp) { CfLock thislock; char lockname[CF_BUFSIZE]; if (a.restart_class) { snprintf(lockname, CF_BUFSIZE - 1, "proc-%s-%s", pp->promiser, a.restart_class); } else { snprintf(lockname, CF_BUFSIZE - 1, "proc-%s-norestart", pp->promiser); } thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } PromiseBanner(pp); PromiseResult result = VerifyProcessOp(ctx, PROCESSTABLE, a, pp); YieldCurrentLock(thislock); return result; } static PromiseResult VerifyProcessOp(EvalContext *ctx, Item *procdata, Attributes a, const Promise *pp) { bool do_signals = true; int out_of_range; int killed = 0; bool need_to_restart = true; Item *killlist = NULL; int matches = FindPidMatches(procdata, &killlist, a, pp->promiser); /* promise based on number of matches */ PromiseResult result = PROMISE_RESULT_NOOP; if (a.process_count.min_range != CF_NOINT) /* if a range is specified */ { if ((matches < a.process_count.min_range) || (matches > a.process_count.max_range)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Process count for '%s' was out of promised range (%d found)", pp->promiser, matches); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); for (const Rlist *rp = a.process_count.out_of_range_define; rp != NULL; rp = rp->next) { ClassRef ref = ClassRefParse(RlistScalarValue(rp)); EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise"); ClassRefDestroy(ref); } out_of_range = true; } else { for (const Rlist *rp = a.process_count.in_range_define; rp != NULL; rp = rp->next) { ClassRef ref = ClassRefParse(RlistScalarValue(rp)); EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=promise"); ClassRefDestroy(ref); } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Process promise for '%s' is kept", pp->promiser); out_of_range = false; } } else { out_of_range = true; } if (!out_of_range) { DeleteItemList(killlist); return result; } if (a.transaction.action == cfa_warn) { do_signals = false; result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { do_signals = true; } /* signal/kill promises for existing matches */ if (do_signals && (matches > 0)) { if (a.process_stop != NULL) { if (DONTDO) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to keep process-stop promise for '%s', but only a warning is promised", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { if (IsExecutable(CommandArg0(a.process_stop))) { ShellCommandReturnsZero(a.process_stop, SHELL_TYPE_NONE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Process promise to stop '%s' could not be kept because '%s' the stop operator failed", pp->promiser, a.process_stop); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); DeleteItemList(killlist); return result; } } } killed = DoAllSignals(ctx, killlist, a, pp, &result); } /* delegated promise to restart killed or non-existent entries */ need_to_restart = (a.restart_class != NULL) && (killed || (matches == 0)); DeleteItemList(killlist); if (!need_to_restart) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No restart promised for %s", pp->promiser); return result; } else { if (a.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Need to keep restart promise for '%s', but only a warning is promised", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Making a one-time restart promise for '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); EvalContextClassPutSoft(ctx, a.restart_class, CONTEXT_SCOPE_NAMESPACE, "source=promise"); } } return result; } #ifndef __MINGW32__ int DoAllSignals(EvalContext *ctx, Item *siglist, Attributes a, const Promise *pp, PromiseResult *result) { Item *ip; Rlist *rp; pid_t pid; int killed = false; if (siglist == NULL) { return 0; } if (a.signals == NULL) { Log(LOG_LEVEL_VERBOSE, "No signals to send for '%s'", pp->promiser); return 0; } for (ip = siglist; ip != NULL; ip = ip->next) { pid = ip->counter; for (rp = a.signals; rp != NULL; rp = rp->next) { int signal = SignalFromString(RlistScalarValue(rp)); if (!DONTDO) { if ((signal == SIGKILL) || (signal == SIGTERM)) { killed = true; } if (kill((pid_t) pid, signal) < 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Couldn't send promised signal '%s' (%d) to pid %jd (might be dead). (kill: %s)", RlistScalarValue(rp), signal, (intmax_t)pid, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Signalled '%s' (%d) to process %jd (%s)", RlistScalarValue(rp), signal, (intmax_t)pid, ip->name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } } else { Log(LOG_LEVEL_ERR, "Need to keep signal promise '%s' in process entry '%s'", RlistScalarValue(rp), ip->name); } } } return killed; } #endif static int FindPidMatches(Item *procdata, Item **killlist, Attributes a, const char *promiser) { int matches = 0; pid_t cfengine_pid = getpid(); Item *matched = SelectProcesses(procdata, promiser, a.process_select, a.haveselect); for (Item *ip = matched; ip != NULL; ip = ip->next) { pid_t pid = ip->counter; if (a.signals) /* There are some processes we don't want to signal. */ { if (pid == 1) { if (RlistLen(a.signals) == 1 && RlistKeyIn(a.signals, "hup")) { Log(LOG_LEVEL_VERBOSE, "Okay to send only HUP to init"); } else { continue; } } else if (pid < 4) { Log(LOG_LEVEL_VERBOSE, "Will not signal or restart processes 0,1,2,3 (occurred while looking for %s)", promiser); continue; } if (pid == cfengine_pid) { Log(LOG_LEVEL_VERBOSE, "cf-agent will not signal itself!"); continue; } } bool promised_zero = (a.process_count.min_range == 0) && (a.process_count.max_range == 0); if ((a.transaction.action == cfa_warn) && promised_zero) { Log(LOG_LEVEL_ERR, "Process alert '%s'", procdata->name); /* legend */ Log(LOG_LEVEL_ERR, "Process alert '%s'", ip->name); continue; } if (a.transaction.action == cfa_warn) { Log(LOG_LEVEL_ERR, "Matched '%s'", ip->name); } else { Log(LOG_LEVEL_VERBOSE, "Matched '%s'", ip->name); } PrependItem(killlist, ip->name, ""); (*killlist)->counter = pid; matches++; } DeleteItemList(matched); return matches; } cfengine-3.6.2/cf-agent/files_changes.h0000644000175100017510000000415012352557236017455 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_CHANGES_H #define CFENGINE_FILES_CHANGES_H #include typedef enum { FILE_STATE_NEW, FILE_STATE_REMOVED, FILE_STATE_CONTENT_CHANGED, FILE_STATE_STATS_CHANGED } FileState; void FileChangesLogChange(const char *file, FileState status, char *msg, const Promise *pp); bool FileChangesCheckAndUpdateHash(EvalContext *ctx, const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type, Attributes attr, const Promise *pp, PromiseResult *result); bool FileChangesGetDirectoryList(const char *path, Seq *files); void FileChangesLogNewFile(const char *path, const Promise *pp); void FileChangesCheckAndUpdateDirectory(const char *name, const Seq *file_set, const Seq *db_file_set, bool update, const Promise *pp, PromiseResult *result); void FileChangesCheckAndUpdateStats(const char *file, struct stat *sb, bool update, const Promise *pp); #endif cfengine-3.6.2/cf-agent/vercmp.c0000644000175100017510000001572212352022221016136 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include static VersionCmpResult InvertResult(VersionCmpResult result) { if (result == VERCMP_ERROR) { return VERCMP_ERROR; } else { return !result; } } static VersionCmpResult AndResults(VersionCmpResult lhs, VersionCmpResult rhs) { if ((lhs == VERCMP_ERROR) || (rhs == VERCMP_ERROR)) { return VERCMP_ERROR; } else { return lhs && rhs; } } static VersionCmpResult RunCmpCommand(EvalContext *ctx, const char *command, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result) { Buffer *expanded_command = BufferNew(); { VarRef *ref_v1 = VarRefParseFromScope("v1", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_v1, v1, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_v2 = VarRefParseFromScope("v2", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_v2, v2, CF_DATA_TYPE_STRING, "source=promise"); ExpandScalar(ctx, NULL, PACKAGES_CONTEXT, command, expanded_command); EvalContextVariableRemove(ctx, ref_v1); VarRefDestroy(ref_v1); EvalContextVariableRemove(ctx, ref_v2); VarRefDestroy(ref_v2); } FILE *pfp = a.packages.package_commands_useshell ? cf_popen_sh(BufferData(expanded_command), "w") : cf_popen(BufferData(expanded_command), "w", true); if (pfp == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Can not start package version comparison command '%s'. (cf_popen: %s)", BufferData(expanded_command), GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(expanded_command); return VERCMP_ERROR; } Log(LOG_LEVEL_VERBOSE, "Executing '%s'", BufferData(expanded_command)); int retcode = cf_pclose(pfp); if (retcode == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error during package version comparison command execution '%s'. (cf_pclose: %s)", BufferData(expanded_command), GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(expanded_command); return VERCMP_ERROR; } BufferDestroy(expanded_command); return retcode == 0; } static VersionCmpResult CompareVersionsLess(EvalContext *ctx, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result) { if (a.packages.package_version_less_command) { return RunCmpCommand(ctx, a.packages.package_version_less_command, v1, v2, a, pp, result); } else { return ComparePackageVersionsInternal(v1, v2, PACKAGE_VERSION_COMPARATOR_LT); } } static VersionCmpResult CompareVersionsEqual(EvalContext *ctx, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result) { if (a.packages.package_version_equal_command) { return RunCmpCommand(ctx, a.packages.package_version_equal_command, v1, v2, a, pp, result); } else if (a.packages.package_version_less_command) { /* emulate v1 == v2 by !(v1 < v2) && !(v2 < v1) */ return AndResults(InvertResult(CompareVersionsLess(ctx, v1, v2, a, pp, result)), InvertResult(CompareVersionsLess(ctx, v2, v1, a, pp, result))); } else { /* Built-in fallback */ return ComparePackageVersionsInternal(v1, v2, PACKAGE_VERSION_COMPARATOR_EQ); } } VersionCmpResult CompareVersions(EvalContext *ctx, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result) { VersionCmpResult cmp_result; switch (a.packages.package_select) { case PACKAGE_VERSION_COMPARATOR_EQ: case PACKAGE_VERSION_COMPARATOR_NONE: cmp_result = CompareVersionsEqual(ctx, v1, v2, a, pp, result); break; case PACKAGE_VERSION_COMPARATOR_NEQ: cmp_result = InvertResult(CompareVersionsEqual(ctx, v1, v2, a, pp, result)); break; case PACKAGE_VERSION_COMPARATOR_LT: cmp_result = CompareVersionsLess(ctx, v1, v2, a, pp, result); break; case PACKAGE_VERSION_COMPARATOR_GT: cmp_result = CompareVersionsLess(ctx, v2, v1, a, pp, result); break; case PACKAGE_VERSION_COMPARATOR_GE: cmp_result = InvertResult(CompareVersionsLess(ctx, v1, v2, a, pp, result)); break; case PACKAGE_VERSION_COMPARATOR_LE: cmp_result = InvertResult(CompareVersionsLess(ctx, v2, v1, a, pp, result)); break; default: ProgrammingError("Unexpected comparison value: %d", a.packages.package_select); break; } const char *text_result; switch (cmp_result) { case VERCMP_NO_MATCH: text_result = "no"; break; case VERCMP_MATCH: text_result = "yes"; break; default: text_result = "Incompatible version format. Can't decide"; break; } Log(LOG_LEVEL_VERBOSE, "CompareVersions: Checked whether package version %s %s %s: %s", v1, PackageVersionComparatorToString(a.packages.package_select), v2, text_result); return cmp_result; } const char* PackageVersionComparatorToString(const PackageVersionComparator pvc) { switch (pvc) { case PACKAGE_VERSION_COMPARATOR_EQ: return "=="; case PACKAGE_VERSION_COMPARATOR_NONE: return "=="; case PACKAGE_VERSION_COMPARATOR_NEQ: return "!="; case PACKAGE_VERSION_COMPARATOR_LT: return "<"; case PACKAGE_VERSION_COMPARATOR_GT: return ">"; case PACKAGE_VERSION_COMPARATOR_GE: return ">="; case PACKAGE_VERSION_COMPARATOR_LE: return "<="; default: ProgrammingError("Unexpected PackageVersionComparator value: %d", pvc); } return NULL; } cfengine-3.6.2/cf-agent/abstract_dir.c0000644000175100017510000000513212352022221017275 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include struct AbstractDir_ { /* Local directories */ Dir *local_dir; /* Remote directories */ Item *list; Item *listpos; }; AbstractDir *AbstractDirOpen(const char *dirname, FileCopy fc, AgentConnection *conn) { AbstractDir *d = xcalloc(1, sizeof(AbstractDir)); if (conn == NULL) { d->local_dir = DirOpen(dirname); if (d->local_dir == NULL) { free(d); return NULL; } } else { assert(fc.servers && strcmp(RlistScalarValue(fc.servers), "localhost")); d->list = RemoteDirList(dirname, fc.encrypt, conn); if (d->list == NULL) { free(d); return NULL; } d->listpos = d->list; } return d; } static const struct dirent *RemoteDirRead(AbstractDir *dir) { const struct dirent *ret = NULL; if (dir->listpos != NULL) { ret = (const struct dirent *)dir->listpos->name; dir->listpos = dir->listpos->next; } return ret; } const struct dirent *AbstractDirRead(AbstractDir *dir) { if (dir->local_dir) { return DirRead(dir->local_dir); } else { return RemoteDirRead(dir); } } static void RemoteDirClose(AbstractDir *dir) { if (dir->list) { DeleteItemList(dir->list); } free(dir); } void AbstractDirClose(AbstractDir *dir) { if (dir->local_dir) { DirClose(dir->local_dir); free(dir); } else { RemoteDirClose(dir); } } cfengine-3.6.2/cf-agent/verify_processes.h0000644000175100017510000000245012316547775020265 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_PROCESSES_H #define CFENGINE_VERIFY_PROCESSES_H #include PromiseResult VerifyProcessesPromise(EvalContext *ctx, const Promise *pp); /* To be implemented in Nova for Win32 */ int DoAllSignals(EvalContext *ctx, Item *siglist, Attributes a, const Promise *pp, PromiseResult *result); #endif cfengine-3.6.2/cf-agent/cf-agent-enterprise-stubs.h0000644000175100017510000000643512352566767021704 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF_AGENT_ENTERPRISE_STUBS_H #define CFENGINE_CF_AGENT_ENTERPRISE_STUBS_H #include #include #include #include #if defined(__MINGW32__) PromiseResult VerifyRegistryPromise(EvalContext *ctx, Attributes a, const Promise *pp); #endif ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, LastSawBundle, const Bundle *, bundle, double, compliance); typedef bool (*CopyRegularFileFunction)(EvalContext *ctx, const char *source, const char *dest, struct stat sstat, struct stat dstat, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn, PromiseResult *result); typedef void (*DeleteCompressedArrayFunction)(CompressedArray *start); ENTERPRISE_FUNC_8ARG_DECLARE(PromiseResult, LogFileChange, EvalContext *, ctx, const char *, file, int, change, Attributes, a, const Promise *, pp, CopyRegularFileFunction, CopyRegularFilePtr, const char *, destination, DeleteCompressedArrayFunction, DeleteCompressedArrayPtr); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, ReportPatches, PackageManager *, list); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, Nova_NoteVarUsageDB, EvalContext *, ctx, const GenericAgentConfig *, config); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, Nova_NoteClassUsage, EvalContext *, ctx, const GenericAgentConfig *, config); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, Nova_TrackExecution, const char *, input_file); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, GenerateDiffReports, const GenericAgentConfig *, config); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, Nova_NoteAgentExecutionPerformance, const char *, input_file, struct timespec, start); #endif cfengine-3.6.2/cf-agent/nfs.h0000644000175100017510000000304312316547775015460 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_NFS_H #define CFENGINE_NFS_H #include bool LoadMountInfo(Seq *list); void DeleteMountInfo(Seq *list); int VerifyNotInFstab(EvalContext *ctx, char *name, Attributes a, const Promise *pp, PromiseResult *result); int VerifyInFstab(EvalContext *ctx, char *name, Attributes a, const Promise *pp, PromiseResult *result); PromiseResult VerifyMount(EvalContext *ctx, char *name, Attributes a, const Promise *pp); PromiseResult VerifyUnmount(EvalContext *ctx, char *name, Attributes a, const Promise *pp); void CleanupNFS(void); void MountAll(void); #endif cfengine-3.6.2/cf-agent/files_links.c0000644000175100017510000005426712352557236017176 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #define CF_MAXLINKLEVEL 4 #if !defined(__MINGW32__) static bool MakeLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result); #endif static char *AbsLinkPath(const char *from, const char *relto); /*****************************************************************************/ #ifdef __MINGW32__ PromiseResult VerifyLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { Log(LOG_LEVEL_VERBOSE, "Windows does not support symbolic links (at VerifyLink())"); return PROMISE_RESULT_FAIL; } #else static bool EnforcePromise(enum cfopaction action) { return ((!DONTDO) && (action != cfa_warn)); } PromiseResult VerifyLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { char to[CF_BUFSIZE], linkbuf[CF_BUFSIZE], absto[CF_BUFSIZE]; struct stat sb; memset(to, 0, CF_BUFSIZE); if ((!IsAbsoluteFileName(source)) && (*source != '.')) /* links without a directory reference */ { snprintf(to, CF_BUFSIZE - 1, "./%s", source); } else { strlcpy(to, source, CF_BUFSIZE); } if (!IsAbsoluteFileName(to)) /* relative path, must still check if exists */ { Log(LOG_LEVEL_DEBUG, "Relative link destination detected '%s'", to); strcpy(absto, AbsLinkPath(destination, to)); Log(LOG_LEVEL_DEBUG, "Absolute path to relative link '%s', '%s'", absto, destination); } else { strcpy(absto, to); } bool source_file_exists = true; if (stat(absto, &sb) == -1) { Log(LOG_LEVEL_DEBUG, "No source file '%s'", absto); source_file_exists = false; } if ((!source_file_exists) && (attr.link.when_no_file != cfa_force) && (attr.link.when_no_file != cfa_delete)) { Log(LOG_LEVEL_INFO, "Source '%s' for linking is absent", absto); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create link '%s' -> '%s', no source", destination, to); return PROMISE_RESULT_FAIL; } if ((!source_file_exists) && (attr.link.when_no_file == cfa_delete)) { PromiseResult result = PROMISE_RESULT_CHANGE; KillGhostLink(ctx, destination, attr, pp, &result); return result; } memset(linkbuf, 0, CF_BUFSIZE); if (readlink(destination, linkbuf, CF_BUFSIZE - 1) == -1) { if (!MakeParentDirectory2(destination, attr.move_obstructions, EnforcePromise(attr.transaction.action))) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create parent directory of link '%s' -> '%s' (enforce %d)", destination, to, EnforcePromise(attr.transaction.action)); return PROMISE_RESULT_FAIL; } else { PromiseResult result = PROMISE_RESULT_NOOP; if (!MoveObstruction(ctx, destination, attr, pp, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create link '%s' -> '%s', failed to move obstruction", destination, to); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } if (!MakeLink(ctx, destination, source, attr, pp, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create link '%s' -> '%s'", destination, to); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } return result; } } else { int ok = false; if ((attr.link.link_type == FILE_LINK_TYPE_SYMLINK) && (strcmp(linkbuf, to) != 0) && (strcmp(linkbuf, source) != 0)) { ok = true; } else if (strcmp(linkbuf, source) != 0) { ok = true; } if (ok) { if (attr.move_obstructions) { if (!DONTDO) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Overriding incorrect link '%s'", destination); PromiseResult result = PROMISE_RESULT_CHANGE; if (unlink(destination) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Link '%s' points to '%s' not '%s', error removing link", destination, linkbuf, to); return PROMISE_RESULT_FAIL; } MakeLink(ctx, destination, source, attr, pp, &result); return result; } else { Log(LOG_LEVEL_ERR, "Must remove incorrect link '%s'", destination); return PROMISE_RESULT_NOOP; } } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Link '%s' points to '%s' not '%s', not authorized to override", destination, linkbuf, to); return PROMISE_RESULT_FAIL; } } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Link '%s' points to '%s', promise kept", destination, source); return PROMISE_RESULT_NOOP; } } } #endif /* !__MINGW32__ */ /*****************************************************************************/ PromiseResult VerifyAbsoluteLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { char absto[CF_BUFSIZE]; char expand[CF_BUFSIZE]; char linkto[CF_BUFSIZE]; if (*source == '.') { strcpy(linkto, destination); ChopLastNode(linkto); AddSlash(linkto); strcat(linkto, source); } else { strcpy(linkto, source); } CompressPath(absto, linkto); expand[0] = '\0'; if (attr.link.when_no_file == cfa_force) { if (!ExpandLinks(expand, absto, 0)) /* begin at level 1 and beam out at 15 */ { Log(LOG_LEVEL_ERR, "Failed to make absolute link in"); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; } else { Log(LOG_LEVEL_DEBUG, "ExpandLinks returned '%s'", expand); } } else { strcpy(expand, absto); } CompressPath(linkto, expand); return VerifyLink(ctx, destination, linkto, attr, pp); } /*****************************************************************************/ PromiseResult VerifyRelativeLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { char *sp, *commonto, *commonfrom; char buff[CF_BUFSIZE], linkto[CF_BUFSIZE], add[CF_BUFSIZE]; int levels = 0; if (*source == '.') { return VerifyLink(ctx, destination, source, attr, pp); } if (!CompressPath(linkto, source)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link '%s' to '%s'", destination, source); return PROMISE_RESULT_INTERRUPTED; } commonto = linkto; commonfrom = destination; if (strcmp(commonto, commonfrom) == 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Failed to link '%s' to '%s', can't link file '%s' to itself", destination, source, commonto); return PROMISE_RESULT_INTERRUPTED; } while (*commonto == *commonfrom) { commonto++; commonfrom++; } while (!((IsAbsoluteFileName(commonto)) && (IsAbsoluteFileName(commonfrom)))) { commonto--; commonfrom--; } commonto++; for (sp = commonfrom; *sp != '\0'; sp++) { if (IsFileSep(*sp)) { levels++; } } memset(buff, 0, CF_BUFSIZE); strcat(buff, "."); strcat(buff, FILE_SEPARATOR_STR); while (--levels > 0) { snprintf(add, CF_BUFSIZE - 1, "..%c", FILE_SEPARATOR); if (!JoinPath(buff, add)) { return PROMISE_RESULT_FAIL; } } if (!JoinPath(buff, commonto)) { return PROMISE_RESULT_FAIL; } return VerifyLink(ctx, destination, buff, attr, pp); } /*****************************************************************************/ PromiseResult VerifyHardLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp) { char to[CF_BUFSIZE], absto[CF_BUFSIZE]; struct stat ssb, dsb; memset(to, 0, CF_BUFSIZE); if ((!IsAbsoluteFileName(source)) && (*source != '.')) /* links without a directory reference */ { snprintf(to, CF_BUFSIZE - 1, ".%c%s", FILE_SEPARATOR, source); } else { strlcpy(to, source, CF_BUFSIZE); } if (!IsAbsoluteFileName(to)) /* relative path, must still check if exists */ { Log(LOG_LEVEL_DEBUG, "Relative link destination detected '%s'", to); strcpy(absto, AbsLinkPath(destination, to)); Log(LOG_LEVEL_DEBUG, "Absolute path to relative link '%s', destination '%s'", absto, destination); } else { strcpy(absto, to); } if (stat(absto, &ssb) == -1) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, attr, "Source file '%s' doesn't exist", source); return PROMISE_RESULT_INTERRUPTED; } if (!S_ISREG(ssb.st_mode)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Source file '%s' is not a regular file, not appropriate to hard-link", to); return PROMISE_RESULT_FAIL; } Log(LOG_LEVEL_DEBUG, "Trying to hard link '%s' -> '%s'", destination, to); if (stat(destination, &dsb) == -1) { PromiseResult result = PROMISE_RESULT_NOOP; MakeHardLink(ctx, destination, to, attr, pp, &result); return result; } /* both files exist, but are they the same file? POSIX says */ /* the files could be on different devices, but unix doesn't */ /* allow this behaviour so the tests below are theoretical... */ if ((dsb.st_ino != ssb.st_ino) && (dsb.st_dev != ssb.st_dev)) { Log(LOG_LEVEL_VERBOSE, "If this is POSIX, unable to determine if %s is hard link is correct", destination); Log(LOG_LEVEL_VERBOSE, "since it points to a different filesystem!"); if ((dsb.st_mode == ssb.st_mode) && (dsb.st_size == ssb.st_size)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Hard link '%s' -> '%s' on different device appears okay", destination, to); return PROMISE_RESULT_NOOP; } } if ((dsb.st_ino == ssb.st_ino) && (dsb.st_dev == ssb.st_dev)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Hard link '%s' -> '%s' exists and is okay", destination, to); return PROMISE_RESULT_NOOP; } Log(LOG_LEVEL_INFO, "'%s' does not appear to be a hard link to '%s'", destination, to); PromiseResult result = PROMISE_RESULT_NOOP; if (!MoveObstruction(ctx, destination, attr, pp, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create hard link '%s' -> '%s', unable to move obstruction", destination, to); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } if (MakeHardLink(ctx, destination, to, attr, pp, &result)) { result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to create hard link '%s' -> '%s'", destination, to); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } return result; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ #ifdef __MINGW32__ bool KillGhostLink(EvalContext *ctx, const char *name, Attributes attr, const Promise *pp, PromiseResult *result) { Log(LOG_LEVEL_VERBOSE, "Windows does not support symbolic links (at KillGhostLink())"); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Windows does not support killing link '%s'", name); PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } #else /* !__MINGW32__ */ bool KillGhostLink(EvalContext *ctx, const char *name, Attributes attr, const Promise *pp, PromiseResult *result) { char linkbuf[CF_BUFSIZE], tmp[CF_BUFSIZE]; char linkpath[CF_BUFSIZE], *sp; struct stat statbuf; memset(linkbuf, 0, CF_BUFSIZE); memset(linkpath, 0, CF_BUFSIZE); if (readlink(name, linkbuf, CF_BUFSIZE - 1) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't read link '%s' while checking for deadlinks", name); return true; /* ignore */ } if (!IsAbsoluteFileName(linkbuf)) { strcpy(linkpath, name); /* Get path to link */ for (sp = linkpath + strlen(linkpath); (*sp != FILE_SEPARATOR) && (sp >= linkpath); sp--) { *sp = '\0'; } } strcat(linkpath, linkbuf); CompressPath(tmp, linkpath); if (stat(tmp, &statbuf) == -1) /* link points nowhere */ { if ((attr.link.when_no_file == cfa_delete) || (attr.recursion.rmdeadlinks)) { Log(LOG_LEVEL_VERBOSE, "'%s' is a link which points to '%s', but that file doesn't seem to exist", name, linkbuf); if (!DONTDO) { unlink(name); /* May not work on a client-mounted system ! */ cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Removing ghost '%s', reference to something that is not there", name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } } return false; } #endif /* !__MINGW32__ */ /*****************************************************************************/ #if !defined(__MINGW32__) static bool MakeLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result) { if (DONTDO || (attr.transaction.action == cfa_warn)) { Log(LOG_LEVEL_ERR, "Need to link files '%s' -> '%s'", from, to); return false; } else { if (symlink(to, from) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't link '%s' to '%s'. (symlink: %s)", to, from, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Linked files '%s' -> '%s'", from, to); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } } #endif /* !__MINGW32__ */ /*****************************************************************************/ #ifdef __MINGW32__ bool MakeHardLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result) { // TODO: Implement ? Log(LOG_LEVEL_VERBOSE, "Hard links are not yet supported on Windows"); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't hard link '%s' to '%s'", to, from); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } #else /* !__MINGW32__ */ bool MakeHardLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result) { if (DONTDO) { Log(LOG_LEVEL_ERR, "Need to hard link files '%s' -> '%s'", from, to); return false; } else { if (link(to, from) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't hard link '%s' to '%s'. (link: %s)", to, from, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Hard linked files '%s' -> '%s'", from, to); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } } #endif /* !__MINGW32__ */ /*********************************************************************/ /* Expand a path contaning symbolic links, up to 4 levels */ /* of symbolic links and then beam out in a hurry ! */ #ifdef __MINGW32__ int ExpandLinks(char *dest, const char *from, int level) { Log(LOG_LEVEL_ERR, "Windows does not support symbolic links (at ExpandLinks(%s,%s))", dest, from); return false; } #else /* !__MINGW32__ */ int ExpandLinks(char *dest, const char *from, int level) { char buff[CF_BUFSIZE]; char node[CF_MAXLINKSIZE]; struct stat statbuf; int lastnode = false; memset(dest, 0, CF_BUFSIZE); if (level >= CF_MAXLINKLEVEL) { Log(LOG_LEVEL_ERR, "Too many levels of symbolic links to evaluate absolute path"); return false; } const char *sp = from; while (*sp != '\0') { if (*sp == FILE_SEPARATOR) { sp++; continue; } sscanf(sp, "%[^/]", node); sp += strlen(node); if (*sp == '\0') { lastnode = true; } if (strcmp(node, ".") == 0) { continue; } if (strcmp(node, "..") == 0) { continue; } else { strcat(dest, "/"); } strcat(dest, node); if (lstat(dest, &statbuf) == -1) /* File doesn't exist so we can stop here */ { Log(LOG_LEVEL_ERR, "Can't stat '%s' in ExpandLinks. (lstat: %s)", dest, GetErrorStr()); return false; } if (S_ISLNK(statbuf.st_mode)) { memset(buff, 0, CF_BUFSIZE); if (readlink(dest, buff, CF_BUFSIZE - 1) == -1) { Log(LOG_LEVEL_ERR, "Expand links can't stat '%s'. (readlink: %s)", dest, GetErrorStr()); return false; } else { if (buff[0] == '.') { ChopLastNode(dest); AddSlash(dest); if (!JoinPath(dest, buff)) { return false; } } else if (IsAbsoluteFileName(buff)) { strcpy(dest, buff); DeleteSlash(dest); if (strcmp(dest, from) == 0) { Log(LOG_LEVEL_DEBUG, "No links to be expanded"); return true; } if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1))) { return false; } } else { ChopLastNode(dest); AddSlash(dest); strcat(dest, buff); DeleteSlash(dest); if (strcmp(dest, from) == 0) { Log(LOG_LEVEL_DEBUG, "No links to be expanded"); return true; } memset(buff, 0, CF_BUFSIZE); if ((!lastnode) && (!ExpandLinks(buff, dest, level + 1))) { return false; } } } } } return true; } #endif /* !__MINGW32__ */ /*********************************************************************/ static char *AbsLinkPath(const char *from, const char *relto) /* Take an abolute source and a relative destination object and find the absolute name of the to object */ { int pop = 1; static char destination[CF_BUFSIZE]; /* GLOBAL_R, no need to initialize */ if (IsAbsoluteFileName(relto)) { ProgrammingError("Call to AbsLInkPath with absolute pathname"); } strcpy(destination, from); /* reuse to save stack space */ const char *sp = NULL; for (sp = relto; *sp != '\0'; sp++) { if (strncmp(sp, "../", 3) == 0) { pop++; sp += 2; continue; } if (strncmp(sp, "./", 2) == 0) { sp += 1; continue; } break; /* real link */ } while (pop > 0) { ChopLastNode(destination); pop--; } if (strlen(destination) == 0) { strcpy(destination, "/"); } else { AddSlash(destination); } strcat(destination, sp); Log(LOG_LEVEL_DEBUG, "Reconstructed absolute linkname '%s'", destination); return destination; } cfengine-3.6.2/cf-agent/abstract_dir.h0000664000175100017510000000253212243421446017320 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ABSTRACT_DIR_H #define CFENGINE_ABSTRACT_DIR_H /* * Opening and reading directory from either local host or CFEngine server */ typedef struct AbstractDir_ AbstractDir; AbstractDir *AbstractDirOpen(const char *dirname, FileCopy fc, AgentConnection *pp); const struct dirent *AbstractDirRead(AbstractDir *dir); void AbstractDirClose(AbstractDir *dir); #endif cfengine-3.6.2/cf-agent/files_edit.h0000664000175100017510000000432212400110676016760 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_EDIT_H #define CFENGINE_FILES_EDIT_H #include #include #ifdef HAVE_LIBXML2 #include #include #endif #define CF_EDIT_IFELAPSED 1 /* NOTE: If doing copy template then edit working copy, the edit ifelapsed must not be higher than the copy ifelapsed. This will make the working copy equal to the copied template file - not the copied + edited file. */ typedef struct { char *filename; Item *file_start; int num_edits; #ifdef HAVE_LIBXML2 xmlDocPtr xmldoc; #endif NewLineMode new_line_mode; } EditContext; // filename must not be freed until FinishEditContext. EditContext *NewEditContext(char *filename, Attributes a); void FinishEditContext(EvalContext *ctx, EditContext *ec, Attributes a, const Promise *pp, PromiseResult *result); #ifdef HAVE_LIBXML2 int LoadFileAsXmlDoc(xmlDocPtr *doc, const char *file, EditDefaults ed); bool SaveXmlDocAsFile(xmlDocPtr doc, const char *file, Attributes a, NewLineMode new_line_mode); #endif #endif cfengine-3.6.2/cf-agent/vercmp_internal.c0000664000175100017510000001401212243421446020036 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include static void ParsePackageVersion(char *version, Rlist **num, Rlist **sep); VersionCmpResult ComparePackageVersionsInternal(const char *v1, const char *v2, PackageVersionComparator cmp) { Rlist *rp_pr, *rp_in; int result = true; int break_loop = false; int cmp_result; VersionCmpResult version_matched = VERCMP_NO_MATCH; Rlist *numbers_pr = NULL, *separators_pr = NULL; Rlist *numbers_in = NULL, *separators_in = NULL; ParsePackageVersion(CanonifyChar(v1, ','), &numbers_pr, &separators_pr); ParsePackageVersion(CanonifyChar(v2, ','), &numbers_in, &separators_in); /* If the format of the version string doesn't match, we're already doomed */ Log(LOG_LEVEL_VERBOSE, "Check for compatible versioning model in (%s,%s)", v1, v2); for (rp_pr = separators_pr, rp_in = separators_in; (rp_pr != NULL) && (rp_in != NULL); rp_pr = rp_pr->next, rp_in = rp_in->next) { if (strcmp(RlistScalarValue(rp_pr), RlistScalarValue(rp_in)) != 0) { result = false; break; } if ((rp_pr->next == NULL) && (rp_in->next == NULL)) { result = true; break; } } if (result) { Log(LOG_LEVEL_VERBOSE, "Verified that versioning models are compatible"); } else { Log(LOG_LEVEL_VERBOSE, "Versioning models for (%s,%s) were incompatible", v1, v2); version_matched = VERCMP_ERROR; } int version_equal = (strcmp(v2, v1) == 0); if (result) { for (rp_pr = numbers_pr, rp_in = numbers_in; (rp_pr != NULL) && (rp_in != NULL); rp_pr = rp_pr->next, rp_in = rp_in->next) { cmp_result = strcmp(RlistScalarValue(rp_pr), RlistScalarValue(rp_in)); switch (cmp) { case PACKAGE_VERSION_COMPARATOR_EQ: case PACKAGE_VERSION_COMPARATOR_NONE: if (version_equal) { version_matched = VERCMP_MATCH; } break; case PACKAGE_VERSION_COMPARATOR_NEQ: if (!version_equal) { version_matched = VERCMP_MATCH; } break; case PACKAGE_VERSION_COMPARATOR_GT: if (cmp_result > 0) { version_matched = VERCMP_MATCH; } else if (cmp_result < 0) { break_loop = true; } break; case PACKAGE_VERSION_COMPARATOR_LT: if (cmp_result < 0) { version_matched = VERCMP_MATCH; } else if (cmp_result > 0) { break_loop = true; } break; case PACKAGE_VERSION_COMPARATOR_GE: if ((cmp_result > 0) || version_equal) { version_matched = VERCMP_MATCH; } else if (cmp_result < 0) { break_loop = true; } break; case PACKAGE_VERSION_COMPARATOR_LE: if ((cmp_result < 0) || version_equal) { version_matched = VERCMP_MATCH; } else if (cmp_result > 0) { break_loop = true; } break; default: break; } if ((version_matched == VERCMP_MATCH) || break_loop) { rp_pr = NULL; rp_in = NULL; break; } } if (rp_pr != NULL) { if ((cmp == PACKAGE_VERSION_COMPARATOR_GT) || (cmp == PACKAGE_VERSION_COMPARATOR_GE)) { version_matched = VERCMP_MATCH; } } if (rp_in != NULL) { if ((cmp == PACKAGE_VERSION_COMPARATOR_LT) || (cmp == PACKAGE_VERSION_COMPARATOR_LE)) { version_matched = VERCMP_MATCH; } } } RlistDestroy(numbers_pr); RlistDestroy(numbers_in); RlistDestroy(separators_pr); RlistDestroy(separators_in); return version_matched; } static void ParsePackageVersion(char *version, Rlist **num, Rlist **sep) { char *sp, numeral[30], separator[2]; if (version == NULL) { return; } for (sp = version; *sp != '\0'; sp++) { memset(numeral, 0, 30); memset(separator, 0, 2); /* Split in 2's complement */ sscanf(sp, "%29[0-9a-zA-Z]", numeral); sp += strlen(numeral); /* Append to end up with left->right (major->minor) comparison */ RlistAppendScalar(num, numeral); if (*sp == '\0') { return; } sscanf(sp, "%1[^0-9a-zA-Z]", separator); RlistAppendScalar(sep, separator); } } cfengine-3.6.2/cf-agent/tokyo_check.h0000664000175100017510000000016612411001073017145 0ustar00a10038a1003800000000000000#ifndef CFENGINE_TOKYO_CHECK_H #define CFENGINE_TOKYO_CHECK_H int CheckTokyoDBCoherence( const char *path ); #endif cfengine-3.6.2/cf-agent/verify_environments.c0000664000175100017510000010531712411001073020755 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBVIRT /*****************************************************************************/ #include #include /*****************************************************************************/ enum cfhypervisors { cfv_virt_xen, cfv_virt_kvm, cfv_virt_esx, cfv_virt_vbox, cfv_virt_test, cfv_virt_xen_net, cfv_virt_kvm_net, cfv_virt_esx_net, cfv_virt_test_net, cfv_zone, cfv_ec2, cfv_eucalyptus, cfv_none }; /*****************************************************************************/ virConnectPtr CFVC[cfv_none]; #define CF_MAX_CONCURRENT_ENVIRONMENTS 256 int CF_RUNNING[CF_MAX_CONCURRENT_ENVIRONMENTS]; char *CF_SUSPENDED[CF_MAX_CONCURRENT_ENVIRONMENTS]; /*****************************************************************************/ static int EnvironmentsSanityChecks(Attributes a, const Promise *pp); static PromiseResult VerifyEnvironments(EvalContext *ctx, Attributes a, const Promise *pp); static PromiseResult VerifyVirtDomain(EvalContext *ctx, char *uri, enum cfhypervisors envtype, Attributes a, const Promise *pp); static PromiseResult VerifyVirtNetwork(EvalContext *ctx, char *uri, enum cfhypervisors envtype, Attributes a, const Promise *pp); static PromiseResult CreateVirtDom(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp); static PromiseResult DeleteVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp); static PromiseResult RunningVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp); static PromiseResult SuspendedVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp); static PromiseResult DownVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp); static void EnvironmentErrorHandler(void); static void ShowRunList(virConnectPtr vc); static void ShowDormant(void); static PromiseResult CreateVirtNetwork(EvalContext *ctx, virConnectPtr vc, char **networks, Attributes a, const Promise *pp); static PromiseResult DeleteVirtNetwork(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp); static enum cfhypervisors Str2Hypervisors(char *s); /*****************************************************************************/ void NewEnvironmentsContext(void) { int i; for (i = 0; i < cfv_none; i++) { CFVC[i] = NULL; } } void DeleteEnvironmentsContext(void) { int i; for (i = 0; i < cfv_none; i++) { if (CFVC[i] != NULL) { virConnectClose(CFVC[i]); CFVC[i] = NULL; } } } /*****************************************************************************/ PromiseResult VerifyEnvironmentsPromise(EvalContext *ctx, const Promise *pp) { CfLock thislock; Attributes a = GetEnvironmentsAttributes(ctx, pp); PromiseResult result = PROMISE_RESULT_NOOP; if (EnvironmentsSanityChecks(a, pp)) { thislock = AcquireLock(ctx, "virtual", VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_NOOP; } PromiseBanner(pp); bool excluded = false; Promise *pexp = ExpandDeRefPromise(ctx, pp, &excluded); if (excluded) { result = PROMISE_RESULT_SKIPPED; } else { result = VerifyEnvironments(ctx, a, pp); } PromiseDestroy(pexp); } YieldCurrentLock(thislock); return result; } /*****************************************************************************/ static int EnvironmentsSanityChecks(Attributes a, const Promise *pp) { if (a.env.spec) { if (a.env.cpus != CF_NOINT || a.env.memory != CF_NOINT || a.env.disk != CF_NOINT) { Log(LOG_LEVEL_ERR, "Conflicting promise of both a spec and cpu/memory/disk resources"); return false; } } if (a.env.host == NULL) { Log(LOG_LEVEL_ERR, "No environment_host defined for environment promise"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: if (a.env.cpus != CF_NOINT || a.env.memory != CF_NOINT || a.env.disk != CF_NOINT || a.env.name || a.env.addresses) { Log(LOG_LEVEL_ERR, "Network environment promises computational resources (%d,%d,%d,%s)", a.env.cpus, a.env.memory, a.env.disk, a.env.name); PromiseRef(LOG_LEVEL_ERR, pp); } break; default: break; } return true; } /*****************************************************************************/ static PromiseResult VerifyEnvironments(EvalContext *ctx, Attributes a, const Promise *pp) { char hyper_uri[CF_MAXVARSIZE]; enum cfhypervisors envtype = cfv_none; switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_xen_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "xen:///"); envtype = cfv_virt_xen; break; case cfv_virt_kvm: case cfv_virt_kvm_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "qemu:///session"); envtype = cfv_virt_kvm; break; case cfv_virt_esx: case cfv_virt_esx_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "esx://127.0.0.1"); envtype = cfv_virt_esx; break; case cfv_virt_test: case cfv_virt_test_net: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "test:///default"); envtype = cfv_virt_test; break; case cfv_virt_vbox: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "vbox:///session"); envtype = cfv_virt_vbox; break; case cfv_zone: snprintf(hyper_uri, CF_MAXVARSIZE - 1, "solaris_zone"); envtype = cfv_zone; break; default: Log(LOG_LEVEL_ERR, "Environment type '%s' not currently supported", a.env.type); return PROMISE_RESULT_NOOP; break; } Log(LOG_LEVEL_VERBOSE, "Selecting environment type '%s' '%s'", a.env.type, hyper_uri); ClassRef environment_host_ref = ClassRefParse(a.env.host); if (!EvalContextClassGet(ctx, environment_host_ref.ns, environment_host_ref.name)) { switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: case ENVIRONMENT_STATE_RUNNING: Log(LOG_LEVEL_VERBOSE, "This host ''%s' is not the promised host for the environment '%s', so setting its intended state to 'down'", VFQNAME, a.env.host); a.env.state = ENVIRONMENT_STATE_DOWN; break; default: Log(LOG_LEVEL_VERBOSE, "This is not the promised host for the environment, but it does not promise a run state, so take promise as valid"); } } ClassRefDestroy(environment_host_ref); virInitialize(); PromiseResult result = PROMISE_RESULT_NOOP; #if defined(__linux__) switch (Str2Hypervisors(a.env.type)) { case cfv_virt_xen: case cfv_virt_kvm: case cfv_virt_esx: case cfv_virt_vbox: case cfv_virt_test: result = PromiseResultUpdate(result, VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp)); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: result = PromiseResultUpdate(result, VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp)); break; case cfv_ec2: break; case cfv_eucalyptus: break; default: break; } #elif defined(__APPLE__) switch (Str2Hypervisors(a.env.type)) { case cfv_virt_vbox: case cfv_virt_test: result = PromiseResultUpdate(result, VerifyVirtDomain(ctx, hyper_uri, envtype, a, pp)); break; case cfv_virt_xen_net: case cfv_virt_kvm_net: case cfv_virt_esx_net: case cfv_virt_test_net: result = PromiseResultUpdate(result, VerifyVirtNetwork(ctx, hyper_uri, envtype, a, pp)); break; default: break; } #elif defined(__sun) switch (Str2Hypervisors(a.env.type)) { case cfv_zone: result = PromiseResultUpdate(result, VerifyZone(a, pp)); break; default: break; } #else Log(LOG_LEVEL_VERBOSE, "Unable to resolve an environment supervisor/monitor for this platform, aborting"); #endif return result; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static PromiseResult VerifyVirtDomain(EvalContext *ctx, char *uri, enum cfhypervisors envtype, Attributes a, const Promise *pp) { int num, i; /* set up the library error handler */ virSetErrorFunc(NULL, (void *) EnvironmentErrorHandler); if (CFVC[envtype] == NULL) { if ((CFVC[envtype] = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to connect to virtualization monitor '%s'", uri); return PROMISE_RESULT_NOOP; } } for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { CF_RUNNING[i] = -1; CF_SUSPENDED[i] = NULL; } num = virConnectListDomains(CFVC[envtype], CF_RUNNING, CF_MAX_CONCURRENT_ENVIRONMENTS); Log(LOG_LEVEL_VERBOSE, "Found %d running guest environments on this host (including enclosure)", num); ShowRunList(CFVC[envtype]); num = virConnectListDefinedDomains(CFVC[envtype], CF_SUSPENDED, CF_MAX_CONCURRENT_ENVIRONMENTS); Log(LOG_LEVEL_VERBOSE, "Found %d dormant guest environments on this host", num); ShowDormant(); PromiseResult result = PROMISE_RESULT_NOOP; switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: result = PromiseResultUpdate(result, CreateVirtDom(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_DELETE: result = PromiseResultUpdate(result, DeleteVirt(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_RUNNING: result = PromiseResultUpdate(result, RunningVirt(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_SUSPENDED: result = PromiseResultUpdate(result, SuspendedVirt(ctx, CFVC[envtype], a, pp)); break; case ENVIRONMENT_STATE_DOWN: result = PromiseResultUpdate(result, DownVirt(ctx, CFVC[envtype], a, pp)); break; default: Log(LOG_LEVEL_INFO, "No state specified for this environment"); break; } return result; } /*****************************************************************************/ static PromiseResult VerifyVirtNetwork(EvalContext *ctx, char *uri, enum cfhypervisors envtype, Attributes a, const Promise *pp) { int num, i; char *networks[CF_MAX_CONCURRENT_ENVIRONMENTS]; if (CFVC[envtype] == NULL) { if ((CFVC[envtype] = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to connect to virtualization monitor '%s'", uri); return PROMISE_RESULT_NOOP; } } for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { networks[i] = NULL; } num = virConnectListNetworks(CFVC[envtype], networks, CF_MAX_CONCURRENT_ENVIRONMENTS); Log(LOG_LEVEL_VERBOSE, "Detected %d active networks", num); PromiseResult result = PROMISE_RESULT_NOOP; switch (a.env.state) { case ENVIRONMENT_STATE_CREATE: result = PromiseResultUpdate(result, CreateVirtNetwork(ctx, CFVC[envtype], networks, a, pp)); break; case ENVIRONMENT_STATE_DELETE: result = PromiseResultUpdate(result, DeleteVirtNetwork(ctx, CFVC[envtype], a, pp)); break; default: Log(LOG_LEVEL_INFO, "No recogized state specified for this network environment"); break; } return result; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static PromiseResult CreateVirtDom(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { int alloc_file = false; char *xml_file; const char *name; char defaultxml[CF_MAXVARSIZE]; virDomainPtr dom; int i; snprintf(defaultxml, CF_MAXVARSIZE - 1, "" " %s" " 8388608" " 2097152" " 2" " " " hvm" " " "", pp->promiser); for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { if (CF_RUNNING[i] > 0) { dom = virDomainLookupByID(vc, CF_RUNNING[i]); name = virDomainGetName(dom); if (name && strcmp(name, pp->promiser) == 0) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Found a running environment called '%s' - promise kept", name); return PROMISE_RESULT_NOOP; } virDomainFree(dom); } } for (i = 0; CF_SUSPENDED[i] != NULL; i++) { if (strcmp(CF_SUSPENDED[i], pp->promiser) == 0) { Log(LOG_LEVEL_INFO, "Found an existing, but suspended, environment id = %s, called '%s'", CF_SUSPENDED[i], CF_SUSPENDED[i]); } } if(a.env.spec) { xml_file = xstrdup(a.env.spec); alloc_file = true; } else { Log(LOG_LEVEL_VERBOSE, "No spec file is promised, so reverting to default settings"); xml_file = defaultxml; } PromiseResult result = PROMISE_RESULT_NOOP; if ((dom = virDomainCreateXML(vc, xml_file, 0))) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Created a virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); if (a.env.cpus != CF_NOINT) { int maxcpus; if ((maxcpus = virConnectGetMaxVcpus(vc, virConnectGetType(vc))) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't determine the available CPU resources"); } else { if (a.env.cpus > maxcpus) { Log(LOG_LEVEL_INFO, "The promise to allocate %d CPUs in domain '%s' cannot be kept - only %d exist on the host", a.env.cpus, pp->promiser, maxcpus); } else if (virDomainSetVcpus(dom, (unsigned int) a.env.cpus) == -1) { Log(LOG_LEVEL_INFO, "Unable to adjust CPU count to %d", a.env.cpus); } else { Log(LOG_LEVEL_INFO, "Verified that environment CPU count is now %d", a.env.cpus); } } } if (a.env.memory != CF_NOINT) { unsigned long maxmem; if ((maxmem = virDomainGetMaxMemory(dom)) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't determine the available CPU resources"); } else { if (virDomainSetMaxMemory(dom, (unsigned long) a.env.memory) == -1) { Log(LOG_LEVEL_INFO, " Unable to set the memory limit to %d", a.env.memory); } else { Log(LOG_LEVEL_INFO, "Setting the memory limit to %d", a.env.memory); } if (virDomainSetMemory(dom, (unsigned long) a.env.memory) == -1) { Log(LOG_LEVEL_INFO, " Unable to set the current memory to %d", a.env.memory); } } } if (a.env.disk != CF_NOINT) { Log(LOG_LEVEL_VERBOSE, "Info: env_disk parameter is not currently supported on this platform"); } virDomainFree(dom); } else { virErrorPtr vp; vp = virGetLastError(); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed to create a virtual domain '%s' - check spec for errors: '%s'", pp->promiser, vp->message); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); Log(LOG_LEVEL_VERBOSE, "Quoted spec file: %s", xml_file); } if (alloc_file) { free(xml_file); } return result; } /*****************************************************************************/ static PromiseResult DeleteVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virDomainPtr dom; dom = virDomainLookupByName(vc, pp->promiser); PromiseResult result = PROMISE_RESULT_NOOP; if (dom) { if (virDomainDestroy(dom) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed to delete virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Deleted virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } virDomainFree(dom); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No such virtual domain called '%s' - promise kept", pp->promiser); } return result; } /*****************************************************************************/ static PromiseResult RunningVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virDomainPtr dom; virDomainInfo info; dom = virDomainLookupByName(vc, pp->promiser); PromiseResult result = PROMISE_RESULT_NOOP; if (dom) { if (virDomainGetInfo(dom, &info) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to probe virtual domain '%s'", pp->promiser); virDomainFree(dom); return PROMISE_RESULT_FAIL; } switch (info.state) { case VIR_DOMAIN_RUNNING: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' running - promise kept", pp->promiser); break; case VIR_DOMAIN_BLOCKED: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' running but waiting for a resource - promise kept as far as possible", pp->promiser); break; case VIR_DOMAIN_SHUTDOWN: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' is shutting down", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); Log(LOG_LEVEL_VERBOSE, "It is currently impossible to know whether it will reboot or not - deferring promise check until it has completed its shutdown"); break; case VIR_DOMAIN_PAUSED: if (virDomainResume(dom) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' failed to resume after suspension", pp->promiser); virDomainFree(dom); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); return result; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' was suspended, resuming", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; case VIR_DOMAIN_SHUTOFF: if (virDomainCreate(dom) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' failed to resume after halting", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); virDomainFree(dom); return result; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' was inactive, booting...", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; case VIR_DOMAIN_CRASHED: if (virDomainReboot(dom, 0) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' has crashed and rebooting failed", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); virDomainFree(dom); return result; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' has crashed, rebooting...", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; default: Log(LOG_LEVEL_VERBOSE, "Virtual domain '%s' is reported as having no state, whatever that means", pp->promiser); break; } if (a.env.cpus > 0) { if (virDomainSetVcpus(dom, a.env.cpus) == -1) { Log(LOG_LEVEL_INFO, " Unable to set the number of cpus to %d", a.env.cpus); } else { Log(LOG_LEVEL_INFO, "Setting the number of virtual cpus to %d", a.env.cpus); } } if (a.env.memory != CF_NOINT) { if (virDomainSetMaxMemory(dom, (unsigned long) a.env.memory) == -1) { Log(LOG_LEVEL_INFO, " Unable to set the memory limit to %d", a.env.memory); } else { Log(LOG_LEVEL_INFO, "Setting the memory limit to %d", a.env.memory); } if (virDomainSetMemory(dom, (unsigned long) a.env.memory) == -1) { Log(LOG_LEVEL_INFO, " Unable to set the current memory to %d", a.env.memory); } } if (a.env.disk != CF_NOINT) { Log(LOG_LEVEL_VERBOSE, "Info: env_disk parameter is not currently supported on this platform"); } virDomainFree(dom); } else { Log(LOG_LEVEL_VERBOSE, "Virtual domain '%s' cannot be located, attempting to recreate", pp->promiser); result = PromiseResultUpdate(result, CreateVirtDom(ctx, vc, a, pp)); } return result; } /*****************************************************************************/ static PromiseResult SuspendedVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virDomainPtr dom; virDomainInfo info; dom = virDomainLookupByName(vc, pp->promiser); PromiseResult result = PROMISE_RESULT_NOOP; if (dom) { if (virDomainGetInfo(dom, &info) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to probe virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); virDomainFree(dom); return result; } switch (info.state) { case VIR_DOMAIN_BLOCKED: case VIR_DOMAIN_RUNNING: if (virDomainSuspend(dom) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' failed to suspend", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); virDomainFree(dom); return result; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' running, suspending", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; case VIR_DOMAIN_SHUTDOWN: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' is shutting down", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); Log(LOG_LEVEL_VERBOSE, "It is currently impossible to know whether it will reboot or not - deferring promise check until it has completed its shutdown"); break; case VIR_DOMAIN_PAUSED: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' is suspended - promise kept", pp->promiser); break; case VIR_DOMAIN_SHUTOFF: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' is down - promise kept", pp->promiser); break; case VIR_DOMAIN_CRASHED: if (virDomainSuspend(dom) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' is crashed has failed to suspend", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); virDomainFree(dom); return result; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' is in a crashed state, suspending", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; default: Log(LOG_LEVEL_VERBOSE, "Virtual domain '%s' is reported as having no state, whatever that means", pp->promiser); break; } virDomainFree(dom); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' cannot be found - take promise as kept", pp->promiser); } return result; } /*****************************************************************************/ static PromiseResult DownVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virDomainPtr dom; virDomainInfo info; dom = virDomainLookupByName(vc, pp->promiser); PromiseResult result = PROMISE_RESULT_NOOP; if (dom) { if (virDomainGetInfo(dom, &info) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to probe virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); virDomainFree(dom); return result; } switch (info.state) { case VIR_DOMAIN_BLOCKED: case VIR_DOMAIN_RUNNING: if (virDomainShutdown(dom) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' failed to shutdown", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); virDomainFree(dom); return result; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' running, terminating", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; case VIR_DOMAIN_SHUTOFF: case VIR_DOMAIN_SHUTDOWN: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' is down - promise kept", pp->promiser); break; case VIR_DOMAIN_PAUSED: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' is suspended - ignoring promise", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); break; case VIR_DOMAIN_CRASHED: if (virDomainSuspend(dom) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, a, "Virtual domain '%s' is crashed and failed to shutdown", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); virDomainFree(dom); return false; } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Virtual domain '%s' is in a crashed state, terminating", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; default: Log(LOG_LEVEL_VERBOSE, "Virtual domain '%s' is reported as having no state, whatever that means", pp->promiser); break; } virDomainFree(dom); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Virtual domain '%s' cannot be found - take promise as kept", pp->promiser); } return result; } /*****************************************************************************/ static PromiseResult CreateVirtNetwork(EvalContext *ctx, virConnectPtr vc, char **networks, Attributes a, const Promise *pp) { virNetworkPtr network; char *xml_file; char defaultxml[CF_MAXVARSIZE]; int i, found = false; snprintf(defaultxml, CF_MAXVARSIZE - 1, "" "%s" "" "" "" "" "" "" "" "", pp->promiser); for (i = 0; networks[i] != NULL; i++) { Log(LOG_LEVEL_VERBOSE, "Discovered a running network '%s'", networks[i]); if (strcmp(networks[i], pp->promiser) == 0) { found = true; } } if (found) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Network '%s' exists - promise kept", pp->promiser); return PROMISE_RESULT_NOOP; } if (a.env.spec) { xml_file = xstrdup(a.env.spec); } else { xml_file = xstrdup(defaultxml); } PromiseResult result = PROMISE_RESULT_NOOP; if ((network = virNetworkCreateXML(vc, xml_file)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to create network '%s'", pp->promiser); free(xml_file); return PROMISE_RESULT_FAIL; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Created network '%s' - promise repaired", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } free(xml_file); virNetworkFree(network); return result; } /*****************************************************************************/ static PromiseResult DeleteVirtNetwork(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virNetworkPtr network; if ((network = virNetworkLookupByName(vc, pp->promiser)) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Couldn't find a network called '%s' - promise assumed kept", pp->promiser); return PROMISE_RESULT_NOOP; } PromiseResult result = PROMISE_RESULT_NOOP; if (virNetworkDestroy(network) == 0) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Deleted network '%s' - promise repaired", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Network deletion of '%s' failed", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } virNetworkFree(network); return result; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static void EnvironmentErrorHandler() { } /*****************************************************************************/ static void ShowRunList(virConnectPtr vc) { int i; virDomainPtr dom; const char *name; for (i = 0; i < CF_MAX_CONCURRENT_ENVIRONMENTS; i++) { if (CF_RUNNING[i] > 0) { if ((dom = virDomainLookupByID(vc, CF_RUNNING[i]))) { Log(LOG_LEVEL_VERBOSE, "Found a running virtual domain with id %d", CF_RUNNING[i]); } if ((name = virDomainGetName(dom))) { Log(LOG_LEVEL_VERBOSE, "Found a running virtual domain called '%s'", name); } virDomainFree(dom); } } } /*****************************************************************************/ static void ShowDormant(void) { int i; for (i = 0; CF_SUSPENDED[i] != NULL; i++) { Log(LOG_LEVEL_VERBOSE, "Found a suspended, domain environment called '%s'", CF_SUSPENDED[i]); } } /*****************************************************************************/ static enum cfhypervisors Str2Hypervisors(char *s) { static char *names[] = { "xen", "kvm", "esx", "vbox", "test", "xen_net", "kvm_net", "esx_net", "test_net", "zone", "ec2", "eucalyptus", NULL }; int i; if (s == NULL) { return cfv_virt_test; } for (i = 0; names[i] != NULL; i++) { if (s && (strcmp(s, names[i]) == 0)) { return (enum cfhypervisors) i; } } return (enum cfhypervisors) i; } /*****************************************************************************/ #else /* !HAVE_LIBVIRT */ void NewEnvironmentsContext(void) { } void DeleteEnvironmentsContext(void) { } PromiseResult VerifyEnvironmentsPromise(ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Promise *pp) { return PROMISE_RESULT_NOOP; } #endif cfengine-3.6.2/cf-agent/files_select.c0000664000175100017510000003755312400110676017321 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include static int SelectTypeMatch(struct stat *lstatptr, Rlist *crit); static int SelectOwnerMatch(EvalContext *ctx, char *path, struct stat *lstatptr, Rlist *crit); static int SelectModeMatch(struct stat *lstatptr, Rlist *ls); static int SelectTimeMatch(time_t stattime, time_t fromtime, time_t totime); static int SelectNameRegexMatch(EvalContext *ctx, const char *filename, char *crit); static int SelectPathRegexMatch(EvalContext *ctx, char *filename, char *crit); static bool SelectExecRegexMatch(EvalContext *ctx, char *filename, char *crit, char *prog); static int SelectIsSymLinkTo(EvalContext *ctx, char *filename, Rlist *crit); static int SelectExecProgram(char *filename, char *command); static int SelectSizeMatch(size_t size, size_t min, size_t max); #if !defined(__MINGW32__) static int SelectGroupMatch(EvalContext *ctx, struct stat *lstatptr, Rlist *crit); #endif #if defined HAVE_CHFLAGS static int SelectBSDMatch(struct stat *lstatptr, Rlist *bsdflags); #endif int SelectLeaf(EvalContext *ctx, char *path, struct stat *sb, FileSelect fs) { Rlist *rp; StringSet *leaf_attr = StringSetNew(); #ifdef __MINGW32__ if (fs.issymlinkto != NULL) { Log(LOG_LEVEL_VERBOSE, "files_select.issymlinkto is ignored on Windows (symbolic links are not supported by Windows)"); } if (fs.groups != NULL) { Log(LOG_LEVEL_VERBOSE, "files_select.search_groups is ignored on Windows (file groups are not supported by Windows)"); } if (fs.bsdflags != NULL) { Log(LOG_LEVEL_VERBOSE, "files_select.search_bsdflags is ignored on Windows"); } #endif /* __MINGW32__ */ if (fs.name == NULL) { StringSetAdd(leaf_attr, xstrdup("leaf_name")); } for (rp = fs.name; rp != NULL; rp = rp->next) { if (SelectNameRegexMatch(ctx, path, RlistScalarValue(rp))) { StringSetAdd(leaf_attr, xstrdup("leaf_name")); break; } } if (fs.path == NULL) { StringSetAdd(leaf_attr, xstrdup("leaf_path")); } for (rp = fs.path; rp != NULL; rp = rp->next) { if (SelectPathRegexMatch(ctx, path, RlistScalarValue(rp))) { StringSetAdd(leaf_attr, xstrdup("path_name")); break; } } if (SelectTypeMatch(sb, fs.filetypes)) { StringSetAdd(leaf_attr, xstrdup("file_types")); } if ((fs.owners) && (SelectOwnerMatch(ctx, path, sb, fs.owners))) { StringSetAdd(leaf_attr, xstrdup("owner")); } if (fs.owners == NULL) { StringSetAdd(leaf_attr, xstrdup("owner")); } #ifdef __MINGW32__ StringSetAdd(leaf_attr, xstrdup("group")); #else /* !__MINGW32__ */ if ((fs.groups) && (SelectGroupMatch(ctx, sb, fs.groups))) { StringSetAdd(leaf_attr, xstrdup("group")); } if (fs.groups == NULL) { StringSetAdd(leaf_attr, xstrdup("group")); } #endif /* !__MINGW32__ */ if (SelectModeMatch(sb, fs.perms)) { StringSetAdd(leaf_attr, xstrdup("mode")); } #if defined HAVE_CHFLAGS if (SelectBSDMatch(sb, fs.bsdflags)) { StringSetAdd(leaf_attr, xstrdup("bsdflags")); } #endif if (SelectTimeMatch(sb->st_atime, fs.min_atime, fs.max_atime)) { StringSetAdd(leaf_attr, xstrdup("atime")); } if (SelectTimeMatch(sb->st_ctime, fs.min_ctime, fs.max_ctime)) { StringSetAdd(leaf_attr, xstrdup("ctime")); } if (SelectSizeMatch(sb->st_size, fs.min_size, fs.max_size)) { StringSetAdd(leaf_attr, xstrdup("size")); } if (SelectTimeMatch(sb->st_mtime, fs.min_mtime, fs.max_mtime)) { StringSetAdd(leaf_attr, xstrdup("mtime")); } if ((fs.issymlinkto) && (SelectIsSymLinkTo(ctx, path, fs.issymlinkto))) { StringSetAdd(leaf_attr, xstrdup("issymlinkto")); } if ((fs.exec_regex) && (SelectExecRegexMatch(ctx, path, fs.exec_regex, fs.exec_program))) { StringSetAdd(leaf_attr, xstrdup("exec_regex")); } if ((fs.exec_program) && (SelectExecProgram(path, fs.exec_program))) { StringSetAdd(leaf_attr, xstrdup("exec_program")); } bool result = EvalFileResult(fs.result, leaf_attr); Log(LOG_LEVEL_VERBOSE, "file_select result '%s' on '%s' was '%s'", fs.result, path, result ? "true" : "false"); StringSetDestroy(leaf_attr); return result; } /*******************************************************************/ /* Level */ /*******************************************************************/ static int SelectSizeMatch(size_t size, size_t min, size_t max) { if ((size <= max) && (size >= min)) { return true; } return false; } /*******************************************************************/ static int SelectTypeMatch(struct stat *lstatptr, Rlist *crit) { Rlist *rp; StringSet *leafattrib = StringSetNew(); if (S_ISREG(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("reg")); StringSetAdd(leafattrib, xstrdup("plain")); } if (S_ISDIR(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("dir")); } #ifndef __MINGW32__ if (S_ISLNK(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("symlink")); } if (S_ISFIFO(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("fifo")); } if (S_ISSOCK(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("socket")); } if (S_ISCHR(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("char")); } if (S_ISBLK(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("block")); } #endif /* !__MINGW32__ */ #ifdef HAVE_DOOR_CREATE if (S_ISDOOR(lstatptr->st_mode)) { StringSetAdd(leafattrib, xstrdup("door")); } #endif for (rp = crit; rp != NULL; rp = rp->next) { if (EvalFileResult(RlistScalarValue(rp), leafattrib)) { StringSetDestroy(leafattrib); return true; } } StringSetDestroy(leafattrib); return false; } static int SelectOwnerMatch(EvalContext *ctx, char *path, struct stat *lstatptr, Rlist *crit) { Rlist *rp; char ownerName[CF_BUFSIZE]; int gotOwner; StringSet *leafattrib = StringSetNew(); #ifndef __MINGW32__ // no uids on Windows char buffer[CF_SMALLBUF]; snprintf(buffer, CF_SMALLBUF, "%jd", (uintmax_t) lstatptr->st_uid); StringSetAdd(leafattrib, xstrdup(buffer)); #endif /* __MINGW32__ */ gotOwner = GetOwnerName(path, lstatptr, ownerName, sizeof(ownerName)); if (gotOwner) { StringSetAdd(leafattrib, xstrdup(ownerName)); } else { StringSetAdd(leafattrib, xstrdup("none")); } for (rp = crit; rp != NULL; rp = rp->next) { if (EvalFileResult(RlistScalarValue(rp), leafattrib)) { Log(LOG_LEVEL_DEBUG, "Select owner match"); StringSetDestroy(leafattrib); return true; } if (gotOwner && (FullTextMatch(ctx, RlistScalarValue(rp), ownerName))) { Log(LOG_LEVEL_DEBUG, "Select owner match"); StringSetDestroy(leafattrib); return true; } #ifndef __MINGW32__ if (FullTextMatch(ctx, RlistScalarValue(rp), buffer)) { Log(LOG_LEVEL_DEBUG, "Select owner match"); StringSetDestroy(leafattrib); return true; } #endif /* !__MINGW32__ */ } StringSetDestroy(leafattrib); return false; } /*******************************************************************/ static int SelectModeMatch(struct stat *lstatptr, Rlist *list) { mode_t newperm, plus, minus; Rlist *rp; for (rp = list; rp != NULL; rp = rp->next) { plus = 0; minus = 0; if (!ParseModeString(RlistScalarValue(rp), &plus, &minus)) { Log(LOG_LEVEL_ERR, "Problem validating a mode string '%s' in search filter", RlistScalarValue(rp)); continue; } newperm = (lstatptr->st_mode & 07777); newperm |= plus; newperm &= ~minus; if ((newperm & 07777) == (lstatptr->st_mode & 07777)) { return true; } } return false; } /*******************************************************************/ #if defined HAVE_CHFLAGS static int SelectBSDMatch(struct stat *lstatptr, Rlist *bsdflags) { u_long newflags, plus, minus; if (!ParseFlagString(bsdflags, &plus, &minus)) { Log(LOG_LEVEL_ERR, "Problem validating a BSD flag string"); } newflags = (lstatptr->st_flags & CHFLAGS_MASK); newflags |= plus; newflags &= ~minus; if ((newflags & CHFLAGS_MASK) == (lstatptr->st_flags & CHFLAGS_MASK)) /* file okay */ { return true; } return false; } #endif /*******************************************************************/ static int SelectTimeMatch(time_t stattime, time_t fromtime, time_t totime) { return ((fromtime < stattime) && (stattime < totime)); } /*******************************************************************/ static int SelectNameRegexMatch(EvalContext *ctx, const char *filename, char *crit) { if (FullTextMatch(ctx, crit, ReadLastNode(filename))) { return true; } return false; } /*******************************************************************/ static int SelectPathRegexMatch(EvalContext *ctx, char *filename, char *crit) { if (FullTextMatch(ctx, crit, filename)) { return true; } return false; } /*******************************************************************/ static bool SelectExecRegexMatch(EvalContext *ctx, char *filename, char *crit, char *prog) { // insert real value of $(this.promiser) in command char *buf_tmp = SearchAndReplace(prog, "$(this.promiser)", filename); char *buf = SearchAndReplace(buf_tmp, "${this.promiser}", filename); free(buf_tmp); FILE *pp = cf_popen(buf, "r", true); if (pp == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", buf, GetErrorStr()); free(buf); return false; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Error reading output from command '%s'. (fgets: %s)", buf, GetErrorStr()); } cf_pclose(pp); free(line); free(buf); return false; } if (FullTextMatch(ctx, crit, line)) { cf_pclose(pp); free(line); free(buf); return true; } } cf_pclose(pp); free(line); free(buf); return false; } /*******************************************************************/ static int SelectIsSymLinkTo(EvalContext *ctx, char *filename, Rlist *crit) { #ifndef __MINGW32__ char buffer[CF_BUFSIZE]; Rlist *rp; for (rp = crit; rp != NULL; rp = rp->next) { memset(buffer, 0, CF_BUFSIZE); struct stat statbuf; // Don't worry if this gives an error, that's handled above us. // We're calling lstat() here to avoid dereferencing the // symlink... and we only care if the inode is a directory. if (lstat(filename, &statbuf) == -1) { // Do nothing. } else if (S_ISDIR(statbuf.st_mode)) { Log(LOG_LEVEL_DEBUG, "Skipping readlink() on directory %s", filename); return false; } if (readlink(filename, buffer, CF_BUFSIZE - 1) == -1) { Log(LOG_LEVEL_ERR, "Unable to read link '%s' in filter. (readlink: %s)", filename, GetErrorStr()); return false; } if (FullTextMatch(ctx, RlistScalarValue(rp), buffer)) { return true; } } #endif /* !__MINGW32__ */ return false; } /*******************************************************************/ static int SelectExecProgram(char *filename, char *command) /* command can include $(this.promiser) for the name of the file */ { // insert real value of $(this.promiser) in command char *buf_tmp = SearchAndReplace(command, "$(this.promiser)", filename); char *buf = SearchAndReplace(buf_tmp, "${this.promiser}", filename); free(buf_tmp); bool returns_zero = ShellCommandReturnsZero(buf, SHELL_TYPE_NONE); if (returns_zero) { Log(LOG_LEVEL_DEBUG, "Select ExecProgram match for '%s'", buf); free(buf); return true; } else { free(buf); return false; } } #ifndef __MINGW32__ /*******************************************************************/ /* Unix implementations */ /*******************************************************************/ int GetOwnerName(ARG_UNUSED char *path, struct stat *lstatptr, char *owner, int ownerSz) { struct passwd *pw; memset(owner, 0, ownerSz); pw = getpwuid(lstatptr->st_uid); if (pw == NULL) { Log(LOG_LEVEL_ERR, "Could not get owner name of user with 'uid=%ju'. (getpwuid: %s)", (uintmax_t)lstatptr->st_uid, GetErrorStr()); return false; } strncpy(owner, pw->pw_name, ownerSz - 1); return true; } /*******************************************************************/ static int SelectGroupMatch(EvalContext *ctx, struct stat *lstatptr, Rlist *crit) { char buffer[CF_SMALLBUF]; struct group *gr; Rlist *rp; StringSet *leafattrib = StringSetNew(); snprintf(buffer, CF_SMALLBUF, "%jd", (uintmax_t) lstatptr->st_gid); StringSetAdd(leafattrib, xstrdup(buffer)); if ((gr = getgrgid(lstatptr->st_gid)) != NULL) { StringSetAdd(leafattrib, xstrdup(gr->gr_name)); } else { StringSetAdd(leafattrib, xstrdup("none")); } for (rp = crit; rp != NULL; rp = rp->next) { if (EvalFileResult(RlistScalarValue(rp), leafattrib)) { Log(LOG_LEVEL_DEBUG, "Select group match"); StringSetDestroy(leafattrib); return true; } if (gr && (FullTextMatch(ctx, RlistScalarValue(rp), gr->gr_name))) { Log(LOG_LEVEL_DEBUG, "Select group match"); StringSetDestroy(leafattrib); return true; } if (FullTextMatch(ctx, RlistScalarValue(rp), buffer)) { Log(LOG_LEVEL_DEBUG, "Select group match"); StringSetDestroy(leafattrib); return true; } } StringSetDestroy(leafattrib); return false; } #endif /* !__MINGW32__ */ cfengine-3.6.2/cf-agent/findhub.c0000644000175100017510000001564112352557236016304 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include List *hublist = NULL; static void AtExitDlClose(void); static int CompareHosts(const void *a, const void *b); void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void *userdata) { assert(c); if (state == AVAHI_CLIENT_FAILURE) { Log(LOG_LEVEL_ERR, "Server connection failure '%s'", avahi_strerror_ptr(avahi_client_errno_ptr(c))); avahi_simple_poll_quit_ptr(spoll); } } void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void *userdata) { AvahiClient *c = userdata; assert(b); switch(event) { case AVAHI_BROWSER_FAILURE: Log(LOG_LEVEL_ERR, "Avahi browser error '%s'", avahi_strerror_ptr(avahi_client_errno_ptr(avahi_service_browser_get_client_ptr(b)))); avahi_simple_poll_quit_ptr(spoll); return; case AVAHI_BROWSER_NEW: if ( !(avahi_service_resolver_new_ptr(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, (AvahiServiceResolverCallback) resolve_callback, c)) ) { Log(LOG_LEVEL_ERR, "Failed to resolve service '%s', error '%s'", name, avahi_strerror_ptr(avahi_client_errno_ptr(c))); } break; case AVAHI_BROWSER_REMOVE: break; case AVAHI_BROWSER_ALL_FOR_NOW: avahi_simple_poll_quit_ptr(spoll); break; case AVAHI_BROWSER_CACHE_EXHAUSTED: break; } } void resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AVAHI_GCC_UNUSED AvahiStringList *txt, AVAHI_GCC_UNUSED AvahiLookupFlags flags, AVAHI_GCC_UNUSED void* userdata) { HostProperties *hostprop = xcalloc(1, sizeof(HostProperties)); assert(r); char a[AVAHI_ADDRESS_STR_MAX]; switch(event) { case AVAHI_RESOLVER_FAILURE: Log(LOG_LEVEL_ERR, "In Avahi resolver, failed to resolve service '%s' of type '%s' in domain '%s' (error: '%s')", name, type, domain, avahi_strerror_ptr(avahi_client_errno_ptr(avahi_service_resolver_get_client_ptr(r)))); break; case AVAHI_RESOLVER_FOUND: avahi_address_snprint_ptr(a, sizeof(a), address); strlcpy(hostprop->Hostname, host_name, 4096); strlcpy(hostprop->IPAddress, a, AVAHI_ADDRESS_STR_MAX); hostprop->Port = port; ListAppend(hublist, hostprop); break; } avahi_service_resolver_free_ptr(r); } void PrintList(List *list) { ListIterator *i = NULL; i = ListIteratorGet(list); if (!i) { ProgrammingError("Unable to get iterator for hub list"); return; } do { HostProperties *hostprop = (HostProperties *)ListIteratorData(i); Log(LOG_LEVEL_NOTICE, "CFEngine Policy Server: hostname '%s', IP address '%s', port %d", hostprop->Hostname, hostprop->IPAddress, hostprop->Port); } while (ListIteratorNext(i) != -1); ListIteratorDestroy(&i); } int ListHubs(List **list) { AvahiClient *client = NULL; AvahiServiceBrowser *sb = NULL; int error; hublist = ListNew(&CompareHosts, NULL, &free); if (!hublist) { return -1; } spoll = NULL; avahi_handle = NULL; RegisterAtExitFunction(&AtExitDlClose); if (loadavahi() == -1) { Log(LOG_LEVEL_ERR, "Avahi was not found"); return -1; } if (!(spoll = avahi_simple_poll_new_ptr())) { Log(LOG_LEVEL_ERR, "Failed to create simple poll object."); if (spoll) { avahi_simple_poll_free_ptr(spoll); } return -1; } client = avahi_client_new_ptr(avahi_simple_poll_get_ptr(spoll), 0, client_callback, NULL, &error); if (!client) { Log(LOG_LEVEL_ERR, "Failed to create client '%s'", avahi_strerror_ptr(error)); if (client) { avahi_client_free_ptr(client); } if (spoll) { avahi_simple_poll_free_ptr(spoll); } return -1; } if (!(sb = avahi_service_browser_new_ptr(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_cfenginehub._tcp", NULL, 0, browse_callback, client))) { Log(LOG_LEVEL_ERR, "Failed to create service browser '%s'", avahi_strerror_ptr(avahi_client_errno_ptr(client))); if (spoll) { avahi_simple_poll_free_ptr(spoll); } if (client) { avahi_client_free_ptr(client); } if (sb) { avahi_service_browser_free_ptr(sb); } return -1; } avahi_simple_poll_loop_ptr(spoll); if (sb) avahi_service_browser_free_ptr(sb); if (client) avahi_client_free_ptr(client); if (spoll) avahi_simple_poll_free_ptr(spoll); *list = hublist; return ListCount(*list); } static void AtExitDlClose(void) { if (avahi_handle != NULL) { dlclose(avahi_handle); } } static int CompareHosts(const void *a, const void *b) { return StringSafeCompare(((HostProperties*)a)->Hostname, ((HostProperties*)b)->Hostname); } cfengine-3.6.2/cf-agent/promiser_regex_resolver.h0000644000175100017510000000241212316547775021644 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROMISER_REGEX_RESOLVER_H #define CFENGINE_PROMISER_REGEX_RESOLVER_H PromiseResult LocateFilePromiserGroup(EvalContext *ctx, char *wildpath, const Promise *pp, PromiseResult (*fnptr) (EvalContext *ctx, char *path, const Promise *ptr)); #endif cfengine-3.6.2/cf-agent/match_scope.c0000664000175100017510000000701512400110676017133 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include /* StringFromLong */ #include /* CompileRegex */ /* Sets variables */ static int RegExMatchSubString(EvalContext *ctx, pcre *rx, const char *teststring, int *start, int *end) { int ovector[OVECCOUNT]; int rc = 0; if ((rc = pcre_exec(rx, NULL, teststring, strlen(teststring), 0, 0, ovector, OVECCOUNT)) >= 0) { *start = ovector[0]; *end = ovector[1]; EvalContextVariableClearMatch(ctx); for (int i = 0; i < rc; i++) /* make backref vars $(1),$(2) etc */ { const char *backref_start = teststring + ovector[i * 2]; int backref_len = ovector[i * 2 + 1] - ovector[i * 2]; if (backref_len < CF_MAXVARSIZE) { char substring[CF_MAXVARSIZE]; char *index = StringFromLong(i); strlcpy(substring, backref_start, MIN(CF_MAXVARSIZE, backref_len + 1)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_MATCH, index, substring, CF_DATA_TYPE_STRING, "source=regex"); free(index); } } } else { *start = 0; *end = 0; } pcre_free(rx); return rc >= 0; } /* Sets variables */ static int RegExMatchFullString(EvalContext *ctx, pcre *rx, const char *teststring) { int match_start; int match_len; if (RegExMatchSubString(ctx, rx, teststring, &match_start, &match_len)) { return (match_start == 0) && (match_len == strlen(teststring)); } else { return false; } } int FullTextMatch(EvalContext *ctx, const char *regexp, const char *teststring) { pcre *rx; if (strcmp(regexp, teststring) == 0) { return true; } rx = CompileRegex(regexp); if (rx == NULL) { return false; } if (RegExMatchFullString(ctx, rx, teststring)) { return true; } else { return false; } } bool ValidateRegEx(const char *regex) { pcre *rx = CompileRegex(regex); bool regex_valid = rx != NULL; pcre_free(rx); return regex_valid; } int BlockTextMatch(EvalContext *ctx, const char *regexp, const char *teststring, int *start, int *end) { pcre *rx = CompileRegex(regexp); if (rx == NULL) { return 0; } if (RegExMatchSubString(ctx, rx, teststring, start, end)) { return true; } else { return false; } } cfengine-3.6.2/cf-agent/acl_posix.h0000644000175100017510000000225512316547775016657 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ACL_POSIX_H #define CFENGINE_ACL_POSIX_H #include PromiseResult CheckPosixLinuxACL(EvalContext *ctx, const char *file_path, Acl acl, Attributes a, const Promise *pp); #endif cfengine-3.6.2/cf-agent/files_changes.c0000664000175100017510000005662512411001073017443 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include /* The format of the changes database is as follows: Key: | Value: "D_" | "\0\0..." (SORTED!) | "H_ | "\0" | "S_ | "" Explanation: - The "D" entry contains all the filenames that have been recorded in that directory, stored as the basename. - The "H" entry records the hash of a file. - The "S" entry records the stat information of a file. */ #define CHANGES_HASH_STRING_LEN 7 #define CHANGES_HASH_FILE_NAME_OFFSET CHANGES_HASH_STRING_LEN+1 typedef struct { unsigned char mess_digest[EVP_MAX_MD_SIZE + 1]; /* Content digest */ } ChecksumValue; static bool GetDirectoryListFromDatabase(CF_DB *db, const char * path, Seq *files); static bool FileChangesSetDirectoryList(CF_DB *db, const char *path, const Seq *files); /* * Key format: * * 7 bytes hash name, \0 padded at right * 1 byte \0 * N bytes pathname */ static char *NewIndexKey(char type, const char *name, int *size) { char *chk_key; // "H_" plus pathname plus index_str in one block + \0 *size = strlen(name) + CHANGES_HASH_FILE_NAME_OFFSET + 3; chk_key = xcalloc(1, *size); // Data start after offset for index strncpy(chk_key, "H_", 2); strncpy(chk_key + 2, HashNameFromId(type), CHANGES_HASH_STRING_LEN); strncpy(chk_key + 2 + CHANGES_HASH_FILE_NAME_OFFSET, name, strlen(name)); return chk_key; } static void DeleteIndexKey(char *key) { free(key); } static ChecksumValue *NewHashValue(unsigned char digest[EVP_MAX_MD_SIZE + 1]) { ChecksumValue *chk_val; chk_val = xcalloc(1, sizeof(ChecksumValue)); memcpy(chk_val->mess_digest, digest, EVP_MAX_MD_SIZE + 1); return chk_val; } static void DeleteHashValue(ChecksumValue *chk_val) { free(chk_val); } static int ReadHash(CF_DB *dbp, HashMethod type, const char *name, unsigned char digest[EVP_MAX_MD_SIZE + 1]) { char *key; int size; ChecksumValue chk_val; key = NewIndexKey(type, name, &size); if (ReadComplexKeyDB(dbp, key, size, (void *) &chk_val, sizeof(ChecksumValue))) { memcpy(digest, chk_val.mess_digest, EVP_MAX_MD_SIZE + 1); DeleteIndexKey(key); return true; } else { DeleteIndexKey(key); return false; } } static int WriteHash(CF_DB *dbp, HashMethod type, const char *name, unsigned char digest[EVP_MAX_MD_SIZE + 1]) { char *key; ChecksumValue *value; int ret, keysize; key = NewIndexKey(type, name, &keysize); value = NewHashValue(digest); ret = WriteComplexKeyDB(dbp, key, keysize, value, sizeof(ChecksumValue)); DeleteIndexKey(key); DeleteHashValue(value); return ret; } static void DeleteHash(CF_DB *dbp, HashMethod type, const char *name) { int size; char *key; key = NewIndexKey(type, name, &size); DeleteComplexKeyDB(dbp, key, size); DeleteIndexKey(key); } static void AddMigratedFileToDirectoryList(CF_DB *changes_db, const char *file, const char *common_msg) { // This is incredibly inefficient, since we add files to the list one by one, // but the migration only ever needs to be done once for each host. size_t file_len = strlen(file); char dir[file_len + 1]; strcpy(dir, file); const char *basefile; char *last_slash = strrchr(dir, '/'); if (last_slash == NULL) { Log(LOG_LEVEL_ERR, "%s: Invalid file entry: '%s'", common_msg, dir); return; } if (last_slash == dir) { // If we only have one slash, it is the root dir, so we need to have // dir be equal to "/". We cannot both have that, and let basefile // point to the the next component in dir (since the first character // will then be '\0'), so point to the original file buffer instead. dir[1] = '\0'; basefile = file + 1; } else { basefile = last_slash + 1; *last_slash = '\0'; } Seq *files = SeqNew(1, free); if (!GetDirectoryListFromDatabase(changes_db, dir, files)) { Log(LOG_LEVEL_ERR, "%s: Not able to get directory index", common_msg); SeqDestroy(files); return; } if (SeqBinaryIndexOf(files, basefile, (SeqItemComparator)strcmp) == -1) { SeqAppend(files, xstrdup(basefile)); SeqSort(files, (SeqItemComparator)strcmp, NULL); if (!FileChangesSetDirectoryList(changes_db, dir, files)) { Log(LOG_LEVEL_ERR, "%s: Not able to update directory index", common_msg); } } SeqDestroy(files); } static bool MigrateOldChecksumDatabase(CF_DB *changes_db) { CF_DB *old_db; const char *common_msg = "While converting old checksum database to new format"; if (!OpenDB(&old_db, dbid_checksums)) { Log(LOG_LEVEL_ERR, "%s: Could not open database.", common_msg); return false; } CF_DBC *cursor; if (!NewDBCursor(old_db, &cursor)) { Log(LOG_LEVEL_ERR, "%s: Could not open database cursor.", common_msg); CloseDB(old_db); return false; } char *key; int ksize; char *value; int vsize; while (NextDB(cursor, &key, &ksize, (void **)&value, &vsize)) { char new_key[ksize + 2]; new_key[0] = 'H'; new_key[1] = '_'; memcpy(new_key + 2, key, ksize); if (!WriteComplexKeyDB(changes_db, new_key, sizeof(new_key), value, vsize)) { Log(LOG_LEVEL_ERR, "%s: Could not write file checksum to database", common_msg); // Keep trying for other keys. } AddMigratedFileToDirectoryList(changes_db, key + CHANGES_HASH_FILE_NAME_OFFSET, common_msg); } DeleteDBCursor(cursor); CloseDB(old_db); return true; } static bool MigrateOldStatDatabase(CF_DB *changes_db) { CF_DB *old_db; const char *common_msg = "While converting old filestat database to new format"; if (!OpenDB(&old_db, dbid_filestats)) { Log(LOG_LEVEL_ERR, "%s: Could not open database.", common_msg); return false; } CF_DBC *cursor; if (!NewDBCursor(old_db, &cursor)) { Log(LOG_LEVEL_ERR, "%s: Could not open database cursor.", common_msg); CloseDB(old_db); return false; } char *key; int ksize; char *value; int vsize; while (NextDB(cursor, &key, &ksize, (void **)&value, &vsize)) { char new_key[ksize + 2]; new_key[0] = 'S'; new_key[1] = '_'; memcpy(new_key + 2, key, ksize); if (!WriteComplexKeyDB(changes_db, new_key, sizeof(new_key), value, vsize)) { Log(LOG_LEVEL_ERR, "%s: Could not write filestat to database", common_msg); // Keep trying for other keys. } AddMigratedFileToDirectoryList(changes_db, key, common_msg); } DeleteDBCursor(cursor); CloseDB(old_db); return true; } static bool OpenChangesDB(CF_DB **db) { if (!OpenDB(db, dbid_changes)) { Log(LOG_LEVEL_ERR, "Could not open changes database"); return false; } struct stat statbuf; char *old_checksums_db = DBIdToPath(GetWorkDir(), dbid_checksums); char *old_filestats_db = DBIdToPath(GetWorkDir(), dbid_filestats); if (stat(old_checksums_db, &statbuf) != -1) { Log(LOG_LEVEL_INFO, "Migrating checksum database"); MigrateOldChecksumDatabase(*db); char migrated_db_name[PATH_MAX]; snprintf(migrated_db_name, sizeof(migrated_db_name), "%s.cf-migrated", old_checksums_db); Log(LOG_LEVEL_INFO, "After checksum database migration: Renaming '%s' to '%s'", old_checksums_db, migrated_db_name); if (rename(old_checksums_db, migrated_db_name) != 0) { Log(LOG_LEVEL_ERR, "Could not rename '%s' to '%s'", old_checksums_db, migrated_db_name); } } if (stat(old_filestats_db, &statbuf) != -1) { Log(LOG_LEVEL_INFO, "Migrating filestat database"); MigrateOldStatDatabase(*db); char migrated_db_name[PATH_MAX]; snprintf(migrated_db_name, sizeof(migrated_db_name), "%s.cf-migrated", old_filestats_db); Log(LOG_LEVEL_INFO, "After filestat database migration: Renaming '%s' to '%s'", old_filestats_db, migrated_db_name); if (rename(old_filestats_db, migrated_db_name) != 0) { Log(LOG_LEVEL_ERR, "Could not rename '%s' to '%s'", old_filestats_db, migrated_db_name); } } free(old_checksums_db); free(old_filestats_db); return true; } static void RemoveAllFileTraces(CF_DB *db, const char *path) { for (int c = 0; c < HASH_METHOD_NONE; c++) { DeleteHash(db, c, path); } char key[strlen(path) + 3]; xsnprintf(key, sizeof(key), "S_%s", path); DeleteDB(db, key); } static bool GetDirectoryListFromDatabase(CF_DB *db, const char *path, Seq *files) { char key[strlen(path) + 3]; xsnprintf(key, sizeof(key), "D_%s", path); if (!HasKeyDB(db, key, sizeof(key))) { // Not an error, so successful, but seq remains unchanged. return true; } int size = ValueSizeDB(db, key, sizeof(key)); if (size <= 0) { // Shouldn't happen, since we don't store empty lists, but play it safe // and return empty seq. return true; } char raw_entries[size]; if (!ReadDB(db, key, raw_entries, size)) { Log(LOG_LEVEL_ERR, "Could not read changes database entry"); return false; } char *raw_entries_end = raw_entries + size; for (char *pos = raw_entries; pos < raw_entries_end;) { char *null_pos = memchr(pos, '\0', raw_entries_end - pos); if (!null_pos) { Log(LOG_LEVEL_ERR, "Unexpected end of value in changes database"); return false; } SeqAppend(files, xstrdup(pos)); pos = null_pos + 1; } return true; } bool FileChangesGetDirectoryList(const char *path, Seq *files) { CF_DB *db; if (!OpenChangesDB(&db)) { Log(LOG_LEVEL_ERR, "Could not open changes database"); return false; } bool result = GetDirectoryListFromDatabase(db, path, files); CloseDB(db); return result; } static bool FileChangesSetDirectoryList(CF_DB *db, const char *path, const Seq *files) { int size = 0; int no_files = SeqLength(files); char key[strlen(path) + 3]; xsnprintf(key, sizeof(key), "D_%s", path); if (no_files == 0) { DeleteDB(db, key); return true; } for (int c = 0; c < no_files; c++) { size += strlen(SeqAt(files, c)) + 1; } char raw_entries[size]; char *pos = raw_entries; for (int c = 0; c < no_files; c++) { strcpy(pos, SeqAt(files, c)); pos += strlen(pos) + 1; } if (!WriteDB(db, key, raw_entries, size)) { Log(LOG_LEVEL_ERR, "Could not write to changes database"); return false; } return true; } /* Returns false if filename never seen before, and adds a checksum to the database. Returns true if hashes do not match and also updates database to the new value if update is true */ bool FileChangesCheckAndUpdateHash_impl(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type, bool update, const Promise *pp, PromiseResult *result) { const int size = HashSizeFromId(type); unsigned char dbdigest[EVP_MAX_MD_SIZE + 1]; CF_DB *dbp; bool found; bool different; bool ret = false; if (!OpenChangesDB(&dbp)) { Log(LOG_LEVEL_ERR, "Unable to open the hash database!"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } if (ReadHash(dbp, type, filename, dbdigest)) { found = true; different = (memcmp(digest, dbdigest, size) != 0); if (different) { Log(LOG_LEVEL_NOTICE, "Hash '%s' for '%s' changed!", HashNameFromId(type), filename); if (pp->comment) { Log(LOG_LEVEL_NOTICE, "Preceding promise '%s'", pp->comment); } } } else { found = false; different = true; } if (different) { if ((!found || update) && !DONTDO) { const char *action = found ? "Updating" : "Storing"; char buffer[CF_HOSTKEY_STRING_SIZE]; Log(LOG_LEVEL_NOTICE, "%s %s hash for '%s' (%s)", action, HashNameFromId(type), filename, HashPrintSafe(buffer, sizeof(buffer), digest, type, true)); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); WriteHash(dbp, type, filename, digest); ret = found; } else { Log(LOG_LEVEL_NOTICE, "Hash for file '%s' changed", filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); ret = true; } } else { Log(LOG_LEVEL_VERBOSE, "File hash for %s is correct", filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_NOOP); ret = false; } CloseDB(dbp); return ret; } bool FileChangesCheckAndUpdateHash(EvalContext *ctx, const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type, Attributes attr, const Promise *pp, PromiseResult *result) { bool ret = FileChangesCheckAndUpdateHash_impl(filename, digest, type, attr.change.update, pp, result); // TODO: Move cfPS even further up the call stack. cfPS(ctx, LOG_LEVEL_DEBUG, *result, pp, attr, "Updating promise status for files changes promise"); return ret; } void FileChangesLogNewFile(const char *path, const Promise *pp) { Log(LOG_LEVEL_NOTICE, "New file '%s' found", path); FileChangesLogChange(path, FILE_STATE_NEW, "New file found", pp); } // db_file_set should already be sorted. void FileChangesCheckAndUpdateDirectory(const char *name, const Seq *file_set, const Seq *db_file_set, bool update, const Promise *pp, PromiseResult *result) { CF_DB *db; if (!OpenChangesDB(&db)) { Log(LOG_LEVEL_ERR, "Could not open changes database"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return; } Seq *disk_file_set = SeqSoftSort(file_set, (SeqItemComparator)strcmp, NULL); // We'll traverse the union of disk_file_set and db_file_set in merged order. int num_files = SeqLength(disk_file_set); int num_db_files = SeqLength(db_file_set); bool changed = false; for (int disk_pos = 0, db_pos = 0; disk_pos < num_files || db_pos < num_db_files;) { int compare_result; if (disk_pos >= num_files) { compare_result = 1; } else if (db_pos >= num_db_files) { compare_result = -1; } else { compare_result = strcmp(SeqAt(disk_file_set, disk_pos), SeqAt(db_file_set, db_pos)); } if (compare_result < 0) { /* We would have called this here, but we assume that DepthSearch() has already done it for us. The reason is that calling it here produces a very unnatural order, with all stat and content changes, as well as all subdirectories, appearing in the log before the message about a new file. This is because we save the list for last and *then* compare it to the saved directory list, *after* traversing the tree. So we let DepthSearch() do it while traversing instead. Removed files will still be listed last. */ #if 0 char *file = SeqAt(disk_file_set, disk_pos); char path[strlen(name) + strlen(file) + 2]; xsnprintf(path, sizeof(path), "%s/%s", name, file); FileChangesLogNewFile(path, pp); #endif changed = true; disk_pos++; } else if (compare_result > 0) { char *db_file = SeqAt(db_file_set, db_pos); char path[strlen(name) + strlen(db_file) + 2]; xsnprintf(path, sizeof(path), "%s/%s", name, db_file); Log(LOG_LEVEL_NOTICE, "File '%s' no longer exists", path); FileChangesLogChange(path, FILE_STATE_REMOVED, "File removed", pp); RemoveAllFileTraces(db, path); changed = true; db_pos++; } else { // DB file entry and filesystem file entry matched. disk_pos++; db_pos++; } } PromiseResult newres; if (!changed) { newres = PROMISE_RESULT_NOOP; } else if (update && FileChangesSetDirectoryList(db, name, disk_file_set)) { newres = PROMISE_RESULT_CHANGE; } else { newres = PROMISE_RESULT_FAIL; } *result = PromiseResultUpdate(*result, newres); SeqSoftDestroy(disk_file_set); CloseDB(db); } void FileChangesCheckAndUpdateStats(const char *file, struct stat *sb, bool update, const Promise *pp) { struct stat cmpsb; CF_DB *dbp; if (!OpenChangesDB(&dbp)) { return; } char key[strlen(file) + 3]; xsnprintf(key, sizeof(key), "S_%s", file); if (!ReadDB(dbp, key, &cmpsb, sizeof(struct stat))) { if (!DONTDO) { if (!WriteDB(dbp, key, sb, sizeof(struct stat))) { Log(LOG_LEVEL_ERR, "Could not write stat information to database"); } CloseDB(dbp); return; } } if (cmpsb.st_mode == sb->st_mode && cmpsb.st_uid == sb->st_uid && cmpsb.st_gid == sb->st_gid && cmpsb.st_dev == sb->st_dev && cmpsb.st_ino == sb->st_ino && cmpsb.st_mtime == sb->st_mtime) { CloseDB(dbp); return; } if (cmpsb.st_mode != sb->st_mode) { Log(LOG_LEVEL_NOTICE, "Permissions for '%s' changed %04jo -> %04jo", file, (uintmax_t)cmpsb.st_mode, (uintmax_t)sb->st_mode); char msg_temp[CF_MAXVARSIZE]; snprintf(msg_temp, sizeof(msg_temp), "Permission: %04jo -> %04jo", (uintmax_t)cmpsb.st_mode, (uintmax_t)sb->st_mode); FileChangesLogChange(file, FILE_STATE_STATS_CHANGED, msg_temp, pp); } if (cmpsb.st_uid != sb->st_uid) { Log(LOG_LEVEL_NOTICE, "Owner for '%s' changed %jd -> %jd", file, (uintmax_t) cmpsb.st_uid, (uintmax_t) sb->st_uid); char msg_temp[CF_MAXVARSIZE]; snprintf(msg_temp, sizeof(msg_temp), "Owner: %jd -> %jd", (uintmax_t)cmpsb.st_uid, (uintmax_t)sb->st_uid); FileChangesLogChange(file, FILE_STATE_STATS_CHANGED, msg_temp, pp); } if (cmpsb.st_gid != sb->st_gid) { Log(LOG_LEVEL_NOTICE, "Group for '%s' changed %jd -> %jd", file, (uintmax_t) cmpsb.st_gid, (uintmax_t) sb->st_gid); char msg_temp[CF_MAXVARSIZE]; snprintf(msg_temp, sizeof(msg_temp), "Group: %jd -> %jd", (uintmax_t)cmpsb.st_gid, (uintmax_t)sb->st_gid); FileChangesLogChange(file, FILE_STATE_STATS_CHANGED, msg_temp, pp); } if (cmpsb.st_dev != sb->st_dev) { Log(LOG_LEVEL_NOTICE, "Device for '%s' changed %jd -> %jd", file, (intmax_t) cmpsb.st_dev, (intmax_t) sb->st_dev); char msg_temp[CF_MAXVARSIZE]; snprintf(msg_temp, sizeof(msg_temp), "Device: %jd -> %jd", (uintmax_t)cmpsb.st_dev, (uintmax_t)sb->st_dev); FileChangesLogChange(file, FILE_STATE_STATS_CHANGED, msg_temp, pp); } if (cmpsb.st_ino != sb->st_ino) { Log(LOG_LEVEL_NOTICE, "inode for '%s' changed %ju -> %ju", file, (uintmax_t) cmpsb.st_ino, (uintmax_t) sb->st_ino); } if (cmpsb.st_mtime != sb->st_mtime) { char from[CF_MAXVARSIZE]; char to[CF_MAXVARSIZE]; strcpy(from, ctime(&(cmpsb.st_mtime))); strcpy(to, ctime(&(sb->st_mtime))); Chop(from, CF_MAXVARSIZE); Chop(to, CF_MAXVARSIZE); Log(LOG_LEVEL_NOTICE, "Last modified time for '%s' changed '%s' -> '%s'", file, from, to); char msg_temp[CF_MAXVARSIZE]; snprintf(msg_temp, sizeof(msg_temp), "Modified time: %s -> %s", from, to); FileChangesLogChange(file, FILE_STATE_STATS_CHANGED, msg_temp, pp); } if (pp->comment) { Log(LOG_LEVEL_NOTICE, "Preceding promise '%s'", pp->comment); } if (update && !DONTDO) { if (!DeleteDB(dbp, key) || !WriteDB(dbp, key, sb, sizeof(struct stat))) { Log(LOG_LEVEL_ERR, "Could not write stat information to database"); } } CloseDB(dbp); } static char FileStateToChar(FileState status) { switch(status) { case FILE_STATE_NEW: return 'N'; case FILE_STATE_REMOVED: return 'R'; case FILE_STATE_CONTENT_CHANGED: return 'C'; case FILE_STATE_STATS_CHANGED: return 'S'; default: ProgrammingError("Unhandled file status in switch: %d", status); } } void FileChangesLogChange(const char *file, FileState status, char *msg, const Promise *pp) { FILE *fp; char fname[CF_BUFSIZE]; time_t now = time(NULL); /* This is inefficient but we don't want to lose any data */ snprintf(fname, CF_BUFSIZE, "%s/state/%s", CFWORKDIR, CF_FILECHANGE_NEW); MapName(fname); #ifndef __MINGW32__ struct stat sb; if (stat(fname, &sb) != -1) { if (sb.st_mode & (S_IWGRP | S_IWOTH)) { Log(LOG_LEVEL_ERR, "File '%s' (owner %ju) was writable by others (security exception)", fname, (uintmax_t)sb.st_uid); } } #endif /* !__MINGW32__ */ fp = safe_fopen(fname, "a"); if (fp == NULL) { Log(LOG_LEVEL_ERR, "Could not write to the hash change log. (fopen: %s)", GetErrorStr()); return; } const char *handle = PromiseID(pp); fprintf(fp, "%lld,%s,%s,%c,%s\n", (long long) now, handle, file, FileStateToChar(status), msg); fclose(fp); safe_chmod(fname, 0600); } cfengine-3.6.2/cf-agent/files_editxml.h0000644000175100017510000000241212316547775017521 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_EDITXML_H #define CFENGINE_FILES_EDITXML_H int ScheduleEditXmlOperations(EvalContext *ctx, const Bundle *bp, Attributes a, const Promise *parentp, EditContext *edcontext); #ifdef HAVE_LIBXML2 int XmlCompareToFile(xmlDocPtr doc, char *file, EditDefaults edits); #endif #endif cfengine-3.6.2/cf-agent/verify_users_stub.c0000644000175100017510000000270012352022221020414 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include void VerifyOneUsersPromise (ARG_UNUSED const char *puser, ARG_UNUSED User u, ARG_UNUSED PromiseResult *result, ARG_UNUSED enum cfopaction action, ARG_UNUSED EvalContext *ctx, ARG_UNUSED const Attributes *a, ARG_UNUSED const Promise *pp) { Log(LOG_LEVEL_ERR, "Users promise type is not supported on this OS"); } cfengine-3.6.2/cf-agent/retcode.h0000644000175100017510000000227512332665147016315 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_RETCODE_H #define CFENGINE_RETCODE_H #include #include int VerifyCommandRetcode(EvalContext *ctx, int retcode, Attributes a, const Promise *pp, PromiseResult *result); #endif cfengine-3.6.2/cf-agent/vercmp.h0000644000175100017510000000305112352022221016133 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERCMP_H #define CFENGINE_VERCMP_H typedef enum { VERCMP_ERROR = -1, VERCMP_NO_MATCH = 0, VERCMP_MATCH = 1 } VersionCmpResult; /* * a, pp are used for * a.packages.package_select * a.packages.package_version_less_command * a.packages.package_version_equal_command * a.packages.package_commands_useshell * cfPS */ VersionCmpResult CompareVersions(EvalContext *ctx, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result); const char* PackageVersionComparatorToString(const PackageVersionComparator pvc); #endif cfengine-3.6.2/cf-agent/files_properties.h0000664000175100017510000000301212243421446020227 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_PROPERTIES_H #define CFENGINE_FILES_PROPERTIES_H #include #include /* AgentConnection */ void AddFilenameToListOfSuspicious(const char *filename); /* * Both functions assume that current working directory is #path, so #filename * can be stat'ed at relative path (if it is a local file). */ bool ConsiderLocalFile(const char *filename, const char *path); bool ConsiderAbstractFile(const char *nodename, const char *path, FileCopy fc, AgentConnection *conn); #endif cfengine-3.6.2/cf-agent/findhub_priv.h0000644000175100017510000000443712316547775017361 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FINDHUB_PRIV_H #define CFENGINE_FINDHUB_PRIV_H #include #include AvahiSimplePoll *spoll; typedef struct { char Hostname[4096]; char IPAddress[AVAHI_ADDRESS_STR_MAX]; uint16_t Port; } HostProperties; void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupFlags flags, void* userdata); void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata); void client_callback(AvahiClient *c, AvahiClientState state, void *userdata); #endif cfengine-3.6.2/cf-agent/load_avahi.h0000664000175100017510000000524612243421446016753 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LOAD_AVAHI_H #define CFENGINE_LOAD_AVAHI_H #include #include #include #include #include #include #include #include #include #include #include #include #include void (*avahi_simple_poll_quit_ptr)(AvahiSimplePoll *); char* (*avahi_address_snprint_ptr)(char *, size_t , const AvahiAddress *); int (*avahi_service_resolver_free_ptr)(AvahiServiceResolver *); int (*avahi_client_errno_ptr)(AvahiClient *); const char* (*avahi_strerror_ptr)(int); AvahiServiceResolver* (*avahi_service_resolver_new_ptr)(AvahiClient *, AvahiIfIndex, AvahiProtocol, const char *, const char *, const char *, AvahiProtocol, AvahiLookupFlags, AvahiServiceResolverCallback, void *); AvahiClient* (*avahi_service_browser_get_client_ptr)(AvahiServiceBrowser *); AvahiClient* (*avahi_service_resolver_get_client_ptr)(AvahiServiceResolver *); AvahiSimplePoll* (*avahi_simple_poll_new_ptr)(); const AvahiPoll* (*avahi_simple_poll_get_ptr)(AvahiSimplePoll *s); AvahiClient* (*avahi_client_new_ptr)(const AvahiPoll *, AvahiClientFlags, AvahiClientCallback, void *, int *); int (*avahi_simple_poll_loop_ptr)(AvahiSimplePoll *); int (*avahi_service_browser_free_ptr)(AvahiServiceBrowser *); void (*avahi_client_free_ptr)(AvahiClient *client); void (*avahi_simple_poll_free_ptr)(AvahiSimplePoll *); AvahiServiceBrowser* (*avahi_service_browser_new_ptr)(AvahiClient *, AvahiIfIndex, AvahiProtocol, const char *, const char *, AvahiLookupFlags, AvahiServiceBrowserCallback, void*); void *avahi_handle; int loadavahi(); #endif cfengine-3.6.2/cf-agent/acl_posix.c0000644000175100017510000007526212316547775016662 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_ACL_H # include #endif #ifdef HAVE_SYS_ACL_H # include #endif #ifdef HAVE_ACL_LIBACL_H # include #endif #ifdef HAVE_LIBACL static int CheckPosixLinuxAccessACEs(EvalContext *ctx, Rlist *aces, AclMethod method, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result); static int CheckPosixLinuxDefaultACEs(EvalContext *ctx, Rlist *aces, AclMethod method, AclDefault acl_default, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result); static int CheckPosixLinuxACEs(EvalContext *ctx, Rlist *aces, AclMethod method, const char *file_path, acl_type_t acl_type, Attributes a, const Promise *pp, PromiseResult *result); static int CheckDefaultEqualsAccessACL(EvalContext *ctx, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result); static int CheckDefaultClearACL(EvalContext *ctx, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result); static int ParseEntityPosixLinux(char **str, acl_entry_t ace, int *is_mask); static int ParseModePosixLinux(char *mode, acl_permset_t old_perms); static acl_entry_t FindACE(acl_t acl, acl_entry_t ace_find); static int ACLEquals(acl_t first, acl_t second); static int ACECount(acl_t acl); static int PermsetEquals(acl_permset_t first, acl_permset_t second); PromiseResult CheckPosixLinuxACL(EvalContext *ctx, const char *file_path, Acl acl, Attributes a, const Promise *pp) { PromiseResult result = PROMISE_RESULT_NOOP; if (!CheckPosixLinuxAccessACEs(ctx, acl.acl_entries, acl.acl_method, file_path, a, pp, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed checking access ACL on %s", file_path); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; } if (IsDir(file_path)) { if (!CheckPosixLinuxDefaultACEs(ctx, acl.acl_default_entries, acl.acl_method, acl.acl_default, file_path, a, pp, &result)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed checking default ACL on '%s'", file_path); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; } } return PROMISE_RESULT_NOOP; } static int CheckPosixLinuxAccessACEs(EvalContext *ctx, Rlist *aces, AclMethod method, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result) { return CheckPosixLinuxACEs(ctx, aces, method, file_path, ACL_TYPE_ACCESS, a, pp, result); } static int CheckPosixLinuxDefaultACEs(EvalContext *ctx, Rlist *aces, AclMethod method, AclDefault acl_default, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result) { int retval; switch (acl_default) { case ACL_DEFAULT_NO_CHANGE: // no change always succeeds retval = true; break; case ACL_DEFAULT_SPECIFY: // default ALC is specified in promise retval = CheckPosixLinuxACEs(ctx, aces, method, file_path, ACL_TYPE_DEFAULT, a, pp, result); break; case ACL_DEFAULT_ACCESS: // default ACL should be the same as access ACL retval = CheckDefaultEqualsAccessACL(ctx, file_path, a, pp, result); break; case ACL_DEFAULT_CLEAR: // default ALC should be empty retval = CheckDefaultClearACL(ctx, file_path, a, pp, result); break; default: // unknown inheritance policy Log(LOG_LEVEL_ERR, "Unknown inheritance policy - shouldn't happen"); retval = false; break; } return retval; } /* Takes as input CFEngine-syntax ACEs and a path to a file. Checks if the CFEngine-syntax ACL translates to the POSIX Linux ACL set on the given file. If it doesn't, the ACL on the file is updated. */ static int CheckPosixLinuxACEs(EvalContext *ctx, Rlist *aces, AclMethod method, const char *file_path, acl_type_t acl_type, Attributes a, const Promise *pp, PromiseResult *result) { acl_t acl_existing; acl_t acl_new; acl_t acl_tmp; acl_entry_t ace_parsed; acl_entry_t ace_current; acl_permset_t perms; char *cf_ace; int retv; int has_mask; Rlist *rp; char *acl_type_str; acl_new = NULL; acl_existing = NULL; acl_tmp = NULL; has_mask = false; acl_type_str = acl_type == ACL_TYPE_ACCESS ? "Access" : "Default"; // read existing acl if ((acl_existing = acl_get_file(file_path, acl_type)) == NULL) { Log(LOG_LEVEL_VERBOSE, "No ACL for '%s' could be read. (acl_get_file: %s)", file_path, GetErrorStr()); return false; } // allocate memory for temp ace (it needs to reside in a temp acl) if ((acl_tmp = acl_init(1)) == NULL) { Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_init: %s)", GetErrorStr()); acl_free((void *) acl_existing); return false; } if (acl_create_entry(&acl_tmp, &ace_parsed) != 0) { Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_create_entry: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); return false; } // copy existing aces if we are appending if (method == ACL_METHOD_APPEND) { if ((acl_new = acl_dup(acl_existing)) == NULL) { Log(LOG_LEVEL_ERR, "Error copying existing ACL (acl_dup: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); return false; } } else // overwrite existing acl { if ((acl_new = acl_init(5)) == NULL) // TODO: Always OK with 5 here ? { Log(LOG_LEVEL_ERR, "New ACL could not be allocated (acl_init: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); return false; } } for (rp = aces; rp != NULL; rp = rp->next) { cf_ace = RlistScalarValue(rp); if (!ParseEntityPosixLinux(&cf_ace, ace_parsed, &has_mask)) { Log(LOG_LEVEL_ERR, "Error parsing entity in 'cf_ace'."); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } // check if an ACE with this entity-type and id already exist in the Posix Linux ACL ace_current = FindACE(acl_new, ace_parsed); // create new entry in ACL if it did not exist if (ace_current == NULL) { if (acl_create_entry(&acl_new, &ace_current) != 0) { Log(LOG_LEVEL_ERR, "Failed to allocate ace (acl_create_entry: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } // copy parsed entity-type and id if (acl_copy_entry(ace_current, ace_parsed) != 0) { Log(LOG_LEVEL_ERR, "Error copying Linux entry in 'cf_ace' (acl_copy_entry: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } // clear ace_current's permissions to avoid ace_parsed from last // loop iteration to be taken into account when applying mode below if ((acl_get_permset(ace_current, &perms) != 0)) { Log(LOG_LEVEL_ERR, "Error obtaining permset for 'ace_current' (acl_get_permset: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } if (acl_clear_perms(perms) != 0) { Log(LOG_LEVEL_ERR, "Error clearing permset for 'ace_current'. (acl_clear_perms: %s)", GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } } // mode string should be prefixed with an entry seperator if (*cf_ace != ':') { Log(LOG_LEVEL_ERR, "No separator before mode-string in 'cf_ace'"); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } cf_ace += 1; if (acl_get_permset(ace_current, &perms) != 0) { Log(LOG_LEVEL_ERR, "Error obtaining permset for 'cf_ace'"); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } if (!ParseModePosixLinux(cf_ace, perms)) { Log(LOG_LEVEL_ERR, "Error parsing mode-string in 'cf_ace'"); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } // only allow permissions exist on posix acls, so we do // not check what follows next } // if no mask exists, calculate one (or both?): run acl_calc_mask and add one if (!has_mask) { if (acl_calc_mask(&acl_new) != 0) { Log(LOG_LEVEL_ERR, "Error calculating new acl mask"); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } } if ((retv = ACLEquals(acl_existing, acl_new)) == -1) { Log(LOG_LEVEL_ERR, "Error while comparing existing and new ACL, unable to repair."); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } if (retv == 1) // existing and new acl differ, update existing { switch (a.transaction.action) { case cfa_warn: cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "%s ACL on file '%s' needs to be updated", acl_type_str, file_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); break; case cfa_fix: if (!DONTDO) { if ((retv = acl_set_file(file_path, acl_type, acl_new)) != 0) { Log(LOG_LEVEL_ERR, "Error setting new %s ACL on file '%s' (acl_set_file: %s), are required ACEs present ?", acl_type_str, file_path, GetErrorStr()); acl_free((void *) acl_existing); acl_free((void *) acl_tmp); acl_free((void *) acl_new); return false; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "%s ACL on '%s' successfully changed.", acl_type_str, file_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); break; default: ProgrammingError("CFEngine: internal error: illegal file action"); } } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "'%s' ACL on '%s' needs no modification.", acl_type_str, file_path); } acl_free((void *) acl_existing); acl_free((void *) acl_new); acl_free((void *) acl_tmp); return true; } /* Checks if the default ACL of the given file is the same as the access ACL. If not, the default ACL is set in this way. Returns 0 on success and -1 on failure. */ static int CheckDefaultEqualsAccessACL(EvalContext *ctx, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result) { acl_t acl_access; acl_t acl_default; int equals; int retval = false; acl_access = NULL; acl_default = NULL; if ((acl_access = acl_get_file(file_path, ACL_TYPE_ACCESS)) == NULL) { Log(LOG_LEVEL_ERR, "Could not find an ACL for '%s'. (acl_get_file: %s)", file_path, GetErrorStr()); return false; } acl_default = acl_get_file(file_path, ACL_TYPE_DEFAULT); if (acl_default == NULL) { Log(LOG_LEVEL_ERR, "Could not find default ACL for '%s'. (acl_get_file: %s)", file_path, GetErrorStr()); acl_free(acl_access); return false; } equals = ACLEquals(acl_access, acl_default); switch (equals) { case 0: // they equal, as desired cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Default ACL on '%s' needs no modification.", file_path); retval = true; break; case 1: // set access ACL as default ACL switch (a.transaction.action) { case cfa_warn: cfPS(ctx, LOG_LEVEL_WARNING, PROMISE_RESULT_WARN, pp, a, "Default ACL on '%s' needs to be copied from access ACL.", file_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); break; case cfa_fix: if (!DONTDO) { if ((acl_set_file(file_path, ACL_TYPE_DEFAULT, acl_access)) != 0) { Log(LOG_LEVEL_ERR, "Could not set default ACL to access"); acl_free(acl_access); acl_free(acl_default); return false; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Default ACL on '%s' successfully copied from access ACL.", file_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); retval = true; break; default: ProgrammingError("CFEngine: internal error: illegal file action"); retval = false; } break; default: retval = false; Log(LOG_LEVEL_ERR, "Unable to compare access and default ACEs"); } acl_free(acl_access); acl_free(acl_default); return retval; } /* Checks if the default ACL is empty. If not, it is cleared. */ int CheckDefaultClearACL(EvalContext *ctx, const char *file_path, Attributes a, const Promise *pp, PromiseResult *result) { acl_t acl_existing; acl_t acl_empty; acl_entry_t ace_dummy; int retv; int retval = false; acl_existing = NULL; acl_empty = NULL; if ((acl_existing = acl_get_file(file_path, ACL_TYPE_DEFAULT)) == NULL) { Log(LOG_LEVEL_ERR, "Unable to read default acl for '%s'. (acl_get_file: %s)", file_path, GetErrorStr()); return false; } retv = acl_get_entry(acl_existing, ACL_FIRST_ENTRY, &ace_dummy); switch (retv) { case -1: Log(LOG_LEVEL_VERBOSE, "Couldn't retrieve ACE for '%s'. (acl_get_entry: %s)", file_path, GetErrorStr()); retval = false; break; case 0: // no entries, as desired cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Default ACL on '%s' needs no modification.", file_path); retval = true; break; case 1: // entries exist, set empty ACL if ((acl_empty = acl_init(0)) == NULL) { Log(LOG_LEVEL_ERR, "Could not reinitialize ACL for '%s'. (acl_init: %s)", file_path, GetErrorStr()); retval = false; break; } switch (a.transaction.action) { case cfa_warn: cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Default ACL on '%s' needs to be cleared", file_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); break; case cfa_fix: if (!DONTDO) { if (acl_set_file(file_path, ACL_TYPE_DEFAULT, acl_empty) != 0) { Log(LOG_LEVEL_ERR, "Could not reset ACL for %s", file_path); retval = false; break; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Default ACL on '%s' successfully cleared", file_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); retval = true; break; default: ProgrammingError("CFEngine: internal error: illegal file action"); retval = false; } break; default: retval = false; } acl_free(acl_empty); acl_free(acl_existing); return retval; } /* Walks through the acl given as the first parameter, looking for an ACE that has the same entity type and id as the ace in the second parameter. If a match is found, then the matching ace is returned. Else, NULL is returned. */ static acl_entry_t FindACE(acl_t acl, acl_entry_t ace_find) { acl_entry_t ace_curr; acl_tag_t tag_curr; acl_tag_t tag_find; id_t *id_curr; id_t *id_find; int more_aces; int retv_tag; id_find = NULL; more_aces = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace_curr); if (more_aces == -1) { Log(LOG_LEVEL_ERR, "Error reading acl. (acl_get_entry: %s)", GetErrorStr()); return NULL; } else if (more_aces == 0) { return NULL; } /* find the tag type and id we are looking for */ if (acl_get_tag_type(ace_find, &tag_find) != 0) { Log(LOG_LEVEL_ERR, "Error reading tag type. (acl_get_tag_type: %s)", GetErrorStr()); return NULL; } if (tag_find == ACL_USER || tag_find == ACL_GROUP) { id_find = acl_get_qualifier(ace_find); if (id_find == NULL) { Log(LOG_LEVEL_ERR, "Error reading tag type. (acl_get_qualifier: %s)", GetErrorStr()); return NULL; } } /* check if any of the aces match */ while (more_aces) { if ((retv_tag = acl_get_tag_type(ace_curr, &tag_curr)) != 0) { Log(LOG_LEVEL_ERR, "Unable to get tag type. (acl_get_tag_type: %s)", GetErrorStr()); acl_free(id_find); return NULL; } if (tag_curr == tag_find) { if (id_find == NULL) { return ace_curr; } id_curr = acl_get_qualifier(ace_curr); if (id_curr == NULL) { Log(LOG_LEVEL_ERR, "Couldn't extract qualifier. (acl_get_qualifier: %s)", GetErrorStr()); return NULL; } if (*id_curr == *id_find) { acl_free(id_find); acl_free(id_curr); return ace_curr; } acl_free(id_curr); } more_aces = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace_curr); } if (id_find != NULL) { acl_free(id_find); } return NULL; } /* Checks if the two ACLs contain equal ACEs and equally many. Does not assume that the ACEs lie in the same order. Returns 0 if so, and 1 if they differ, and -1 on error. */ static int ACLEquals(acl_t first, acl_t second) { acl_entry_t ace_first; acl_entry_t ace_second; acl_permset_t perms_first; acl_permset_t perms_second; int first_cnt; int second_cnt; int more_aces; int retv_perms; if ((first_cnt = ACECount(first)) == -1) { Log(LOG_LEVEL_VERBOSE, "Couldn't count ACEs"); return -1; } if ((second_cnt = ACECount(second)) == -1) { Log(LOG_LEVEL_VERBOSE, "Couldn't count ACEs"); return -1; } if (first_cnt != second_cnt) { return 1; } if (first_cnt == 0) { return 0; } // check that every ace of first acl exist in second acl more_aces = acl_get_entry(first, ACL_FIRST_ENTRY, &ace_first); if (more_aces != 1) // first must contain at least one entry { Log(LOG_LEVEL_ERR, "Unable to read ACE. (acl_get_entry: %s)", GetErrorStr()); return -1; } while (more_aces) { /* no ace in second match entity-type and id of first */ if ((ace_second = FindACE(second, ace_first)) == NULL) { return 1; } /* permissions must also match */ if (acl_get_permset(ace_first, &perms_first) != 0) { Log(LOG_LEVEL_ERR, "Unable to read permissions. (acl_get_permset: %s)", GetErrorStr()); return -1; } if (acl_get_permset(ace_second, &perms_second) != 0) { Log(LOG_LEVEL_ERR, "Unable to read permissions. (acl_get_permset: %s)", GetErrorStr()); return -1; } retv_perms = PermsetEquals(perms_first, perms_second); if (retv_perms == -1) { return -1; } else if (retv_perms == 1) // permissions differ { return 1; } more_aces = acl_get_entry(first, ACL_NEXT_ENTRY, &ace_first); } return 0; } static int ACECount(acl_t acl) { int more_aces; int count; acl_entry_t ace; count = 0; more_aces = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace); if (more_aces <= 0) { return more_aces; } while (more_aces) { more_aces = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace); count++; } return count; } static int PermsetEquals(acl_permset_t first, acl_permset_t second) { acl_perm_t perms_avail[3] = { ACL_READ, ACL_WRITE, ACL_EXECUTE }; int first_set; int second_set; int i; for (i = 0; i < 3; i++) { first_set = acl_get_perm(first, perms_avail[i]); if (first_set == -1) { return -1; } second_set = acl_get_perm(second, perms_avail[i]); if (second_set == -1) { return -1; } if (first_set != second_set) { return 1; } } return 0; } /* Takes a ':' or null-terminated string "entity-type:id", and converts and stores these into a Posix Linux ace data structure (with unset permissions). Sets is_mask to true if this is a mask entry. */ static int ParseEntityPosixLinux(char **str, acl_entry_t ace, int *is_mask) { struct passwd *pwd; struct group *grp; acl_tag_t etype; size_t idsz; id_t id; char *ids; char *id_end; int result = true; int i; ids = NULL; // TODO: Support numeric id in addition to (user/group) name ? // Posix language: tag type, qualifier, permissions if (strncmp(*str, "user:", 5) == 0) { *str += 5; // create null-terminated string for entity id id_end = index(*str, ':'); if (id_end == NULL) // entity id already null-terminated { idsz = strlen(*str); } else // copy entity-id to new null-terminated string { idsz = id_end - *str; } ids = xmalloc(idsz + 1); for (i = 0; i < idsz; i++) ids[i] = (*str)[i]; ids[idsz] = '\0'; *str += idsz; // file object owner if (strncmp(ids, "*", 2) == 0) { etype = ACL_USER_OBJ; id = 0; } else { etype = ACL_USER; pwd = getpwnam(ids); if (pwd == NULL) { Log(LOG_LEVEL_ERR, "Couldn't find user id for '%s'. (getpwnnam: %s)", ids, GetErrorStr()); free(ids); return false; } id = pwd->pw_uid; } } else if (strncmp(*str, "group:", 6) == 0) { *str += 6; // create null-terminated string for entity id id_end = index(*str, ':'); if (id_end == NULL) // entity id already null-terminated { idsz = strlen(*str); } else // copy entity-id to new null-terminated string { idsz = id_end - *str; } ids = xmalloc(idsz + 1); for (i = 0; i < idsz; i++) ids[i] = (*str)[i]; ids[idsz] = '\0'; *str += idsz; // file group if (strncmp(ids, "*", 2) == 0) { etype = ACL_GROUP_OBJ; id = 0; // TODO: Correct file group id ?? } else { etype = ACL_GROUP; grp = getgrnam(ids); if (grp == NULL) { Log(LOG_LEVEL_ERR, "Error looking up group id for %s", ids); free(ids); return false; } id = grp->gr_gid; } } else if (strncmp(*str, "all:", 4) == 0) { *str += 3; etype = ACL_OTHER; } else if (strncmp(*str, "mask:", 5) == 0) { *str += 4; etype = ACL_MASK; *is_mask = true; } else { Log(LOG_LEVEL_ERR, "ace does not start with user:/group:/all:/mask:"); return false; } if (acl_set_tag_type(ace, etype) != 0) { Log(LOG_LEVEL_ERR, "Could not set ACE tag type. (acl_set_tag_type: %s)", GetErrorStr()); result = false; } else if (etype == ACL_USER || etype == ACL_GROUP) { if ((acl_set_qualifier(ace, &id)) != 0) { Log(LOG_LEVEL_ERR, "Could not set ACE qualifier. (acl_set_qualifier: %s)", GetErrorStr()); result = false; } } if (ids != NULL) { free(ids); } return result; } /* Takes a CFEngine-syntax mode string and existing Posix Linux-formatted permissions on the file system object as arguments. The mode-string will be applied on the permissions. Returns true on success, false otherwise. */ static int ParseModePosixLinux(char *mode, acl_permset_t perms) { int retv; int more_entries; acl_perm_t perm; enum { add, del } op; op = add; if (*mode == '\0' || *mode == ':') { if (acl_clear_perms(perms) != 0) { Log(LOG_LEVEL_ERR, "Error clearing perms. (acl_clear_perms: %s)", GetErrorStr()); return false; } else { return true; } } more_entries = true; while (more_entries) { switch (*mode) { case '+': op = add; mode++; break; case '-': op = del; mode++; break; case '=': mode++; // fallthrough default: // if mode does not start with + or -, we clear existing perms op = add; if (acl_clear_perms(perms) != 0) { Log(LOG_LEVEL_ERR, "Unable to clear ACL permissions. (acl_clear_perms: %s)", GetErrorStr()); return false; } } // parse generic perms (they are 1-1 on Posix) while (*mode != '\0' && strchr(CF_VALID_GPERMS, *mode)) { if (*mode == '\0') { break; } switch (*mode) { case 'r': perm = ACL_READ; break; case 'w': perm = ACL_WRITE; break; case 'x': perm = ACL_EXECUTE; break; default: Log(LOG_LEVEL_ERR, "No linux support for generic permission flag '%c'", *mode); return false; } if (op == add) { retv = acl_add_perm(perms, perm); } else { retv = acl_delete_perm(perms, perm); } if (retv != 0) { Log(LOG_LEVEL_ERR, "Could not change ACE permission. (acl_[add|delete]_perms: %s)", GetErrorStr()); return false; } mode++; } // parse native perms if (*mode == CF_NATIVE_PERMS_SEP_START) { mode++; while (*mode != '\0' && strchr(CF_VALID_NPERMS_POSIX, *mode)) { switch (*mode) { case 'r': perm = ACL_READ; break; case 'w': perm = ACL_WRITE; break; case 'x': perm = ACL_EXECUTE; break; default: Log(LOG_LEVEL_ERR, "No linux support for native permission flag '%c'", *mode); return false; } if (op == add) { retv = acl_add_perm(perms, perm); } else { retv = acl_delete_perm(perms, perm); } if (retv != 0) { Log(LOG_LEVEL_ERR, "Could not change ACE permission. (acl_[add|delete]_perm: %s)", GetErrorStr()); return false; } mode++; } // scan past native perms end seperator mode++; } if (*mode == ',') { more_entries = true; mode++; } else { more_entries = false; } } return true; } #else /* !HAVE_LIBACL */ PromiseResult CheckPosixLinuxACL(EvalContext *ctx, ARG_UNUSED const char *file_path, ARG_UNUSED Acl acl, Attributes a, const Promise *pp) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Posix ACLs are not supported on this Linux system - install the Posix acl library"); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; } #endif cfengine-3.6.2/cf-agent/verify_packages.h0000644000175100017510000000344512316547775020042 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_PACKAGES_H #define CFENGINE_VERIFY_PACKAGES_H #include #include PromiseResult VerifyPackagesPromise(EvalContext *ctx, const Promise *pp); void ExecuteScheduledPackages(EvalContext *ctx); void CleanScheduledPackages(void); int PrependPackageItem(EvalContext *ctx, PackageItem **list, const char *name, const char *version, const char *arch, const Promise *pp); // For testing. VersionCmpResult ComparePackages(EvalContext *ctx, const char *n, const char *v, const char *arch, PackageItem *pi, Attributes a, const Promise *pp, const char *mode, PromiseResult *result); #endif cfengine-3.6.2/cf-agent/Makefile.in0000664000175100017510000010243312412324463016553 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @NT_FALSE@am__append_1 = nfs.c nfs.h @HAVE_USERS_PROMISE_DEPS_TRUE@@NT_FALSE@am__append_2 = verify_users_pam.c @HAVE_USERS_PROMISE_DEPS_FALSE@@NT_FALSE@am__append_3 = verify_users_stub.c @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@am__append_4 = \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ findhub.c findhub_priv.h findhub.h \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ load_avahi.c load_avahi.h @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-agent$(EXEEXT) subdir = cf-agent DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libcf_agent_la_DEPENDENCIES = ../libpromises/libpromises.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am__libcf_agent_la_SOURCES_DIST = agent-diagnostics.c \ agent-diagnostics.h tokyo_check.c tokyo_check.h abstract_dir.c \ abstract_dir.h cf-agent.c cf-agent-enterprise-stubs.c \ cf-agent-enterprise-stubs.h comparray.c comparray.h \ acl_posix.c acl_posix.h cf_sql.c cf_sql.h files_changes.c \ files_changes.h promiser_regex_resolver.c \ promiser_regex_resolver.h match_scope.c match_scope.h \ retcode.c retcode.h verify_acl.c verify_acl.h verify_files.c \ verify_files.h verify_files_utils.c verify_files_utils.h \ verify_files_hashes.c verify_files_hashes.h verify_storage.c \ verify_storage.h verify_exec.c verify_exec.h verify_methods.c \ verify_methods.h verify_databases.c verify_databases.h \ verify_processes.c verify_processes.h verify_services.c \ verify_services.h verify_environments.c verify_environments.h \ files_edit.c files_edit.h files_editline.c files_editline.h \ files_editxml.c files_editxml.h files_links.c files_links.h \ files_operators.c files_operators.h files_properties.c \ files_properties.h files_repository.c files_repository.h \ files_select.c files_select.h vercmp_internal.c \ vercmp_internal.h vercmp.c vercmp.h verify_packages.c \ verify_packages.h verify_users.c verify_users.h \ cf-agent-windows-functions.h nfs.c nfs.h verify_users_pam.c \ verify_users_stub.c findhub.c findhub_priv.h findhub.h \ load_avahi.c load_avahi.h @NT_FALSE@am__objects_1 = nfs.lo @HAVE_USERS_PROMISE_DEPS_TRUE@@NT_FALSE@am__objects_2 = \ @HAVE_USERS_PROMISE_DEPS_TRUE@@NT_FALSE@ verify_users_pam.lo @HAVE_USERS_PROMISE_DEPS_FALSE@@NT_FALSE@am__objects_3 = \ @HAVE_USERS_PROMISE_DEPS_FALSE@@NT_FALSE@ verify_users_stub.lo @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@am__objects_4 = \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ findhub.lo \ @HAVE_AVAHI_CLIENT_TRUE@@HAVE_AVAHI_COMMON_TRUE@ load_avahi.lo am_libcf_agent_la_OBJECTS = agent-diagnostics.lo tokyo_check.lo \ abstract_dir.lo cf-agent.lo cf-agent-enterprise-stubs.lo \ comparray.lo acl_posix.lo cf_sql.lo files_changes.lo \ promiser_regex_resolver.lo match_scope.lo retcode.lo \ verify_acl.lo verify_files.lo verify_files_utils.lo \ verify_files_hashes.lo verify_storage.lo verify_exec.lo \ verify_methods.lo verify_databases.lo verify_processes.lo \ verify_services.lo verify_environments.lo files_edit.lo \ files_editline.lo files_editxml.lo files_links.lo \ files_operators.lo files_properties.lo files_repository.lo \ files_select.lo vercmp_internal.lo vercmp.lo \ verify_packages.lo verify_users.lo $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) libcf_agent_la_OBJECTS = $(am_libcf_agent_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) cf_agent_SOURCES = cf-agent.c cf_agent_OBJECTS = cf_agent-cf-agent.$(OBJEXT) @BUILTIN_EXTENSIONS_FALSE@cf_agent_DEPENDENCIES = libcf-agent.la cf_agent_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(cf_agent_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_agent_la_SOURCES) cf-agent.c DIST_SOURCES = $(am__libcf_agent_la_SOURCES_DIST) cf-agent.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-agent.la AM_CPPFLAGS = -I$(srcdir)/../libpromises -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ $(ENTERPRISE_CPPFLAGS) \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(LIBVIRT_CPPFLAGS) \ $(POSTGRESQL_CPPFLAGS) \ $(MYSQL_CPPFLAGS) \ $(LIBXML2_CPPFLAGS) \ $(PAM_CPPFLAGS) AM_CFLAGS = \ $(ENTERPRISE_CFLAGS) \ $(OPENSSL_CFLAGS) \ $(PCRE_CFLAGS) \ $(LIBVIRT_CFLAGS) \ $(POSTGRESQL_CFLAGS) \ $(MYSQL_CFLAGS) \ $(LIBXML2_CFLAGS) \ $(PAM_CFLAGS) AM_LDFLAGS = \ $(OPENSSL_LDFLAGS) \ $(PCRE_LDFLAGS) \ $(LIBVIRT_LDFLAGS) \ $(POSTGRESQL_LDFLAGS) \ $(MYSQL_LDFLAGS) \ $(LIBXML2_LDFLAGS) \ $(PAM_LDFLAGS) libcf_agent_la_LIBADD = ../libpromises/libpromises.la \ $(OPENSSL_LIBS) \ $(PCRE_LIBS) \ $(LIBVIRT_LIBS) \ $(POSTGRESQL_LIBS) \ $(MYSQL_LIBS) \ $(LIBXML2_LIBS) \ $(PAM_LIBS) libcf_agent_la_SOURCES = agent-diagnostics.c agent-diagnostics.h \ tokyo_check.c tokyo_check.h abstract_dir.c abstract_dir.h \ cf-agent.c cf-agent-enterprise-stubs.c \ cf-agent-enterprise-stubs.h comparray.c comparray.h \ acl_posix.c acl_posix.h cf_sql.c cf_sql.h files_changes.c \ files_changes.h promiser_regex_resolver.c \ promiser_regex_resolver.h match_scope.c match_scope.h \ retcode.c retcode.h verify_acl.c verify_acl.h verify_files.c \ verify_files.h verify_files_utils.c verify_files_utils.h \ verify_files_hashes.c verify_files_hashes.h verify_storage.c \ verify_storage.h verify_exec.c verify_exec.h verify_methods.c \ verify_methods.h verify_databases.c verify_databases.h \ verify_processes.c verify_processes.h verify_services.c \ verify_services.h verify_environments.c verify_environments.h \ files_edit.c files_edit.h files_editline.c files_editline.h \ files_editxml.c files_editxml.h files_links.c files_links.h \ files_operators.c files_operators.h files_properties.c \ files_properties.h files_repository.c files_repository.h \ files_select.c files_select.h vercmp_internal.c \ vercmp_internal.h vercmp.c vercmp.h verify_packages.c \ verify_packages.h verify_users.c verify_users.h \ cf-agent-windows-functions.h $(am__append_1) $(am__append_2) \ $(am__append_3) $(am__append_4) @BUILTIN_EXTENSIONS_FALSE@cf_agent_CFLAGS = $(AM_CFLAGS) @BUILTIN_EXTENSIONS_FALSE@cf_agent_LDADD = libcf-agent.la CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-agent/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-agent/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-agent.la: $(libcf_agent_la_OBJECTS) $(libcf_agent_la_DEPENDENCIES) $(EXTRA_libcf_agent_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_agent_la_OBJECTS) $(libcf_agent_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-agent$(EXEEXT): $(cf_agent_OBJECTS) $(cf_agent_DEPENDENCIES) $(EXTRA_cf_agent_DEPENDENCIES) @rm -f cf-agent$(EXEEXT) $(AM_V_CCLD)$(cf_agent_LINK) $(cf_agent_OBJECTS) $(cf_agent_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/abstract_dir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl_posix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agent-diagnostics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-agent-enterprise-stubs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-agent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_agent-cf-agent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_sql.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comparray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_changes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_edit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_editline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_editxml.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_links.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_operators.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_properties.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_repository.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/files_select.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/findhub.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_avahi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_scope.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/promiser_regex_resolver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retcode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokyo_check.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vercmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vercmp_internal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_acl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_databases.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_environments.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_exec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_files.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_files_hashes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_files_utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_methods.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_packages.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_processes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_services.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_users.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_users_pam.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_users_stub.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< cf_agent-cf-agent.o: cf-agent.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_agent_CFLAGS) $(CFLAGS) -MT cf_agent-cf-agent.o -MD -MP -MF $(DEPDIR)/cf_agent-cf-agent.Tpo -c -o cf_agent-cf-agent.o `test -f 'cf-agent.c' || echo '$(srcdir)/'`cf-agent.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_agent-cf-agent.Tpo $(DEPDIR)/cf_agent-cf-agent.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-agent.c' object='cf_agent-cf-agent.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_agent_CFLAGS) $(CFLAGS) -c -o cf_agent-cf-agent.o `test -f 'cf-agent.c' || echo '$(srcdir)/'`cf-agent.c cf_agent-cf-agent.obj: cf-agent.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_agent_CFLAGS) $(CFLAGS) -MT cf_agent-cf-agent.obj -MD -MP -MF $(DEPDIR)/cf_agent-cf-agent.Tpo -c -o cf_agent-cf-agent.obj `if test -f 'cf-agent.c'; then $(CYGPATH_W) 'cf-agent.c'; else $(CYGPATH_W) '$(srcdir)/cf-agent.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_agent-cf-agent.Tpo $(DEPDIR)/cf_agent-cf-agent.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-agent.c' object='cf_agent-cf-agent.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_agent_CFLAGS) $(CFLAGS) -c -o cf_agent-cf-agent.obj `if test -f 'cf-agent.c'; then $(CYGPATH_W) 'cf-agent.c'; else $(CYGPATH_W) '$(srcdir)/cf-agent.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS @BUILTIN_EXTENSIONS_FALSE@ # Workaround for automake madness (try removing it if you want to know why). @BUILTIN_EXTENSIONS_FALSE@ # Build both a libcf-agent.la library, and a cf-agent executable # 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: cfengine-3.6.2/cf-agent/cf_sql.h0000664000175100017510000000325712411001073016116 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SQL_H #define CFENGINE_SQL_H #include typedef struct { int connected; int result; int row; unsigned int maxcolumns; unsigned int maxrows; int column; char **rowdata; char *blank; DatabaseType type; void *data; /* Generic pointer to RDBMS-specific data */ } CfdbConn; int CfConnectDB(CfdbConn *cfdb, DatabaseType dbtype, char *remotehost, char *dbuser, char *passwd, char *db); void CfCloseDB(CfdbConn *cfdb); void CfVoidQueryDB(CfdbConn *cfdb, char *query); void CfNewQueryDB(CfdbConn *cfdb, char *query); char **CfFetchRow(CfdbConn *cfdb); char *CfFetchColumn(CfdbConn *cfdb, int col); void CfDeleteQuery(CfdbConn *cfdb); #endif cfengine-3.6.2/cf-agent/verify_users_pam.c0000664000175100017510000012363112400110676020233 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SHADOW_H # include #endif #define CFUSR_CHECKBIT(v,p) ((v) & (1UL << (p))) #define CFUSR_SETBIT(v,p) ((v) |= ((1UL) << (p))) #define CFUSR_CLEARBIT(v,p) ((v) &= ~((1UL) << (p))) typedef enum { i_uid, i_password, i_comment, i_group, i_groups, i_home, i_shell, i_locked } which; static bool SupportsOption(const char *cmd, const char *option); static const char *GetPlatformSpecificExpirationDate() { // 2nd January 1970. #if defined(_AIX) return "0102000070"; #elif defined(__hpux) || defined(__SVR4) return "02/01/70"; #elif defined(__NetBSD__) return "January 02 1970"; #elif defined(__linux__) return "1970-01-02"; #else # error Your operating system lacks the proper string for the "usermod -e" utility. #endif } static int PasswordSupplier(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { // All allocations here will be freed by the pam framework. *resp = xmalloc(num_msg * sizeof(struct pam_response)); for (int i = 0; i < num_msg; i++) { if ((*msg)[i].msg_style == PAM_PROMPT_ECHO_OFF) { (*resp)[i].resp = xstrdup((const char *)appdata_ptr); } else { (*resp)[i].resp = xstrdup(""); } (*resp)[i].resp_retcode = 0; } return PAM_SUCCESS; } #ifdef _AIX /* * Format of passwd file on AIX is: * * user1: * password = hash * lastupdate = 12783612 * user2: * password = hash * lastupdate = 12783612 * <...> */ static bool GetAIXShadowHash(const char *puser, const char **result) { FILE *fptr = fopen("/etc/security/passwd", "r"); if (fptr == NULL) { return false; } // Not super pretty with a static variable, but it is how POSIX functions // getspnam() and friends do it. static char hash_buf[CF_BUFSIZE]; bool ret = false; char *buf = NULL; size_t bufsize = 0; size_t puser_len = strlen(puser); char name_regex_str[strlen(puser) + 3]; pcre *name_regex = CompileRegex("^(\\S+):"); pcre *hash_regex = CompileRegex("^\\s+password\\s*=\\s*(\\S+)"); bool in_user_section = false; while (true) { ssize_t read_result = CfReadLine(&buf, &bufsize, fptr); if (read_result < 0) { if (feof(fptr)) { errno = 0; } goto end; } int submatch_vec[6]; int pcre_result = pcre_exec(name_regex, NULL, buf, strlen(buf), 0, 0, submatch_vec, 6); if (pcre_result >= 0) { if (submatch_vec[3] - submatch_vec[2] == puser_len && strncmp(buf + submatch_vec[2], puser, puser_len) == 0) { in_user_section = true; } else { in_user_section = false; } continue; } else if (pcre_result != PCRE_ERROR_NOMATCH) { errno = EINVAL; goto end; } if (!in_user_section) { continue; } pcre_result = pcre_exec(hash_regex, NULL, buf, strlen(buf), 0, 0, submatch_vec, 6); if (pcre_result >= 0) { memcpy(hash_buf, buf + submatch_vec[2], submatch_vec[3] - submatch_vec[2]); *result = hash_buf; ret = true; goto end; } else if (pcre_result != PCRE_ERROR_NOMATCH) { errno = EINVAL; goto end; } } end: pcre_free(name_regex); pcre_free(hash_regex); free(buf); fclose(fptr); return ret; } #endif // _AIX #if HAVE_FGETSPENT // Uses fgetspent() instead of getspnam(), to guarantee that the returned user // is a local user, and not for example from LDAP. static struct spwd *GetSpEntry(const char *puser) { FILE *fptr = fopen("/etc/shadow", "r"); if (!fptr) { Log(LOG_LEVEL_ERR, "Could not open '/etc/shadow': %s", GetErrorStr()); return NULL; } struct spwd *spwd_info; bool found = false; while ((spwd_info = fgetspent(fptr))) { if (strcmp(puser, spwd_info->sp_namp) == 0) { found = true; break; } } fclose(fptr); if (found) { return spwd_info; } else { // Failure to find the user means we just set errno to zero. // Perhaps not optimal, but we cannot pass ENOENT, because the fopen might // fail for this reason, and that should not be treated the same. errno = 0; return NULL; } } #endif // HAVE_FGETSPENT static bool GetPasswordHash(const char *puser, const struct passwd *passwd_info, const char **result) { // Silence warning. (void)puser; // If the hash is very short, it's probably a stub. Try getting the shadow password instead. if (strlen(passwd_info->pw_passwd) <= 4) { #ifdef HAVE_FGETSPENT Log(LOG_LEVEL_VERBOSE, "Getting user '%s' password hash from shadow database.", puser); struct spwd *spwd_info; errno = 0; spwd_info = GetSpEntry(puser); if (!spwd_info) { if (errno) { Log(LOG_LEVEL_ERR, "Could not get information from user shadow database: %s", GetErrorStr()); return false; } else { Log(LOG_LEVEL_ERR, "Could not find user when checking password."); return false; } } else if (spwd_info) { *result = spwd_info->sp_pwdp; return true; } #elif defined(_AIX) if (!GetAIXShadowHash(puser, result)) { Log(LOG_LEVEL_ERR, "Could not get information from user shadow database: %s", GetErrorStr()); return false; } return true; #endif } Log(LOG_LEVEL_VERBOSE, "Getting user '%s' password hash from passwd database.", puser); *result = passwd_info->pw_passwd; return true; } static bool IsPasswordCorrect(const char *puser, const char* password, PasswordFormat format, const struct passwd *passwd_info) { /* * Check if password is already correct. If format is 'hash' we just do a simple * comparison with the supplied hash value, otherwise we try a pam login using * the real password. */ if (format == PASSWORD_FORMAT_HASH) { const char *system_hash; if (!GetPasswordHash(puser, passwd_info, &system_hash)) { return false; } bool result = (strcmp(password, system_hash) == 0); Log(LOG_LEVEL_VERBOSE, "Verifying password hash for user '%s': %s.", puser, result ? "correct" : "incorrect"); return result; } else if (format != PASSWORD_FORMAT_PLAINTEXT) { ProgrammingError("Unknown PasswordFormat value"); } int status; pam_handle_t *handle; struct pam_conv conv; conv.conv = PasswordSupplier; conv.appdata_ptr = (void*)password; status = pam_start("login", puser, &conv, &handle); if (status != PAM_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not initialize pam session. (pam_start: '%s')", pam_strerror(NULL, status)); return false; } status = pam_authenticate(handle, PAM_SILENT); pam_end(handle, status); if (status == PAM_SUCCESS) { Log(LOG_LEVEL_VERBOSE, "Verifying plaintext password for user '%s': correct.", puser); return true; } else if (status != PAM_AUTH_ERR) { Log(LOG_LEVEL_ERR, "Could not check password for user '%s' against stored password. (pam_authenticate: '%s')", puser, pam_strerror(NULL, status)); return false; } Log(LOG_LEVEL_VERBOSE, "Verifying plaintext password for user '%s': incorrect.", puser); return false; } static bool ChangePlaintextPasswordUsingLibPam(const char *puser, const char *password) { int status; pam_handle_t *handle; struct pam_conv conv; conv.conv = PasswordSupplier; conv.appdata_ptr = (void*)password; status = pam_start("passwd", puser, &conv, &handle); if (status != PAM_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not initialize pam session. (pam_start: '%s')", pam_strerror(NULL, status)); return false; } Log(LOG_LEVEL_VERBOSE, "Changing password for user '%s'.", puser); status = pam_chauthtok(handle, PAM_SILENT); pam_end(handle, status); if (status == PAM_SUCCESS) { return true; } else { Log(LOG_LEVEL_ERR, "Could not change password for user '%s'. (pam_chauthtok: '%s')", puser, pam_strerror(handle, status)); return false; } } static bool ClearPasswordAdministrationFlags(const char *puser) { (void)puser; // Avoid warning. #ifdef HAVE_PWDADM const char *cmd_str = PWDADM " -c "; char final_cmd[strlen(cmd_str) + strlen(puser) + 1]; xsnprintf(final_cmd, sizeof(final_cmd), "%s%s", cmd_str, puser); Log(LOG_LEVEL_VERBOSE, "Clearing password administration flags for user '%s'. (command: '%s')", puser, final_cmd); int status; status = system(final_cmd); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { Log(LOG_LEVEL_ERR, "Command failed while trying to clear password flags for user '%s'. (Command: '%s')", puser, final_cmd); return false; } #endif // HAVE_PWDADM return true; } #ifdef HAVE_CHPASSWD static bool ChangePasswordHashUsingChpasswd(const char *puser, const char *password) { int status; const char *cmd_str = CHPASSWD " -e"; Log(LOG_LEVEL_VERBOSE, "Changing password hash for user '%s'. (command: '%s')", puser, cmd_str); FILE *cmd = cf_popen_sh(cmd_str, "w"); if (!cmd) { Log(LOG_LEVEL_ERR, "Could not launch password changing command '%s': %s.", cmd_str, GetErrorStr()); return false; } // String lengths plus a ':' and a '\n', but not including '\0'. size_t total_len = strlen(puser) + strlen(password) + 2; char change_string[total_len + 1]; xsnprintf(change_string, total_len + 1, "%s:%s\n", puser, password); clearerr(cmd); if (fwrite(change_string, total_len, 1, cmd) != 1) { const char *error_str; if (ferror(cmd)) { error_str = GetErrorStr(); } else { error_str = "Unknown error"; } Log(LOG_LEVEL_ERR, "Could not write password to password changing command '%s': %s.", cmd_str, error_str); cf_pclose(cmd); return false; } status = cf_pclose(cmd); if (status) { Log(LOG_LEVEL_ERR, "'%s' returned non-zero status: %i\n", cmd_str, status); return false; } return true; } #endif // HAVE_CHPASSWD #if defined(HAVE_LCKPWDF) && defined(HAVE_ULCKPWDF) static bool ChangePasswordHashUsingLckpwdf(const char *puser, const char *password) { bool result = false; struct stat statbuf; const char *passwd_file = "/etc/shadow"; if (stat(passwd_file, &statbuf) == -1) { passwd_file = "/etc/passwd"; } Log(LOG_LEVEL_VERBOSE, "Changing password hash for user '%s' by editing '%s'.", puser, passwd_file); if (lckpwdf() != 0) { Log(LOG_LEVEL_ERR, "Not able to obtain lock on password database."); return false; } char backup_file[strlen(passwd_file) + strlen(".cf-backup") + 1]; xsnprintf(backup_file, sizeof(backup_file), "%s.cf-backup", passwd_file); unlink(backup_file); char edit_file[strlen(passwd_file) + strlen(".cf-edit") + 1]; xsnprintf(edit_file, sizeof(edit_file), "%s.cf-edit", passwd_file); unlink(edit_file); if (!CopyRegularFileDisk(passwd_file, backup_file)) { Log(LOG_LEVEL_ERR, "Could not back up existing password database '%s' to '%s'.", passwd_file, backup_file); goto unlock_passwd; } FILE *passwd_fd = fopen(passwd_file, "r"); if (!passwd_fd) { Log(LOG_LEVEL_ERR, "Could not open password database '%s'. (fopen: '%s')", passwd_file, GetErrorStr()); goto unlock_passwd; } int edit_fd_int = open(edit_file, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR); if (edit_fd_int < 0) { if (errno == EEXIST) { Log(LOG_LEVEL_CRIT, "Temporary file already existed when trying to open '%s'. (open: '%s') " "This should NEVER happen and could mean that someone is trying to break into your system!!", edit_file, GetErrorStr()); } else { Log(LOG_LEVEL_ERR, "Could not open password database temporary file '%s'. (open: '%s')", edit_file, GetErrorStr()); } goto close_passwd_fd; } FILE *edit_fd = fdopen(edit_fd_int, "w"); if (!edit_fd) { Log(LOG_LEVEL_ERR, "Could not open password database temporary file '%s'. (fopen: '%s')", edit_file, GetErrorStr()); close(edit_fd_int); goto close_passwd_fd; } while (true) { size_t line_size = 0; char *line = NULL; int read_result = CfReadLine(&line, &line_size, passwd_fd); if (read_result < 0) { if (!feof(passwd_fd)) { Log(LOG_LEVEL_ERR, "Error while reading password database: %s", GetErrorStr()); free(line); goto close_both; } else { break; } } // Editing the password database is risky business, so do as little parsing as possible. // Just enough to get the hash in there. char *field_start = NULL; char *field_end = NULL; field_start = strchr(line, ':'); if (field_start) { field_end = strchr(field_start + 1, ':'); } if (!field_start || !field_end) { Log(LOG_LEVEL_ERR, "Unexpected format found in password database while editing user '%s'. Not updating.", puser); free(line); goto close_both; } // Worst case length: Existing password is empty plus one '\n' and one '\0'. char new_line[strlen(line) + strlen(password) + 2]; *field_start = '\0'; *field_end = '\0'; if (strcmp(line, puser) == 0) { xsnprintf(new_line, sizeof(new_line), "%s:%s:%s\n", line, password, field_end + 1); } else { xsnprintf(new_line, sizeof(new_line), "%s:%s:%s\n", line, field_start + 1, field_end + 1); } free(line); size_t new_line_size = strlen(new_line); size_t written_so_far = 0; while (written_so_far < new_line_size) { clearerr(edit_fd); size_t written = fwrite(new_line, 1, new_line_size, edit_fd); if (written == 0) { const char *err_str; if (ferror(edit_fd)) { err_str = GetErrorStr(); } else { err_str = "Unknown error"; } Log(LOG_LEVEL_ERR, "Error while writing to file '%s'. (fwrite: '%s')", edit_file, err_str); goto close_both; } written_so_far += written; } } fclose(edit_fd); fclose(passwd_fd); if (!CopyFilePermissionsDisk(passwd_file, edit_file)) { Log(LOG_LEVEL_ERR, "Could not copy permissions from '%s' to '%s'", passwd_file, edit_file); goto unlock_passwd; } if (rename(edit_file, passwd_file) < 0) { Log(LOG_LEVEL_ERR, "Could not replace '%s' with edited password database '%s'. (rename: '%s')", passwd_file, edit_file, GetErrorStr()); goto unlock_passwd; } result = true; goto unlock_passwd; close_both: fclose(edit_fd); unlink(edit_file); close_passwd_fd: fclose(passwd_fd); unlock_passwd: ulckpwdf(); return result; } #endif // defined(HAVE_LCKPWDF) && defined(HAVE_ULCKPWDF) static bool ChangePassword(const char *puser, const char *password, PasswordFormat format) { assert(format == PASSWORD_FORMAT_PLAINTEXT || format == PASSWORD_FORMAT_HASH); bool successful = false; if (format == PASSWORD_FORMAT_PLAINTEXT) { successful = ChangePlaintextPasswordUsingLibPam(puser, password); } else { #ifdef HAVE_CHPASSWD struct stat statbuf; if (stat(CHPASSWD, &statbuf) != -1 && SupportsOption(CHPASSWD, "-e")) { successful = ChangePasswordHashUsingChpasswd(puser, password); } else #endif #if defined(HAVE_LCKPWDF) && defined(HAVE_ULCKPWDF) { successful = ChangePasswordHashUsingLckpwdf(puser, password); } #elif defined(HAVE_CHPASSWD) { Log(LOG_LEVEL_ERR, "No means to set password for user '%s' was found. Tried using the '%s' tool with no luck.", puser, CHPASSWD); successful = false; } #else { Log(LOG_LEVEL_WARNING, "Setting hashed password or locking user '%s' not supported on this platform.", puser); successful = false; } #endif } if (successful) { successful = ClearPasswordAdministrationFlags(puser); } return successful; } static bool IsAccountLocked(const char *puser, const struct passwd *passwd_info) { /* Note that when we lock an account, we do two things, we make the password hash invalid * by adding a '!', and we set the expiry date far in the past. However, we only have the * possibility of checking the password hash, because the expire field is not exposed by * POSIX functions. This is not a problem as long as you stick to CFEngine, but if the user * unlocks the account manually, but forgets to reset the expiry time, CFEngine could think * that the account is unlocked when it really isn't. */ const char *system_hash; if (!GetPasswordHash(puser, passwd_info, &system_hash)) { return false; } return (system_hash[0] == '!'); } static bool SetAccountLockExpiration(const char *puser, bool lock) { // Solaris has the concept of account expiration, but it is only possible // to set a date in the future. We need to set it to a past date, so we // have to skip it on that platform. #ifndef __sun char cmd[CF_BUFSIZE + strlen(puser)]; strcpy (cmd, USERMOD); StringAppend(cmd, " -e \"", sizeof(cmd)); if (lock) { StringAppend(cmd, GetPlatformSpecificExpirationDate(), sizeof(cmd)); } StringAppend(cmd, "\" ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); Log(LOG_LEVEL_VERBOSE, "%s user '%s' by setting expiry date. (command: '%s')", lock ? "Locking" : "Unlocking", puser, cmd); int status; status = system(cmd); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { Log(LOG_LEVEL_ERR, "Command returned error while %s user '%s'. (Command line: '%s')", lock ? "locking" : "unlocking", puser, cmd); return false; } #endif // !__sun return true; } static bool SetAccountLocked(const char *puser, const char *hash, bool lock) { if (lock) { if (hash[0] != '!') { char new_hash[strlen(hash) + 2]; xsnprintf(new_hash, sizeof(new_hash), "!%s", hash); if (!ChangePassword(puser, new_hash, PASSWORD_FORMAT_HASH)) { return false; } } } else { // Important to check. Password may already have been changed if that was also // specified in the policy. if (hash[0] == '!') { if (!ChangePassword(puser, &hash[1], PASSWORD_FORMAT_HASH)) { return false; } } } return SetAccountLockExpiration(puser, lock); } static bool GroupGetUserMembership (const char *user, StringSet *result) { bool ret = true; struct group *group_info; FILE *fptr = fopen("/etc/group", "r"); if (!fptr) { Log(LOG_LEVEL_ERR, "Could not open '/etc/group': %s", GetErrorStr()); return false; } while (true) { errno = 0; // Use fgetgrent() instead of getgrent(), to guarantee that the // returned group is a local group, and not for example from LDAP. group_info = fgetgrent(fptr); if (!group_info) { // Documentation among Unices is conflicting on return codes. When there // are no more entries, this happens: // Linux = ENOENT // AIX = ESRCH if (errno && errno != ENOENT && errno != ESRCH) { Log(LOG_LEVEL_ERR, "Error while getting group list. (fgetgrent: '%s')", GetErrorStr()); ret = false; } break; } for (int i = 0; group_info->gr_mem[i] != NULL; i++) { if (strcmp(user, group_info->gr_mem[i]) == 0) { StringSetAdd(result, xstrdup(group_info->gr_name)); break; } } } fclose(fptr); return ret; } static bool EqualGid(const char *key, const struct group *entry) { return (atoi(key) == entry->gr_gid); } static bool EqualGroupName(const char *key, const struct group *entry) { return (strcmp(key, entry->gr_name) == 0); } // Uses fgetgrent() instead of getgrnam(), to guarantee that the returned group // is a local group, and not for example from LDAP. static struct group *GetGrEntry(const char *key, bool (*equal_fn)(const char *key, const struct group *entry)) { FILE *fptr = fopen("/etc/group", "r"); if (!fptr) { Log(LOG_LEVEL_ERR, "Could not open '/etc/group': %s", GetErrorStr()); return NULL; } struct group *group_info; bool found = false; while ((group_info = fgetgrent(fptr))) { if (equal_fn(key, group_info)) { found = true; break; } } fclose(fptr); if (found) { return group_info; } else { // Failure to find the user means we just set errno to zero. // Perhaps not optimal, but we cannot pass ENOENT, because the fopen might // fail for this reason, and that should not be treated the same. errno = 0; return NULL; } } static void TransformGidsToGroups(StringSet **list) { StringSet *new_list = StringSetNew(); StringSetIterator i = StringSetIteratorInit(*list); const char *data; for (data = StringSetIteratorNext(&i); data; data = StringSetIteratorNext(&i)) { if (strlen(data) != strspn(data, "0123456789")) { // Cannot possibly be a gid. StringSetAdd(new_list, xstrdup(data)); continue; } // In groups vs gids, groups take precedence. So check if it exists. struct group *group_info = GetGrEntry(data, &EqualGroupName); if (!group_info) { if (errno == 0) { group_info = GetGrEntry(data, &EqualGid); if (!group_info) { if (errno != 0) { Log(LOG_LEVEL_ERR, "Error while checking group name '%s': %s", data, GetErrorStr()); StringSetDestroy(new_list); return; } // Neither group nor gid is found. This will lead to an error later, but we don't // handle that here. } else { // Replace gid with group name. StringSetAdd(new_list, xstrdup(group_info->gr_name)); } } else { Log(LOG_LEVEL_ERR, "Error while checking group name '%s': '%s'", data, GetErrorStr()); StringSetDestroy(new_list); return; } } else { StringSetAdd(new_list, xstrdup(data)); } } StringSet *old_list = *list; *list = new_list; StringSetDestroy(old_list); } static bool VerifyIfUserNeedsModifs (const char *puser, User u, const struct passwd *passwd_info, uint32_t *changemap) { if (u.description != NULL && strcmp (u.description, passwd_info->pw_gecos)) { CFUSR_SETBIT (*changemap, i_comment); } if (u.uid != NULL && (atoi (u.uid) != passwd_info->pw_uid)) { CFUSR_SETBIT (*changemap, i_uid); } if (u.home_dir != NULL && strcmp (u.home_dir, passwd_info->pw_dir)) { CFUSR_SETBIT (*changemap, i_home); } if (u.shell != NULL && strcmp (u.shell, passwd_info->pw_shell)) { CFUSR_SETBIT (*changemap, i_shell); } bool account_is_locked = IsAccountLocked(puser, passwd_info); if ((!account_is_locked && u.policy == USER_STATE_LOCKED) || (account_is_locked && u.policy != USER_STATE_LOCKED)) { CFUSR_SETBIT(*changemap, i_locked); } // Don't bother with passwords if the account is going to be locked anyway. if (u.password != NULL && strcmp (u.password, "") && u.policy != USER_STATE_LOCKED) { if (!IsPasswordCorrect(puser, u.password, u.password_format, passwd_info)) { CFUSR_SETBIT (*changemap, i_password); } } if (SafeStringLength(u.group_primary)) { bool group_could_be_gid = (strlen(u.group_primary) == strspn(u.group_primary, "0123456789")); int gid; // We try name first, even if it looks like a gid. Only fall back to gid. struct group *group_info; errno = 0; group_info = GetGrEntry(u.group_primary, &EqualGroupName); if (!group_info && errno != 0) { Log(LOG_LEVEL_ERR, "Could not obtain information about group '%s': %s", u.group_primary, GetErrorStr()); gid = -1; } else if (!group_info) { if (group_could_be_gid) { gid = atoi(u.group_primary); } else { Log(LOG_LEVEL_ERR, "No such group '%s'.", u.group_primary); gid = -1; } } else { gid = group_info->gr_gid; } if (gid != passwd_info->pw_gid) { CFUSR_SETBIT (*changemap, i_group); } } if (u.groups_secondary != NULL) { StringSet *wanted_groups = StringSetNew(); for (Rlist *ptr = u.groups_secondary; ptr; ptr = ptr->next) { if (strcmp(RvalScalarValue(ptr->val), CF_NULL_VALUE) != 0) { StringSetAdd(wanted_groups, xstrdup(RvalScalarValue(ptr->val))); } } TransformGidsToGroups(&wanted_groups); StringSet *current_groups = StringSetNew(); if (!GroupGetUserMembership (puser, current_groups)) { CFUSR_SETBIT (*changemap, i_groups); } else if (!StringSetIsEqual (current_groups, wanted_groups)) { CFUSR_SETBIT (*changemap, i_groups); } StringSetDestroy(current_groups); StringSetDestroy(wanted_groups); } //////////////////////////////////////////// if (*changemap == 0) { return false; } else { return true; } } static bool SupportsOption(const char *cmd, const char *option) { bool supports_option = false; char help_argument[] = " --help"; char help_command[strlen(cmd) + sizeof(help_argument)]; xsnprintf(help_command, sizeof(help_command), "%s%s", cmd, help_argument); FILE *fptr = cf_popen(help_command, "r", true); char *buf = NULL; size_t bufsize = 0; size_t optlen = strlen(option); while (CfReadLine(&buf, &bufsize, fptr) >= 0) { char *m_pos = buf; while ((m_pos = strstr(m_pos, option))) { // Check against false alarms, e.g. hyphenated words in normal text or an // option (say, "-M") that is part of "--M". if ((m_pos == buf || (m_pos[-1] != '-' && (isspace(m_pos[-1]) || ispunct(m_pos[-1])))) && (m_pos[optlen] == '\0' || (isspace(m_pos[optlen]) || ispunct(m_pos[optlen])))) { supports_option = true; // Break out of strstr loop, but read till the end to avoid broken pipes. break; } m_pos++; } } cf_pclose(fptr); free(buf); return supports_option; } static bool ExecuteUserCommand(const char *puser, const char *cmd, size_t sizeof_cmd, const char *action_msg, const char *cap_action_msg) { if (strlen(cmd) >= sizeof_cmd - 1) { // Instead of checking every StringAppend call, assume that a maxed out // string length overflowed the string. Log(LOG_LEVEL_ERR, "Command line too long while %s user '%s'", action_msg, puser); return false; } Log(LOG_LEVEL_VERBOSE, "%s user '%s'. (command: '%s')", cap_action_msg, puser, cmd); int status; status = system(cmd); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { Log(LOG_LEVEL_ERR, "Command returned error while %s user '%s'. (Command line: '%s')", action_msg, puser, cmd); return false; } return true; } static bool DoCreateUser(const char *puser, User u, enum cfopaction action, EvalContext *ctx, const Attributes *a, const Promise *pp) { char cmd[CF_BUFSIZE]; char sec_group_args[CF_BUFSIZE]; if (puser == NULL || !strcmp (puser, "")) { return false; } strcpy (cmd, USERADD); if (u.uid != NULL && strcmp (u.uid, "")) { StringAppend(cmd, " -u \"", sizeof(cmd)); StringAppend(cmd, u.uid, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (u.description != NULL) { StringAppend(cmd, " -c \"", sizeof(cmd)); StringAppend(cmd, u.description, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (u.group_primary != NULL && strcmp (u.group_primary, "")) { // TODO: Should check that group exists StringAppend(cmd, " -g \"", sizeof(cmd)); StringAppend(cmd, u.group_primary, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (u.groups_secondary != NULL) { // TODO: Should check that groups exist strlcpy(sec_group_args, " -G \"", sizeof(sec_group_args)); char sep[2] = { '\0', '\0' }; for (Rlist *i = u.groups_secondary; i; i = i->next) { if (strcmp(RvalScalarValue(i->val), CF_NULL_VALUE) != 0) { StringAppend(sec_group_args, sep, sizeof(sec_group_args)); StringAppend(sec_group_args, RvalScalarValue(i->val), sizeof(sec_group_args)); sep[0] = ','; } } StringAppend(sec_group_args, "\"", sizeof(sec_group_args)); StringAppend(cmd, sec_group_args, sizeof(cmd)); } if (u.home_dir != NULL && strcmp (u.home_dir, "")) { StringAppend(cmd, " -d \"", sizeof(cmd)); StringAppend(cmd, u.home_dir, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (u.shell != NULL && strcmp (u.shell, "")) { StringAppend(cmd, " -s \"", sizeof(cmd)); StringAppend(cmd, u.shell, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (SupportsOption(USERADD, "-M")) { // Prevents creation of home_dir. // We want home_bundle to do that. StringAppend(cmd, " -M", sizeof(cmd)); } StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to create user '%s'.", puser); return false; } else { if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "creating", "Creating")) { return false; } if (u.groups_secondary != NULL) { // Work around issue on AIX. Always set secondary groups a second time, because AIX // likes to assign the primary group as the secondary group as well, even if we didn't // ask for it. strlcpy(cmd, USERMOD, sizeof(cmd)); StringAppend(cmd, sec_group_args, sizeof(cmd)); StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } } // Initially, "useradd" may set the password to '!', which confuses our detection for // locked accounts. So reset it to 'x' hash instead, which will never match anything. if (!ChangePassword(puser, "x", PASSWORD_FORMAT_HASH)) { return false; } if (u.policy == USER_STATE_LOCKED) { if (!SetAccountLocked(puser, "x", true)) { return false; } } if (a->havebundle) { const Constraint *method_attrib = PromiseGetConstraint(pp, "home_bundle"); VerifyMethod(ctx, method_attrib->rval, *a, pp); } if (u.policy != USER_STATE_LOCKED && u.password != NULL && strcmp (u.password, "")) { if (!ChangePassword(puser, u.password, u.password_format)) { return false; } } } return true; } static bool DoRemoveUser (const char *puser, enum cfopaction action) { char cmd[CF_BUFSIZE]; strcpy (cmd, USERDEL); StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to remove user '%s'.", puser); return false; } return ExecuteUserCommand(puser, cmd, sizeof(cmd), "removing", "Removing"); } static bool DoModifyUser (const char *puser, User u, const struct passwd *passwd_info, uint32_t changemap, enum cfopaction action) { char cmd[CF_BUFSIZE]; strcpy (cmd, USERMOD); if (CFUSR_CHECKBIT (changemap, i_uid) != 0) { StringAppend(cmd, " -u \"", sizeof(cmd)); StringAppend(cmd, u.uid, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_comment) != 0) { StringAppend(cmd, " -c \"", sizeof(cmd)); StringAppend(cmd, u.description, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_group) != 0) { StringAppend(cmd, " -g \"", sizeof(cmd)); StringAppend(cmd, u.group_primary, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { /* Work around bug on SUSE. If secondary groups contain a group that is the same group as the primary group, the secondary group is not set. This happens even if the primary group is changed in the same call. Therefore, set an empty group list first, and then set it to the real list later. */ StringAppend(cmd, " -G \"\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_home) != 0) { StringAppend(cmd, " -d \"", sizeof(cmd)); StringAppend(cmd, u.home_dir, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } if (CFUSR_CHECKBIT (changemap, i_shell) != 0) { StringAppend(cmd, " -s \"", sizeof(cmd)); StringAppend(cmd, u.shell, sizeof(cmd)); StringAppend(cmd, "\"", sizeof(cmd)); } StringAppend(cmd, " ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (CFUSR_CHECKBIT (changemap, i_password) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to change password for user '%s'.", puser); return false; } else { if (!ChangePassword(puser, u.password, u.password_format)) { return false; } } } if (CFUSR_CHECKBIT (changemap, i_locked) != 0) { if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to %s account for user '%s'.", (u.policy == USER_STATE_LOCKED) ? "lock" : "unlock", puser); return false; } else { const char *hash; if (!GetPasswordHash(puser, passwd_info, &hash)) { return false; } if (!SetAccountLocked(puser, hash, (u.policy == USER_STATE_LOCKED))) { return false; } } } // If password and locking were the only things changed, don't run the command. CFUSR_CLEARBIT(changemap, i_password); CFUSR_CLEARBIT(changemap, i_locked); if (action == cfa_warn || DONTDO) { Log(LOG_LEVEL_NOTICE, "Need to update user attributes (command '%s').", cmd); return false; } else if (changemap != 0) { if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } if (CFUSR_CHECKBIT (changemap, i_groups) != 0) { // Set real group list (see -G comment earlier). strcpy(cmd, USERMOD); StringAppend(cmd, " -G \"", sizeof(cmd)); char sep[2] = { '\0', '\0' }; for (Rlist *i = u.groups_secondary; i; i = i->next) { if (strcmp(RvalScalarValue(i->val), CF_NULL_VALUE) != 0) { StringAppend(cmd, sep, sizeof(cmd)); StringAppend(cmd, RvalScalarValue(i->val), sizeof(cmd)); sep[0] = ','; } } StringAppend(cmd, "\" ", sizeof(cmd)); StringAppend(cmd, puser, sizeof(cmd)); if (!ExecuteUserCommand(puser, cmd, sizeof(cmd), "modifying", "Modifying")) { return false; } } } return true; } // Uses fgetpwent() instead of getpwnam(), to guarantee that the returned user // is a local user, and not for example from LDAP. static struct passwd *GetPwEntry(const char *puser) { FILE *fptr = fopen("/etc/passwd", "r"); if (!fptr) { Log(LOG_LEVEL_ERR, "Could not open '/etc/passwd': %s", GetErrorStr()); return NULL; } struct passwd *passwd_info; bool found = false; while ((passwd_info = fgetpwent(fptr))) { if (strcmp(puser, passwd_info->pw_name) == 0) { found = true; break; } } fclose(fptr); if (found) { return passwd_info; } else { // Failure to find the user means we just set errno to zero. // Perhaps not optimal, but we cannot pass ENOENT, because the fopen might // fail for this reason, and that should not be treated the same. errno = 0; return NULL; } } void VerifyOneUsersPromise (const char *puser, User u, PromiseResult *result, enum cfopaction action, EvalContext *ctx, const Attributes *a, const Promise *pp) { bool res; struct passwd *passwd_info; passwd_info = GetPwEntry(puser); if (!passwd_info && errno != 0) { Log(LOG_LEVEL_ERR, "Could not get information from user database."); return; } if (u.policy == USER_STATE_PRESENT || u.policy == USER_STATE_LOCKED) { if (passwd_info) { uint32_t cmap = 0; if (VerifyIfUserNeedsModifs (puser, u, passwd_info, &cmap)) { res = DoModifyUser (puser, u, passwd_info, cmap, action); if (res) { *result = PROMISE_RESULT_CHANGE; } else { *result = PROMISE_RESULT_FAIL; } } else { *result = PROMISE_RESULT_NOOP; } } else { res = DoCreateUser (puser, u, action, ctx, a, pp); if (res) { *result = PROMISE_RESULT_CHANGE; } else { *result = PROMISE_RESULT_FAIL; } } } else if (u.policy == USER_STATE_ABSENT) { if (passwd_info) { res = DoRemoveUser (puser, action); if (res) { *result = PROMISE_RESULT_CHANGE; } else { *result = PROMISE_RESULT_FAIL; } } else { *result = PROMISE_RESULT_NOOP; } } } cfengine-3.6.2/cf-agent/files_edit.c0000664000175100017510000001777612411001073016764 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include /*****************************************************************************/ EditContext *NewEditContext(char *filename, Attributes a) { EditContext *ec; if (!IsAbsoluteFileName(filename)) { Log(LOG_LEVEL_ERR, "Relative file name '%s' was marked for editing but has no invariant meaning", filename); return NULL; } ec = xcalloc(1, sizeof(EditContext)); ec->filename = filename; ec->new_line_mode = FileNewLineMode(filename); if (a.haveeditline) { if (!LoadFileAsItemList(&(ec->file_start), filename, a.edits)) { free(ec); return NULL; } } if (a.haveeditxml) { #ifdef HAVE_LIBXML2 if (!LoadFileAsXmlDoc(&(ec->xmldoc), filename, a.edits)) { free(ec); return NULL; } #else Log(LOG_LEVEL_ERR, "Cannot edit XML files without LIBXML2"); free(ec); return NULL; #endif } if (a.edits.empty_before_use) { Log(LOG_LEVEL_VERBOSE, "Build file model from a blank slate (emptying)"); DeleteItemList(ec->file_start); ec->file_start = NULL; } return ec; } /*****************************************************************************/ void FinishEditContext(EvalContext *ctx, EditContext *ec, Attributes a, const Promise *pp, PromiseResult *result) { if (*result == PROMISE_RESULT_NOOP || *result == PROMISE_RESULT_CHANGE) { // A sub promise with CHANGE status does not necessarily mean that the // file has really changed. *result = PROMISE_RESULT_NOOP; } else { // Failure or skipped. Don't update the file. goto end; } if (DONTDO || (a.transaction.action == cfa_warn)) { if (ec && !CompareToFile(ctx, ec->file_start, ec->filename, a, pp, result) && ec->num_edits > 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Should edit file '%s' but only a warning promised", ec->filename); *result = PROMISE_RESULT_WARN; } else { *result = PROMISE_RESULT_NOOP; } } else if (ec && (ec->num_edits > 0)) { if (a.haveeditline || a.edit_template) { if (CompareToFile(ctx, ec->file_start, ec->filename, a, pp, result)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No edit changes to file '%s' need saving", ec->filename); } else if (SaveItemListAsFile(ec->file_start, ec->filename, a, ec->new_line_mode)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Edit file '%s'", ec->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to save file '%s' after editing", ec->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } } if (a.haveeditxml) { #ifdef HAVE_LIBXML2 if (XmlCompareToFile(ec->xmldoc, ec->filename, a.edits)) { if (ec) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No edit changes to xml file '%s' need saving", ec->filename); } } else if (SaveXmlDocAsFile(ec->xmldoc, ec->filename, a, ec->new_line_mode)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Edited xml file '%s'", ec->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed to edit XML file '%s'", ec->filename); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } xmlFreeDoc(ec->xmldoc); #else cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Cannot edit XML files without LIBXML2"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); #endif } } else if (ec) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No edit changes to file '%s' need saving", ec->filename); } end: if (ec != NULL) { DeleteItemList(ec->file_start); free(ec); } } /*********************************************************************/ /* Level */ /*********************************************************************/ /***************************************************************************/ #ifdef HAVE_LIBXML2 int LoadFileAsXmlDoc(xmlDocPtr *doc, const char *file, EditDefaults edits) { struct stat statbuf; if (stat(file, &statbuf) == -1) { Log(LOG_LEVEL_ERR, "The proposed file '%s' could not be loaded. (stat: %s)", file, GetErrorStr()); return false; } if (edits.maxfilesize != 0 && statbuf.st_size > edits.maxfilesize) { Log(LOG_LEVEL_INFO, "File '%s' is bigger than the limit edit.max_file_size = '%jd' > '%d' bytes", file, (intmax_t) statbuf.st_size, edits.maxfilesize); return false; } if (!S_ISREG(statbuf.st_mode)) { Log(LOG_LEVEL_INFO, "'%s' is not a plain file", file); return false; } if (statbuf.st_size == 0) { if ((*doc = xmlNewDoc(BAD_CAST "1.0")) == NULL) { Log(LOG_LEVEL_INFO, "Document '%s' not parsed successfully. (xmlNewDoc: %s)", file, GetErrorStr()); return false; } } else if ((*doc = xmlParseFile(file)) == NULL) { Log(LOG_LEVEL_INFO, "Document '%s' not parsed successfully. (xmlParseFile: %s)", file, GetErrorStr()); return false; } return true; } #endif /*********************************************************************/ #ifdef HAVE_LIBXML2 bool SaveXmlCallback(const char *dest_filename, void *param, ARG_UNUSED NewLineMode new_line_mode) { xmlDocPtr doc = param; //saving xml to file if (xmlSaveFile(dest_filename, doc) == -1) { Log(LOG_LEVEL_ERR, "Failed to write xml document to file '%s' after editing. (xmlSaveFile: %s)", dest_filename, GetErrorStr()); return false; } return true; } #endif /*********************************************************************/ #ifdef HAVE_LIBXML2 bool SaveXmlDocAsFile(xmlDocPtr doc, const char *file, Attributes a, NewLineMode new_line_mode) { return SaveAsFile(&SaveXmlCallback, doc, file, a, new_line_mode); } #endif cfengine-3.6.2/cf-agent/comparray.h0000644000175100017510000000265512316547775016677 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_COMPARRAY_H #define CFENGINE_COMPARRAY_H #include typedef struct CompressedArray_ { int key; char *value; struct CompressedArray_ *next; } CompressedArray; int FixCompressedArrayValue(int i, char *value, CompressedArray **start); void DeleteCompressedArray(CompressedArray *start); int CompressedArrayElementExists(CompressedArray *start, int key); char *CompressedArrayValue(CompressedArray *start, int key); #endif cfengine-3.6.2/cf-agent/verify_users.c0000664000175100017510000000656012411001073017367 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include static int UserSanityCheck(Attributes a, const Promise *pp); PromiseResult VerifyUsersPromise(EvalContext *ctx, const Promise *pp) { CfLock thislock; char lockname[CF_BUFSIZE]; Attributes a = GetUserAttributes(ctx, pp); if (!UserSanityCheck(a, pp)) { return PROMISE_RESULT_FAIL; } PromiseBanner(pp); snprintf(lockname, CF_BUFSIZE - 1, "user-%s-%d", pp->promiser, a.users.policy); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } PromiseResult result = PROMISE_RESULT_NOOP; VerifyOneUsersPromise(pp->promiser, a.users, &result, a.transaction.action, ctx, &a, pp); switch (result) { case PROMISE_RESULT_NOOP: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "User promise kept"); break; case PROMISE_RESULT_FAIL: case PROMISE_RESULT_DENIED: case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_INTERRUPTED: case PROMISE_RESULT_WARN: cfPS(ctx, LOG_LEVEL_INFO, result, pp, a, "User promise not kept"); break; case PROMISE_RESULT_CHANGE: cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "User promise repaired"); break; default: ProgrammingError("Unknown promise result"); break; } YieldCurrentLock(thislock); return result; } /** Pre-check of promise contents **/ static int UserSanityCheck(Attributes a, const Promise *pp) { User *u = &a.users; switch (u->policy) { case USER_STATE_PRESENT: case USER_STATE_ABSENT: case USER_STATE_LOCKED: break; default: Log(LOG_LEVEL_ERR, "No policy specified for 'users' promise '%s'", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if ((SafeStringLength(u->password) == 0 && u->password_format != PASSWORD_FORMAT_NONE) || (SafeStringLength(u->password) != 0 && u->password_format == PASSWORD_FORMAT_NONE)) { Log(LOG_LEVEL_ERR, "Both 'data' and 'format' must be specified in password body for 'users' promise '%s'", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); return false; } return true; } cfengine-3.6.2/cf-agent/Makefile.am0000664000175100017510000000577712411001073016543 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-agent.la AM_CPPFLAGS = -I$(srcdir)/../libpromises -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ $(ENTERPRISE_CPPFLAGS) \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(LIBVIRT_CPPFLAGS) \ $(POSTGRESQL_CPPFLAGS) \ $(MYSQL_CPPFLAGS) \ $(LIBXML2_CPPFLAGS) \ $(PAM_CPPFLAGS) AM_CFLAGS = \ $(ENTERPRISE_CFLAGS) \ $(OPENSSL_CFLAGS) \ $(PCRE_CFLAGS) \ $(LIBVIRT_CFLAGS) \ $(POSTGRESQL_CFLAGS) \ $(MYSQL_CFLAGS) \ $(LIBXML2_CFLAGS) \ $(PAM_CFLAGS) AM_LDFLAGS = \ $(OPENSSL_LDFLAGS) \ $(PCRE_LDFLAGS) \ $(LIBVIRT_LDFLAGS) \ $(POSTGRESQL_LDFLAGS) \ $(MYSQL_LDFLAGS) \ $(LIBXML2_LDFLAGS) \ $(PAM_LDFLAGS) libcf_agent_la_LIBADD = ../libpromises/libpromises.la \ $(OPENSSL_LIBS) \ $(PCRE_LIBS) \ $(LIBVIRT_LIBS) \ $(POSTGRESQL_LIBS) \ $(MYSQL_LIBS) \ $(LIBXML2_LIBS) \ $(PAM_LIBS) libcf_agent_la_SOURCES = \ agent-diagnostics.c agent-diagnostics.h \ tokyo_check.c tokyo_check.h \ abstract_dir.c abstract_dir.h \ cf-agent.c \ cf-agent-enterprise-stubs.c cf-agent-enterprise-stubs.h \ comparray.c comparray.h \ acl_posix.c acl_posix.h \ cf_sql.c cf_sql.h \ files_changes.c files_changes.h \ promiser_regex_resolver.c promiser_regex_resolver.h \ match_scope.c match_scope.h \ retcode.c retcode.h \ verify_acl.c verify_acl.h \ verify_files.c verify_files.h \ verify_files_utils.c verify_files_utils.h \ verify_files_hashes.c verify_files_hashes.h \ verify_storage.c verify_storage.h \ verify_exec.c verify_exec.h \ verify_methods.c verify_methods.h \ verify_databases.c verify_databases.h \ verify_processes.c verify_processes.h \ verify_services.c verify_services.h \ verify_environments.c verify_environments.h \ files_edit.c files_edit.h \ files_editline.c files_editline.h \ files_editxml.c files_editxml.h \ files_links.c files_links.h \ files_operators.c files_operators.h \ files_properties.c files_properties.h \ files_repository.c files_repository.h \ files_select.c files_select.h \ vercmp_internal.c vercmp_internal.h \ vercmp.c vercmp.h \ verify_packages.c verify_packages.h \ verify_users.c verify_users.h \ cf-agent-windows-functions.h if !NT libcf_agent_la_SOURCES += nfs.c nfs.h if HAVE_USERS_PROMISE_DEPS libcf_agent_la_SOURCES += verify_users_pam.c else libcf_agent_la_SOURCES += verify_users_stub.c endif endif if HAVE_AVAHI_CLIENT if HAVE_AVAHI_COMMON libcf_agent_la_SOURCES += \ findhub.c findhub_priv.h findhub.h \ load_avahi.c load_avahi.h endif endif if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-agent # Workaround for automake madness (try removing it if you want to know why). cf_agent_CFLAGS = $(AM_CFLAGS) # Build both a libcf-agent.la library, and a cf-agent executable cf_agent_LDADD = libcf-agent.la endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/cf-agent/verify_methods.h0000644000175100017510000000235312316547775017724 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_METHODS_H #define CFENGINE_VERIFY_METHODS_H #include PromiseResult VerifyMethodsPromise(EvalContext *ctx, const Promise *pp); PromiseResult VerifyMethod(EvalContext *ctx, const Rval call, Attributes a, const Promise *pp); #endif cfengine-3.6.2/cf-agent/verify_packages.c0000664000175100017510000037655012411001073020015 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Called structure: Top-level: cf-agent calls... * CleanScheduledPackages * VerifyPackagesPromise -> all the Verify* functions that schedule operation * ExecuteScheduledPackages -> all the Execute* functions to run operations */ /** Entry points from VerifyPackagesPromise **/ #define REPORT_THIS_PROMISE(__pp) (strncmp(__pp->promiser, "cfe_internal_", 13) != 0) #define cfPS_HELPER_0ARG(__ctx, __log_level, __result, __pp, __a, __str) \ if (REPORT_THIS_PROMISE(__pp)) \ { \ cfPS(__ctx, __log_level, __result, __pp, __a, __str); \ } #define cfPS_HELPER_1ARG(__ctx, __log_level, __result, __pp, __a, __str, __arg1) \ if (REPORT_THIS_PROMISE(__pp)) \ { \ cfPS(__ctx, __log_level, __result, __pp, __a, __str, __arg1); \ } #define cfPS_HELPER_2ARG(__ctx, __log_level, __result, __pp, __a, __str, __arg1, __arg2) \ if (REPORT_THIS_PROMISE(__pp)) \ { \ cfPS(__ctx, __log_level, __result, __pp, __a, __str, __arg1, __arg2); \ } #define cfPS_HELPER_3ARG(__ctx, __log_level, __result, __pp, __a, __str, __arg1, __arg2, __arg3) \ if (REPORT_THIS_PROMISE(__pp)) \ { \ cfPS(__ctx, __log_level, __result, __pp, __a, __str, __arg1, __arg2, __arg3); \ } #define PromiseResultUpdate_HELPER(__pp, __prior, __evidence) \ REPORT_THIS_PROMISE(__pp) ? PromiseResultUpdate(__prior, __evidence) : __evidence static int PackageSanityCheck(EvalContext *ctx, Attributes a, const Promise *pp); static int VerifyInstalledPackages(EvalContext *ctx, PackageManager **alllists, const char *default_arch, Attributes a, const Promise *pp, PromiseResult *result); static PromiseResult VerifyPromisedPackage(EvalContext *ctx, Attributes a, const Promise *pp); static PromiseResult VerifyPromisedPatch(EvalContext *ctx, Attributes a, const Promise *pp); /** Utils **/ static char *GetDefaultArch(const char *command); static bool ExecPackageCommand(EvalContext *ctx, char *command, int verify, int setCmdClasses, Attributes a, const Promise *pp, PromiseResult *result); static int PrependPatchItem(EvalContext *ctx, PackageItem ** list, char *item, PackageItem * chklist, const char *default_arch, Attributes a, const Promise *pp); static int PrependMultiLinePackageItem(EvalContext *ctx, PackageItem ** list, char *item, int reset, const char *default_arch, Attributes a, const Promise *pp); static int PrependListPackageItem(EvalContext *ctx, PackageItem ** list, char *item, const char *default_arch, Attributes a, const Promise *pp); static PackageManager *GetPackageManager(PackageManager **lists, char *mgr, PackageAction pa, PackageActionPolicy x); static void DeletePackageManagers(PackageManager *morituri); static const char *PrefixLocalRepository(const Rlist *repositories, const char *package); ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, ReportPatches, ARG_UNUSED PackageManager *, list) { Log(LOG_LEVEL_VERBOSE, "Patch reporting feature is only available in the enterprise version"); } /*****************************************************************************/ PackageManager *PACKAGE_SCHEDULE = NULL; /* GLOBAL_X */ PackageManager *INSTALLED_PACKAGE_LISTS = NULL; /* GLOBAL_X */ #define PACKAGE_LIST_COMMAND_WINAPI "/Windows_API" /*****************************************************************************/ #define PACKAGE_IGNORED_CFE_INTERNAL "cfe_internal_non_existing_package" /** @brief Verifies a single packages promise Called by cf-agent. * checks "name", "version", "arch", "firstrepo" variables from the "this" context * gets the package attributes into a * on Windows, if the package_list_command is not defined, use the hard-coded PACKAGE_LIST_COMMAND_WINAPI * do a package sanity check on the promise * print promise banner * reset to root directory (Yum bugfix) * get the default architecture from a.packages.package_default_arch_command into default_arch * call VerifyInstalledPackages with default_arch * if the package action is "patch", call VerifyPromisedPatch and return its result through PromiseResultUpdate_HELPER * for all other package actions, call VerifyPromisedPackage and return its result through PromiseResultUpdate_HELPER @param ctx [in] The evaluation context @param pp [in] the Promise for this operation @returns the promise result */ PromiseResult VerifyPackagesPromise(EvalContext *ctx, const Promise *pp) { CfLock thislock; char lockname[CF_BUFSIZE]; PromiseResult result = PROMISE_RESULT_NOOP; const char *reserved_vars[] = { "name", "version", "arch", "firstrepo", NULL }; for (int c = 0; reserved_vars[c]; c++) { const char *reserved = reserved_vars[c]; VarRef *var_ref = VarRefParseFromScope(reserved, "this"); if (EvalContextVariableGet(ctx, var_ref, NULL)) { Log(LOG_LEVEL_WARNING, "$(%s) variable has a special meaning in packages promises. " "Things may not work as expected if it is already defined.", reserved); } VarRefDestroy(var_ref); } Attributes a = GetPackageAttributes(ctx, pp); #ifdef __MINGW32__ if(!a.packages.package_list_command) { a.packages.package_list_command = PACKAGE_LIST_COMMAND_WINAPI; } #endif if (!PackageSanityCheck(ctx, a, pp)) { Log(LOG_LEVEL_VERBOSE, "Package promise %s failed sanity check", pp->promiser); result = PROMISE_RESULT_FAIL; goto end; } PromiseBanner(pp); // Now verify the package itself snprintf(lockname, CF_BUFSIZE - 1, "package-%s-%s", pp->promiser, a.packages.package_list_command); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { result = PROMISE_RESULT_SKIPPED; goto end; } // Start by reseting the root directory in case yum tries to glob regexs(!) if (safe_chdir("/") != 0) { Log(LOG_LEVEL_ERR, "Failed to chdir into '/'"); } char *default_arch = GetDefaultArch(a.packages.package_default_arch_command); if (default_arch == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to obtain default architecture for package manager - aborting"); YieldCurrentLock(thislock); result = PROMISE_RESULT_FAIL; goto end; } Log(LOG_LEVEL_VERBOSE, "Default package architecture for promise %s is '%s'", pp->promiser, default_arch); if (!VerifyInstalledPackages(ctx, &INSTALLED_PACKAGE_LISTS, default_arch, a, pp, &result)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to obtain a list of installed packages - aborting"); free(default_arch); YieldCurrentLock(thislock); result = PROMISE_RESULT_FAIL; goto end; } free(default_arch); switch (a.packages.package_policy) { case PACKAGE_ACTION_PATCH: Log(LOG_LEVEL_VERBOSE, "Verifying patch action for promise %s", pp->promiser); result = PromiseResultUpdate_HELPER(pp, result, VerifyPromisedPatch(ctx, a, pp)); break; default: Log(LOG_LEVEL_VERBOSE, "Verifying action for promise %s", pp->promiser); result = PromiseResultUpdate_HELPER(pp, result, VerifyPromisedPackage(ctx, a, pp)); break; } YieldCurrentLock(thislock); end: if (!REPORT_THIS_PROMISE(pp)) { // This will not be reported elsewhere, so give it kept outcome. result = PROMISE_RESULT_NOOP; cfPS(ctx, LOG_LEVEL_DEBUG, result, pp, a, "Giving dummy package kept outcome"); } return result; } /** @brief Pre-check of promise contents Called by VerifyPackagesPromise. Does many sanity checks on the promise attributes and semantics. @param ctx [in] The evaluation context @param a [in] the promise Attributes for this operation @param pp [in] the Promise for this operation @returns the promise result */ static int PackageSanityCheck(EvalContext *ctx, Attributes a, const Promise *pp) { #ifndef __MINGW32__ // Windows may use Win32 API for listing and parsing if (a.packages.package_list_name_regex == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must supply a method for determining the name of existing packages e.g. use the standard library generic package_method"); return false; } if (a.packages.package_list_version_regex == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must supply a method for determining the version of existing packages e.g. use the standard library generic package_method"); return false; } if ((!a.packages.package_commands_useshell) && (a.packages.package_list_command) && (!IsExecutable(CommandArg0(a.packages.package_list_command)))) { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "The proposed package list command '%s' was not executable", a.packages.package_list_command); return false; } #endif /* !__MINGW32__ */ if ((a.packages.package_list_command == NULL) && (a.packages.package_file_repositories == NULL)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must supply a method for determining the list of existing packages (a command or repository list) e.g. use the standard library generic package_method"); return false; } if (a.packages.package_file_repositories) { Rlist *rp; for (rp = a.packages.package_file_repositories; rp != NULL; rp = rp->next) { if (strlen(RlistScalarValue(rp)) > CF_MAXVARSIZE - 1) { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "The repository path '%s' is too long", RlistScalarValue(rp)); return false; } } } if ((a.packages.package_name_regex) || (a.packages.package_version_regex) || (a.packages.package_arch_regex)) { if (a.packages.package_name_regex == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must supply name regex if you supplied version or arch regex for parsing promiser string"); return false; } if ((a.packages.package_name_regex) && (a.packages.package_version_regex) && (a.packages.package_arch_regex)) { if ((a.packages.package_version) || (a.packages.package_architectures)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must either supply all regexs for (name,version,arch) or a separate version number and architecture"); return false; } } else { if ((a.packages.package_version) && (a.packages.package_architectures)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must either supply all regexs for (name,version,arch) or a separate version number and architecture"); return false; } } if ((a.packages.package_version_regex) && (a.packages.package_version)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must either supply version regex or a separate version number"); return false; } if ((a.packages.package_arch_regex) && (a.packages.package_architectures)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "You must either supply arch regex or a separate architecture"); return false; } } if (!a.packages.package_installed_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Package installed regex undefined"); return false; } if (a.packages.package_policy == PACKAGE_ACTION_VERIFY) { if (!a.packages.package_verify_command) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Package verify policy is used, but no package_verify_command is defined"); return false; } else if ((a.packages.package_noverify_returncode == CF_NOINT) && (a.packages.package_noverify_regex == NULL)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Package verify policy is used, but no definition of verification failiure is set (package_noverify_returncode or packages.package_noverify_regex)"); return false; } } if ((a.packages.package_noverify_returncode != CF_NOINT) && (a.packages.package_noverify_regex)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Both package_noverify_returncode and package_noverify_regex are defined, pick one of them"); return false; } /* Dependency checks */ if (!a.packages.package_delete_command) { if (a.packages.package_delete_convention) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_delete_command is not used, but package_delete_convention is defined."); return false; } } if (!a.packages.package_list_command) { if (a.packages.package_installed_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_list_command is not used, but package_installed_regex is defined."); return false; } if (a.packages.package_list_arch_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_list_command is not used, but package_arch_regex is defined."); return false; } if (a.packages.package_list_name_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_list_command is not used, but package_name_regex is defined."); return false; } if (a.packages.package_list_version_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_list_command is not used, but package_version_regex is defined."); return false; } } if (!a.packages.package_patch_command) { if (a.packages.package_patch_arch_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_patch_command is not used, but package_patch_arch_regex is defined."); return false; } if (a.packages.package_patch_name_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_patch_command is not used, but package_patch_name_regex is defined."); return false; } if (a.packages.package_patch_version_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_patch_command is not used, but package_patch_version_regex is defined."); return false; } } if (!a.packages.package_patch_list_command) { if (a.packages.package_patch_installed_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_patch_list_command is not used, but package_patch_installed_regex is defined."); return false; } } if (!a.packages.package_verify_command) { if (a.packages.package_noverify_regex) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_verify_command is not used, but package_noverify_regex is defined."); return false; } if (a.packages.package_noverify_returncode != CF_NOINT) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "!! Dependency conflict: package_verify_command is not used, but package_noverify_returncode is defined."); return false; } } return true; } /** @brief Generates the list of installed packages Called by VerifyInstalledPackages * calls a.packages.package_list_update_command if $(sys.workdir)/state/software_update_timestamp_ is older than the interval specified in package_list_update_ifelapsed. * assembles the package list from a.packages.package_list_command * respects a.packages.package_commands_useshell (boolean) * parses with a.packages.package_multiline_start and if successful, calls PrependMultiLinePackageItem * else, parses with a.packages.package_installed_regex and if successful, calls PrependListPackageItem @param ctx [in] The evaluation context @param installed_list [in] a list of PackageItems @param default_arch [in] the default architecture @param a [in] the promise Attributes for this operation @param pp [in] the Promise for this operation @param result [inout] the PromiseResult for this operation @returns boolean pass/fail of command run */ static bool PackageListInstalledFromCommand(EvalContext *ctx, PackageItem **installed_list, const char *default_arch, Attributes a, const Promise *pp, PromiseResult *result) { if (a.packages.package_list_update_command != NULL) { time_t horizon = 24 * 60, now = time(NULL); bool call_update = true; struct stat sb; char update_timestamp_file[PATH_MAX]; snprintf(update_timestamp_file, sizeof(update_timestamp_file), "%s%cstate%csoftware_update_timestamp_%s", GetWorkDir(), FILE_SEPARATOR, FILE_SEPARATOR, ReadLastNode(RealPackageManager(a.packages.package_add_command))); if (stat(update_timestamp_file, &sb) != -1) { if (a.packages.package_list_update_ifelapsed != CF_NOINT) { horizon = a.packages.package_list_update_ifelapsed; } char *rel, *action; if (now - sb.st_mtime < horizon * 60) { rel = "less"; action = "Not updating"; call_update = false; } else { rel = "more"; action = "Updating"; } Log(LOG_LEVEL_VERBOSE, "'%s' is %s than %i minutes old. %s package list.", update_timestamp_file, rel, a.packages.package_list_update_ifelapsed, action); } else { Log(LOG_LEVEL_VERBOSE, "'%s' does not exist. Updating package list.", update_timestamp_file); } if (call_update) { Log(LOG_LEVEL_VERBOSE, "Calling package list update command: '%s'", a.packages.package_list_update_command); ExecPackageCommand(ctx, a.packages.package_list_update_command, false, false, a, pp, result); // Touch timestamp file. int err = utime(update_timestamp_file, NULL); if (err < 0) { if (errno == ENOENT) { int fd = open(update_timestamp_file, O_WRONLY | O_CREAT, 0600); if (fd >= 0) { close(fd); } else { Log(LOG_LEVEL_ERR, "Could not create timestamp file '%s'. (open: '%s')", update_timestamp_file, GetErrorStr()); } } else { Log(LOG_LEVEL_ERR, "Could not update timestamp file '%s'. (utime: '%s')", update_timestamp_file, GetErrorStr()); } } } } if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, " ???????????????????????????????????????????????????????????????"); Log(LOG_LEVEL_VERBOSE, " Reading package list from %s", a.packages.package_list_command); Log(LOG_LEVEL_VERBOSE, " ???????????????????????????????????????????????????????????????"); } else { Log(LOG_LEVEL_VERBOSE, "Reading package list from '%s'", a.packages.package_list_command); } FILE *fin; if (a.packages.package_commands_useshell) { if ((fin = cf_popen_sh(a.packages.package_list_command, "r")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open the package list with command '%s'. (cf_popen_sh: %s)", a.packages.package_list_command, GetErrorStr()); return false; } } else if ((fin = cf_popen(a.packages.package_list_command, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open the package list with command '%s'. (cf_popen: %s)", a.packages.package_list_command, GetErrorStr()); return false; } const int reset = true, update = false; size_t buf_size = CF_BUFSIZE; char *buf = xmalloc(buf_size); for (;;) { ssize_t res = CfReadLine(&buf, &buf_size, fin); if (res == -1) { if (!feof(fin)) { Log(LOG_LEVEL_ERR, "Unable to read list of packages from command '%s'. (fread: %s)", a.packages.package_list_command, GetErrorStr()); cf_pclose(fin); free(buf); return false; } else { break; } } if (a.packages.package_multiline_start) { if (FullTextMatch(ctx, a.packages.package_multiline_start, buf)) { PrependMultiLinePackageItem(ctx, installed_list, buf, reset, default_arch, a, pp); } else { PrependMultiLinePackageItem(ctx, installed_list, buf, update, default_arch, a, pp); } } else { if (!FullTextMatch(ctx, a.packages.package_installed_regex, buf)) { Log(LOG_LEVEL_VERBOSE, "Package line '%s' did not match the package_installed_regex pattern", buf); continue; } if (!PrependListPackageItem(ctx, installed_list, buf, default_arch, a, pp)) { Log(LOG_LEVEL_VERBOSE, "Package line '%s' did not match one of the package_list_(name|version|arch)_regex patterns", buf); continue; } } } if (a.packages.package_multiline_start) { PrependMultiLinePackageItem(ctx, installed_list, buf, reset, default_arch, a, pp); } free(buf); return cf_pclose(fin) == 0; } /** @brief Writes the software inventory Called by VerifyInstalledPackages * calls GetSoftwareCacheFilename to get the inventory CSV filename * for each PackageManager in the list * * for each PackageItem in the PackageManager's list * * write name, version, architecture, manager name @param ctx [in] The evaluation context @param list [in] a list of PackageManagers */ static void ReportSoftware(PackageManager *list) { FILE *fout; PackageManager *mp = NULL; PackageItem *pi; char name[CF_BUFSIZE]; GetSoftwareCacheFilename(name); if ((fout = fopen(name, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Cannot open the destination file '%s'. (fopen: %s)", name, GetErrorStr()); return; } Writer *writer_installed = FileWriter(fout); CsvWriter *c = CsvWriterOpen(writer_installed); if (c) { for (mp = list; mp != NULL; mp = mp->next) { for (pi = mp->pack_list; pi != NULL; pi = pi->next) { CsvWriterField(c, pi->name); CsvWriterField(c, pi->version); CsvWriterField(c, pi->arch); CsvWriterField(c, ReadLastNode(RealPackageManager(mp->manager))); CsvWriterNewRecord(c); } } CsvWriterClose(c); } else { Log(LOG_LEVEL_ERR, "Cannot write CSV to file '%s'", name); } WriterClose(writer_installed); } /** @brief Invalidates the software inventory Called by ExecuteSchedule and ExecutePatch * calls GetSoftwareCacheFilename to get the inventory CSV filename * sets atime and mtime on that file to 0 */ static void InvalidateSoftwareCache(void) { char name[CF_BUFSIZE]; struct utimbuf epoch = { 0, 0 }; GetSoftwareCacheFilename(name); if (utime(name, &epoch) != 0) { if (errno != ENOENT) { Log(LOG_LEVEL_ERR, "Cannot mark software cache as invalid. (utimes: %s)", GetErrorStr()); } } } /** @brief Gets the cached list of installed packages from file Called by VerifyInstalledPackages * calls GetSoftwareCacheFilename to get the inventory CSV filename * respects a.packages.package_list_update_ifelapsed, returns NULL if file is too old * parses the CSV out of the file (name, version, arch, manager) with each limited to 250 chars * for each line * * if architecture is "default", replace it with default_arch * * if the package manager name matches, call PrependPackageItem @param ctx [in] The evaluation context @param manager [in] the PackageManager we want @param default_arch [in] the default architecture @param a [in] the promise Attributes for this operation @param pp [in] the Promise for this operation @returns list of PackageItems */ static PackageItem *GetCachedPackageList(EvalContext *ctx, PackageManager *manager, const char *default_arch, Attributes a, const Promise *pp) { PackageItem *list = NULL; char name[CF_MAXVARSIZE], version[CF_MAXVARSIZE], arch[CF_MAXVARSIZE], mgr[CF_MAXVARSIZE], line[CF_BUFSIZE]; char thismanager[CF_MAXVARSIZE]; FILE *fin; time_t horizon = 24 * 60, now = time(NULL); struct stat sb; GetSoftwareCacheFilename(name); if (stat(name, &sb) == -1) { return NULL; } if (a.packages.package_list_update_ifelapsed != CF_NOINT) { horizon = a.packages.package_list_update_ifelapsed; } if (now - sb.st_mtime < horizon * 60) { Log(LOG_LEVEL_VERBOSE, "Cache file '%s' exists and is sufficiently fresh according to (package_list_update_ifelapsed)", name); } else { Log(LOG_LEVEL_VERBOSE, "Cache file '%s' exists, but it is out of date (package_list_update_ifelapsed)", name); return NULL; } if ((fin = fopen(name, "r")) == NULL) { Log(LOG_LEVEL_INFO, "Cannot open the source log '%s' - you need to run a package discovery promise to create it in cf-agent. (fopen: %s)", name, GetErrorStr()); return NULL; } /* Max 2016 entries - at least a week */ snprintf(thismanager, CF_MAXVARSIZE - 1, "%s", ReadLastNode(RealPackageManager(manager->manager))); int linenumber = 0; for(;;) { if (fgets(line, sizeof(line), fin) == NULL) { if (ferror(fin)) { UnexpectedError("Failed to read line %d from stream '%s'", linenumber+1, name); break; } else /* feof */ { break; } } ++linenumber; int scancount = sscanf(line, "%250[^,],%250[^,],%250[^,],%250[^\r\n]", name, version, arch, mgr); if (scancount != 4) { Log(LOG_LEVEL_VERBOSE, "Could only read %d values from line %d in '%s'", scancount, linenumber, name); } /* * Transition to explicit default architecture, if package manager * supports it. * * If old cache contains entries with 'default' architecture, and * package method is updated to detect this architecture, on next * execution update this architecture to the real one. */ if (!strcmp(arch, "default")) { strlcpy(arch, default_arch, CF_MAXVARSIZE); } if (strcmp(thismanager, mgr) == 0) { PrependPackageItem(ctx, &list, name, version, arch, pp); } } fclose(fin); return list; } /** @brief Verifies installed packages for a single Promise Called by VerifyPackagesPromise * from all_mgrs, gets the package manager matching a.packages.package_list_command * populate manager->pack_list with GetCachedPackageList * on Windows, use NovaWin_PackageListInstalledFromAPI if a.packages.package_list_command is set to PACKAGE_LIST_COMMAND_WINAPI * on other platforms, use PackageListInstalledFromCommand * call ReportSoftware to save the installed packages inventory * if a.packages.package_patch_list_command is set, use it and parse each line with a.packages.package_patch_installed_regex; if it matches, call PrependPatchItem * call ReportPatches to save the available updates inventory (Enterprise only) @param ctx [in] The evaluation context @param all_mgrs [in] a list of PackageManagers @param default_arch [in] the default architecture @param a [in] the promise Attributes for this operation @param pp [in] the Promise for this operation @param result [inout] the PromiseResult for this operation @returns boolean pass/fail of verification */ static int VerifyInstalledPackages(EvalContext *ctx, PackageManager **all_mgrs, const char *default_arch, Attributes a, const Promise *pp, PromiseResult *result) { PackageManager *manager = GetPackageManager(all_mgrs, a.packages.package_list_command, PACKAGE_ACTION_NONE, PACKAGE_ACTION_POLICY_NONE); if (manager == NULL) { Log(LOG_LEVEL_ERR, "Can't create a package manager envelope for '%s'", a.packages.package_list_command); return false; } if (manager->pack_list != NULL) { Log(LOG_LEVEL_VERBOSE, "Already have a package list for this manager"); return true; } manager->pack_list = GetCachedPackageList(ctx, manager, default_arch, a, pp); if (manager->pack_list != NULL) { Log(LOG_LEVEL_VERBOSE, "Already have a (cached) package list for this manager "); return true; } if (a.packages.package_list_command == NULL) { /* skip */ } #ifdef __MINGW32__ else if (strcmp(a.packages.package_list_command, PACKAGE_LIST_COMMAND_WINAPI) == 0) { if (!NovaWin_PackageListInstalledFromAPI(ctx, &(manager->pack_list), a, pp)) { Log(LOG_LEVEL_ERR, "Could not get list of installed packages"); return false; } } #endif /* !__MINGW32__ */ else { if (!PackageListInstalledFromCommand(ctx, &(manager->pack_list), default_arch, a, pp, result)) { Log(LOG_LEVEL_ERR, "Could not get list of installed packages"); return false; } } ReportSoftware(INSTALLED_PACKAGE_LISTS); /* Now get available updates */ if (a.packages.package_patch_list_command != NULL) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, " ???????????????????????????????????????????????????????????????"); Log(LOG_LEVEL_VERBOSE, " Reading patches from %s", CommandArg0(a.packages.package_patch_list_command)); Log(LOG_LEVEL_VERBOSE, " ???????????????????????????????????????????????????????????????"); } else { Log(LOG_LEVEL_VERBOSE, "Reading patches from '%s'", CommandArg0(a.packages.package_patch_list_command)); } if ((!a.packages.package_commands_useshell) && (!IsExecutable(CommandArg0(a.packages.package_patch_list_command)))) { Log(LOG_LEVEL_ERR, "The proposed patch list command '%s' was not executable", a.packages.package_patch_list_command); return false; } FILE *fin; if (a.packages.package_commands_useshell) { if ((fin = cf_popen_sh(a.packages.package_patch_list_command, "r")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open the patch list with command '%s'. (cf_popen_sh: %s)", a.packages.package_patch_list_command, GetErrorStr()); return false; } } else if ((fin = cf_popen(a.packages.package_patch_list_command, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open the patch list with command '%s'. (cf_popen: %s)", a.packages.package_patch_list_command, GetErrorStr()); return false; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); for (;;) { ssize_t res = CfReadLine(&vbuff, &vbuff_size, fin); if (res == -1) { if (!feof(fin)) { Log(LOG_LEVEL_ERR, "Unable to read list of patches from command '%s'. (fread: %s)", a.packages.package_patch_list_command, GetErrorStr()); cf_pclose(fin); free(vbuff); return false; } else { break; } } // assume patch_list_command lists available patches/updates by default if ((a.packages.package_patch_installed_regex == NULL) || (!FullTextMatch(ctx, a.packages.package_patch_installed_regex, vbuff))) { PrependPatchItem(ctx, &(manager->patch_avail), vbuff, manager->patch_list, default_arch, a, pp); continue; } if (!PrependPatchItem(ctx, &(manager->patch_list), vbuff, manager->patch_list, default_arch, a, pp)) { continue; } } cf_pclose(fin); free(vbuff); } if (a.packages.package_patch_list_command != NULL) { ReportPatches(INSTALLED_PACKAGE_LISTS); // Enterprise only } if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, " ???????????????????????????????????????????????????????????????"); Log(LOG_LEVEL_VERBOSE, " Done checking packages and patches "); Log(LOG_LEVEL_VERBOSE, " ???????????????????????????????????????????????????????????????"); } else { Log(LOG_LEVEL_VERBOSE, "Done checking packages and patches"); } return true; } /** Evaluate what needs to be done **/ /** @brief Finds the largest version of a package available in a file repository Called by SchedulePackageOp * match = false * for each directory in repositories * * try to match refAnyVer against each file * * if it matches and CompareVersions says it's the biggest found so far, copy the matched version and name into matchName and matchVers and set match to true * return match @param ctx [in] The evaluation context @param matchName [inout] the matched package name (written on match) @param matchVers [inout] the matched package version (written on match) @param refAnyVer [in] the regex to match against the filename to extract a version @param ver [in] the version sought @param repositories [in] the list of directories (file repositories) @param a [in] the promise Attributes for this operation @param pp [in] the Promise for this operation @param result [inout] the PromiseResult for this operation @returns boolean pass/fail of search */ int FindLargestVersionAvail(EvalContext *ctx, char *matchName, char *matchVers, const char *refAnyVer, const char *ver, Rlist *repositories, Attributes a, const Promise *pp, PromiseResult *result) /* Returns true if a version gt/ge ver is found in local repos, false otherwise */ { int match = false; // match any version if (!ver[0] || strcmp(ver, "*") == 0) { matchVers[0] = '\0'; } else { strlcpy(matchVers, ver, CF_MAXVARSIZE); } for (Rlist *rp = repositories; rp != NULL; rp = rp->next) { Dir *dirh = DirOpen(RlistScalarValue(rp)); if (dirh == NULL) { Log(LOG_LEVEL_ERR, "Can't open local directory '%s'. (opendir: %s)", RlistScalarValue(rp), GetErrorStr()); continue; } const struct dirent *dirp; while (NULL != (dirp = DirRead(dirh))) { if (FullTextMatch(ctx, refAnyVer, dirp->d_name)) { char *matchVer = ExtractFirstReference(refAnyVer, dirp->d_name); // check if match is largest so far if (CompareVersions(ctx, matchVer, matchVers, a, pp, result) == VERCMP_MATCH) { strlcpy(matchVers, matchVer, CF_MAXVARSIZE); strlcpy(matchName, dirp->d_name, CF_MAXVARSIZE); match = true; } } } DirClose(dirh); } Log(LOG_LEVEL_DEBUG, "FindLargestVersionAvail: largest version of '%s' is '%s' (match=%d)", matchName, matchVers, match); return match; } /** @brief Returns true if a package (n,v,a) is installed and v is larger than the installed version Called by SchedulePackageOp * for each known PackageManager, compare to attr.packages.package_list_command * bail out if no manager was found * for each PackageItem pi in the manager's package list * * if pi->name equals n and (a is "*" or a equals pi->arch) * * * record instV and instA * * * copy attr into attr2 and override the attr2.packages.package_select to PACKAGE_VERSION_COMPARATOR_LT * * * return CompareVersions of the new monster * return false if the above found no matches @param ctx [in] The evaluation context @param n [in] the specific name @param v [in] the specific version @param a [in] the specific architecture @param instV [inout] the matched package version (written on match) @param instA [inout] the matched package architecture (written on match) @param attr [in] the promise Attributes for this operation @param pp [in] the Promise for this operation @param result [inout] the PromiseResult for this operation @returns boolean if given (n,v,a) is newer than known packages */ static int IsNewerThanInstalled(EvalContext *ctx, const char *n, const char *v, const char *a, char *instV, char *instA, Attributes attr, const Promise *pp, PromiseResult *result) { PackageManager *mp = INSTALLED_PACKAGE_LISTS; while (mp != NULL) { if (strcmp(mp->manager, attr.packages.package_list_command) == 0) { break; } mp = mp->next; } if (NULL == mp) { Log(LOG_LEVEL_VERBOSE, "Found no package manager matching attr.packages.package_list_command '%s'", attr.packages.package_list_command == NULL ? "[empty]" : attr.packages.package_list_command); return false; } Log(LOG_LEVEL_VERBOSE, "Looking for an installed package older than (%s,%s,%s) [name,version,arch]", n, v, a); for (PackageItem *pi = mp->pack_list; pi != NULL; pi = pi->next) { if (strcmp(n, pi->name) == 0 && (strcmp(a, "*") == 0 || strcmp(a, pi->arch) == 0)) { Log(LOG_LEVEL_VERBOSE, "Found installed package (%s,%s,%s) [name,version,arch]", pi->name, pi->version, pi->arch); strlcpy(instV, pi->version, CF_MAXVARSIZE); strlcpy(instA, pi->arch, CF_MAXVARSIZE); /* Horrible */ Attributes attr2 = attr; attr2.packages.package_select = PACKAGE_VERSION_COMPARATOR_LT; return CompareVersions(ctx, pi->version, v, attr2, pp, result) == VERCMP_MATCH; } } Log(LOG_LEVEL_VERBOSE, "Package (%s,%s) [name,arch] is not installed", n, a); return false; } /** @brief Returns string version of a PackageAction @param pa [in] The PackageAction @returns string representation of pa or a ProgrammingError */ static const char *PackageAction2String(PackageAction pa) { switch (pa) { case PACKAGE_ACTION_ADD: return "installing"; case PACKAGE_ACTION_DELETE: return "uninstalling"; case PACKAGE_ACTION_REINSTALL: return "reinstalling"; case PACKAGE_ACTION_UPDATE: return "updating"; case PACKAGE_ACTION_ADDUPDATE: return "installing/updating"; case PACKAGE_ACTION_PATCH: return "patching"; case PACKAGE_ACTION_VERIFY: return "verifying"; default: ProgrammingError("CFEngine: internal error: illegal package action"); } } /** @brief Adds a specific package (name,version,arch) as specified by Attributes a to the scheduled operations Called by SchedulePackageOp. Either warn or fix, based on a->transaction.action. To fix, calls GetPackageManager and enqueues the desired operation and package with the returned manager @param ctx [in] The evaluation context @param a [in] the Attributes specifying how to compare @param mgr [in] the specific manager name @param pa [in] the PackageAction to enqueue @param name [in] the specific name @param version [in] the specific version @param arch [in] the specific architecture @param pp [in] the Promise for this operation @returns the promise result */ static PromiseResult AddPackageToSchedule(EvalContext *ctx, const Attributes *a, char *mgr, PackageAction pa, const char *name, const char *version, const char *arch, const Promise *pp) { switch (a->transaction.action) { case cfa_warn: cfPS_HELPER_3ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, *a, "Need to repair promise '%s' by '%s' package '%s'", pp->promiser, PackageAction2String(pa), name); return PROMISE_RESULT_WARN; case cfa_fix: { PackageManager *manager = GetPackageManager(&PACKAGE_SCHEDULE, mgr, pa, a->packages.package_changes); if (NULL == manager) { ProgrammingError("AddPackageToSchedule: Null package manager found!!!"); } PrependPackageItem(ctx, &(manager->pack_list), name, version, arch, pp); return PROMISE_RESULT_CHANGE; } default: ProgrammingError("CFEngine: internal error: illegal file action"); } } /** @brief Adds a specific patch (name,version,arch) as specified by Attributes a to the scheduled operations Called by SchedulePackageOp. Either warn or fix, based on a->transaction.action. To fix, calls GetPackageManager and enqueues the desired operation and package with the returned manager @param ctx [in] The evaluation context @param a [in] the Attributes specifying how to compare @param mgr [in] the specific manager name @param pa [in] the PackageAction to enqueue @param name [in] the specific name @param version [in] the specific version @param arch [in] the specific architecture @param pp [in] the Promise for this operation @returns the promise result */ static PromiseResult AddPatchToSchedule(EvalContext *ctx, const Attributes *a, char *mgr, PackageAction pa, const char *name, const char *version, const char *arch, const Promise *pp) { switch (a->transaction.action) { case cfa_warn: cfPS_HELPER_3ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, *a, "Need to repair promise '%s' by '%s' package '%s'", pp->promiser, PackageAction2String(pa), name); return PROMISE_RESULT_WARN; case cfa_fix: { PackageManager *manager = GetPackageManager(&PACKAGE_SCHEDULE, mgr, pa, a->packages.package_changes); if (NULL == manager) { ProgrammingError("AddPatchToSchedule: Null package manager found!!!"); } PrependPackageItem(ctx, &(manager->patch_list), name, version, arch, pp); return PROMISE_RESULT_CHANGE; } default: ProgrammingError("Illegal file action"); } } /** @brief Schedules a package operation based on the action, package state, and everything else. Called by VerifyPromisedPatch and CheckPackageState. This function has a complexity metric of 3 Googols. * if package_delete_convention or package_name_convention are given and apply to the operation, construct the package name from them (from PACKAGES_CONTEXT) * else, just use the given package name * warn about "*" in the package name * set package_select_in_range with magic * create PackageAction policy from the package_policy and then split ADDUPDATE into ADD or UPDATE based on "installed" * result starts as NOOP * switch(policy) * * case ADD and "installed": * * * if we have package_file_repositories * * * * use the package_name_convention to build the package name (from PACKAGES_CONTEXT_ANYVER, setting version to "*") * * * * if FindLargestVersionAvail finds the latest package version in the file repos, use that as the package name * * * AddPackageToSchedule package_add_command, ADD, package name, etc. * * case DELETE and (matched AND package_select_in_range) OR (installed AND no_version_specified): * * * fail promise unless package_delete_command * * * if we have package_file_repositories * * * * clean up the name string from any "repo" references and add the right file repo * * * AddPackageToSchedule package_delete_command, DELETE, package name, etc. * * case REINSTALL: * * * fail promise unless package_delete_command * * * fail promise if no_version_specified * * * if (matched AND package_select_in_range) OR (installed AND no_version_specified) do AddPackageToSchedule package_delete_command, DELETE, package name, etc. * * * AddPackageToSchedule package_add_command, ADD, package name, etc. * * case UPDATE: * * * if we have package_file_repositories * * * * use the package_name_convention to build the package name (from PACKAGES_CONTEXT_ANYVER, setting version to "*") * * * * if FindLargestVersionAvail finds the latest package version in the file repos, use that as the package name * * * if installed, IsNewerThanInstalled is checked, and if it returns false we don't update an up-to-date package * * * if installed or (matched AND package_select_in_range AND !no_version_specified) (this is the main update condition) * * * * if package_update_command is not given * * * * * if package_delete_convention is given, use it to build id_del (from PACKAGES_CONTEXT) * * * * * fail promise if package_update_command and package_add_command are not given * * * * * AddPackageToSchedule with package_delete_command, DELETE, id_del, etc * * * * * AddPackageToSchedule with package_add_command, ADD, package name, etc * * * * else we have package_update_command, so AddPackageToSchedule with package_update_command, UPDATE, package name, etc * * * else the package is not updateable: no match or not installed, fail promise * * case PATCH: * * * if matched and not installed, AddPatchToSchedule with package_patch_command, PATCH, package name, etc. * * case VERIFY: * * * if (matched and package_select_in_range) OR (installed AND no_version_specified), AddPatchToSchedule with package_verify_command, VERIFY, package name, etc. @param ctx [in] The evaluation context @param name [in] the specific name @param version [in] the specific version @param arch [in] the specific architecture @param installed [in] is the package installed? @param matched [in] is the package matched in the available list? @param no_version_specified [in] no version was specified in the promise @param a [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @returns the promise result */ static PromiseResult SchedulePackageOp(EvalContext *ctx, const char *name, const char *version, const char *arch, int installed, int matched, int no_version_specified, Attributes a, const Promise *pp) { char refAnyVerEsc[CF_EXPANDSIZE]; char largestVerAvail[CF_MAXVARSIZE]; char largestPackAvail[CF_MAXVARSIZE]; char id[CF_EXPANDSIZE]; Log(LOG_LEVEL_VERBOSE, "Checking if package (%s,%s,%s) [name,version,arch] " "is at the desired state (installed=%d,matched=%d)", name, version, arch, installed, matched); /* Now we need to know the name-convention expected by the package manager */ Buffer *expanded = BufferNew(); if ((a.packages.package_name_convention) || (a.packages.package_delete_convention)) { VarRef *ref_name = VarRefParseFromScope("name", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_name, name, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_version = VarRefParseFromScope("version", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_version, version, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_arch = VarRefParseFromScope("arch", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_arch, arch, CF_DATA_TYPE_STRING, "source=promise"); if ((a.packages.package_delete_convention) && (a.packages.package_policy == PACKAGE_ACTION_DELETE)) { ExpandScalar(ctx, NULL, PACKAGES_CONTEXT, a.packages.package_delete_convention, expanded); strlcpy(id, BufferData(expanded), CF_EXPANDSIZE); } else if (a.packages.package_name_convention) { ExpandScalar(ctx, NULL, PACKAGES_CONTEXT, a.packages.package_name_convention, expanded); strlcpy(id, BufferData(expanded), CF_EXPANDSIZE); } else { strlcpy(id, name, CF_EXPANDSIZE); } EvalContextVariableRemove(ctx, ref_name); VarRefDestroy(ref_name); EvalContextVariableRemove(ctx, ref_version); VarRefDestroy(ref_version); EvalContextVariableRemove(ctx, ref_arch); VarRefDestroy(ref_arch); } else { strlcpy(id, name, CF_EXPANDSIZE); } Log(LOG_LEVEL_VERBOSE, "Package promises to refer to itself as '%s' to the manager", id); if (strchr(id, '*')) { Log(LOG_LEVEL_VERBOSE, "Package name contains '*' -- perhaps " "a missing attribute (name/version/arch) should be specified"); } // This is very confusing int package_select_in_range; switch (a.packages.package_select) { case PACKAGE_VERSION_COMPARATOR_EQ: case PACKAGE_VERSION_COMPARATOR_GE: case PACKAGE_VERSION_COMPARATOR_LE: case PACKAGE_VERSION_COMPARATOR_NONE: Log(LOG_LEVEL_VERBOSE, "Package version seems to match criteria"); package_select_in_range = true; break; default: package_select_in_range = false; break; } PackageAction policy = a.packages.package_policy; if (policy == PACKAGE_ACTION_ADDUPDATE) /* Work out which: */ { if (installed) { policy = PACKAGE_ACTION_UPDATE; } else { policy = PACKAGE_ACTION_ADD; } } PromiseResult result = PROMISE_RESULT_NOOP; switch (policy) { case PACKAGE_ACTION_ADD: if (installed == 0) { if ((a.packages.package_file_repositories != NULL)) { Log(LOG_LEVEL_VERBOSE, "Package method specifies a file repository"); { VarRef *ref_name = VarRefParseFromScope("name", PACKAGES_CONTEXT_ANYVER); EvalContextVariablePut(ctx, ref_name, name, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_version = VarRefParseFromScope("version", PACKAGES_CONTEXT_ANYVER); EvalContextVariablePut(ctx, ref_version, "(.*)", CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_arch = VarRefParseFromScope("arch", PACKAGES_CONTEXT_ANYVER); EvalContextVariablePut(ctx, ref_arch, arch, CF_DATA_TYPE_STRING, "source=promise"); BufferClear(expanded); if (a.packages.package_name_convention) { ExpandScalar(ctx, NULL, PACKAGES_CONTEXT_ANYVER, a.packages.package_name_convention, expanded); } EvalContextVariableRemove(ctx, ref_name); VarRefDestroy(ref_name); EvalContextVariableRemove(ctx, ref_version); VarRefDestroy(ref_version); EvalContextVariableRemove(ctx, ref_arch); VarRefDestroy(ref_arch); } EscapeSpecialChars(BufferData(expanded), refAnyVerEsc, sizeof(refAnyVerEsc), "(.*)",""); if (FindLargestVersionAvail(ctx, largestPackAvail, largestVerAvail, refAnyVerEsc, version, a.packages.package_file_repositories, a, pp, &result)) { Log(LOG_LEVEL_VERBOSE, "Using latest version in file repositories; '%s'", largestPackAvail); strlcpy(id, largestPackAvail, CF_EXPANDSIZE); } else { Log(LOG_LEVEL_VERBOSE, "No package in file repositories satisfy version constraint"); break; } } else { Log(LOG_LEVEL_VERBOSE, "Package method does NOT specify a file repository"); } Log(LOG_LEVEL_VERBOSE, "Schedule package for addition"); if (a.packages.package_add_command == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package add command undefined"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_add_command, PACKAGE_ACTION_ADD, id, "any", "any", pp)); } else { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Package '%s' already installed, so we never add it again", pp->promiser); } break; case PACKAGE_ACTION_DELETE: // we're deleting a matched package found in a range OR an installed package with no version if ((matched && package_select_in_range) || (installed && no_version_specified)) { Log(LOG_LEVEL_VERBOSE, "Schedule package for deletion"); if (a.packages.package_delete_command == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package delete command undefined"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } // expand local repository in the name convention, if present if (a.packages.package_file_repositories) { Log(LOG_LEVEL_VERBOSE, "Package method specifies a file repository"); // remove any "$(repo)" from the name convention string if (strncmp(id, "$(firstrepo)", 12) == 0) { const char *idBuf = id + 12; // and add the correct repo const char *pathName = PrefixLocalRepository(a.packages.package_file_repositories, idBuf); if (pathName) { strlcpy(id, pathName, CF_EXPANDSIZE); Log(LOG_LEVEL_VERBOSE, "Expanded the package repository to '%s'", id); } else { Log(LOG_LEVEL_ERR, "Package '%s' can't be found " "in any of the listed repositories", idBuf); } } } else { Log(LOG_LEVEL_VERBOSE, "Package method does NOT specify a file repository"); } result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_delete_command, PACKAGE_ACTION_DELETE, id, "any", "any", pp)); } else { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Package deletion is as promised -- no match"); } break; case PACKAGE_ACTION_REINSTALL: if (a.packages.package_delete_command == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package delete command undefined"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } if (!no_version_specified) { Log(LOG_LEVEL_VERBOSE, "Schedule package for reinstallation"); if (a.packages.package_add_command == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package add command undefined"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } // we're deleting a matched package found in a range OR an installed package with no version if ((matched && package_select_in_range) || (installed && no_version_specified)) { result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_delete_command, PACKAGE_ACTION_DELETE, id, "any", "any", pp)); } result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_add_command, PACKAGE_ACTION_ADD, id, "any", "any", pp)); } else { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package reinstallation cannot be promised -- insufficient version info or no match"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } break; case PACKAGE_ACTION_UPDATE: { char inst_arch[CF_MAXVARSIZE]; char inst_ver[CF_MAXVARSIZE]; *inst_ver = '\0'; *inst_arch = '\0'; if ((a.packages.package_file_repositories != NULL)) { Log(LOG_LEVEL_VERBOSE, "Package method specifies a file repository"); { VarRef *ref_name = VarRefParseFromScope("name", PACKAGES_CONTEXT_ANYVER); EvalContextVariablePut(ctx, ref_name, name, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_version = VarRefParseFromScope("version", PACKAGES_CONTEXT_ANYVER); EvalContextVariablePut(ctx, ref_version, "(.*)", CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_arch = VarRefParseFromScope("arch", PACKAGES_CONTEXT_ANYVER); EvalContextVariablePut(ctx, ref_arch, arch, CF_DATA_TYPE_STRING, "source=promise"); BufferClear(expanded); ExpandScalar(ctx, NULL, PACKAGES_CONTEXT_ANYVER, a.packages.package_name_convention, expanded); EvalContextVariableRemove(ctx, ref_name); VarRefDestroy(ref_name); EvalContextVariableRemove(ctx, ref_version); VarRefDestroy(ref_version); EvalContextVariableRemove(ctx, ref_arch); VarRefDestroy(ref_arch); } EscapeSpecialChars(BufferData(expanded), refAnyVerEsc, sizeof(refAnyVerEsc), "(.*)",""); if (FindLargestVersionAvail(ctx, largestPackAvail, largestVerAvail, refAnyVerEsc, version, a.packages.package_file_repositories, a, pp, &result)) { Log(LOG_LEVEL_VERBOSE, "Using latest version in file repositories; '%s'", largestPackAvail); strlcpy(id, largestPackAvail, CF_EXPANDSIZE); } else { Log(LOG_LEVEL_VERBOSE, "No package in file repositories satisfy version constraint"); break; } } else { Log(LOG_LEVEL_VERBOSE, "Package method does NOT specify a file repository"); strlcpy(largestVerAvail, version, sizeof(largestVerAvail)); // user-supplied version } if (installed) { Log(LOG_LEVEL_VERBOSE, "Checking if latest available version is newer than installed..."); if (IsNewerThanInstalled(ctx, name, largestVerAvail, arch, inst_ver, inst_arch, a, pp, &result)) { Log(LOG_LEVEL_VERBOSE, "Installed package (%s,%s,%s) [name,version,arch] is older than latest available (%s,%s,%s) [name,version,arch] - updating", name, inst_ver, inst_arch, name, largestVerAvail, arch); } else { Log(LOG_LEVEL_VERBOSE, "Installed package is up to date, not updating"); break; } } if (installed || (matched && package_select_in_range && !no_version_specified)) { if (a.packages.package_update_command == NULL) { Log(LOG_LEVEL_VERBOSE, "Package update command undefined - failing over to delete then add"); // we need to have the version of installed package const char *id_del = id; if (a.packages.package_delete_convention) { if (*inst_ver == '\0') { inst_ver[0] = '*'; inst_ver[1] = '\0'; } if (*inst_arch == '\0') { inst_arch[0] = '*'; inst_arch[1] = '\0'; } VarRef *ref_name = VarRefParseFromScope("name", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_name, name, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_version = VarRefParseFromScope("version", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_version, inst_ver, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_arch = VarRefParseFromScope("arch", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_arch, inst_arch, CF_DATA_TYPE_STRING, "source=promise"); BufferClear(expanded); ExpandScalar(ctx, NULL, PACKAGES_CONTEXT, a.packages.package_delete_convention, expanded); id_del = BufferData(expanded); EvalContextVariableRemove(ctx, ref_name); VarRefDestroy(ref_name); EvalContextVariableRemove(ctx, ref_version); VarRefDestroy(ref_version); EvalContextVariableRemove(ctx, ref_arch); VarRefDestroy(ref_arch); } Log(LOG_LEVEL_VERBOSE, "Scheduling package with id '%s' for deletion", id_del); if (a.packages.package_add_command == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package add command undefined"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } if (a.packages.package_delete_command == NULL) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package delete command undefined"); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_delete_command, PACKAGE_ACTION_DELETE, id_del, "any", "any", pp)); result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_add_command, PACKAGE_ACTION_ADD, id, "any", "any", pp)); } else { Log(LOG_LEVEL_VERBOSE, "Schedule package for update"); result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_update_command, PACKAGE_ACTION_UPDATE, id, "any", "any", pp)); } } else { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Package '%s' cannot be updated -- no match or not installed", pp->promiser); result = PromiseResultUpdate_HELPER(pp, result, PROMISE_RESULT_FAIL); } break; } case PACKAGE_ACTION_PATCH: if (matched && (!installed)) { Log(LOG_LEVEL_VERBOSE, "Schedule package for patching"); result = PromiseResultUpdate_HELPER(pp, result, AddPatchToSchedule(ctx, &a, a.packages.package_patch_command, PACKAGE_ACTION_PATCH, id, "any", "any", pp)); } else { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Package patch state of '%s' is as promised -- already installed", pp->promiser); } break; case PACKAGE_ACTION_VERIFY: if ((matched && package_select_in_range) || (installed && no_version_specified)) { Log(LOG_LEVEL_VERBOSE, "Schedule package for verification"); result = PromiseResultUpdate_HELPER(pp, result, AddPackageToSchedule(ctx, &a, a.packages.package_verify_command, PACKAGE_ACTION_VERIFY, id, "any", "any", pp)); } else { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Package '%s' cannot be verified -- no match", pp->promiser); BufferDestroy(expanded); return PROMISE_RESULT_FAIL; } break; default: break; } BufferDestroy(expanded); return result; } /** @brief Compare a PackageItem to a specific package (n,v,arch) as specified by Attributes a Called by PatchMatch and PackageMatch. First, checks the package names are the same (according to CompareCSVName). Second, checks the architectures are the same or arch is "*" Third, checks the versions with CompareVersions or version is "*" @param ctx [in] The evaluation context @param n [in] the specific name @param v [in] the specific version @param arch [in] the specific architecture @param pi [in] the PackageItem to check @param a [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @param mode [in] the operating mode, informational for logging @returns the version comparison result */ VersionCmpResult ComparePackages(EvalContext *ctx, const char *n, const char *v, const char *arch, PackageItem *pi, Attributes a, const Promise *pp, const char *mode, PromiseResult *result) { Log(LOG_LEVEL_VERBOSE, "Comparing %s package (%s,%s,%s) " "to [%s] with given (%s,%s,%s) [name,version,arch]", mode, pi->name, pi->version, pi->arch, PackageVersionComparatorToString(a.packages.package_select), n, v, arch); if (CompareCSVName(n, pi->name) != 0) { return VERCMP_NO_MATCH; } Log(LOG_LEVEL_VERBOSE, "Matched %s name '%s'", mode, n); if (strcmp(arch, "*") != 0) { if (strcmp(arch, pi->arch) != 0) { return VERCMP_NO_MATCH; } Log(LOG_LEVEL_VERBOSE, "Matched %s arch '%s'", mode, arch); } else { Log(LOG_LEVEL_VERBOSE, "Matched %s wildcard arch '%s'", mode, arch); } if (strcmp(v, "*") == 0) { Log(LOG_LEVEL_VERBOSE, "Matched %s wildcard version '%s'", mode, v); return VERCMP_MATCH; } VersionCmpResult vc = CompareVersions(ctx, pi->version, v, a, pp, result); Log(LOG_LEVEL_VERBOSE, "Version comparison returned %s for %s package (%s,%s,%s) " "to [%s] with given (%s,%s,%s) [name,version,arch]", vc == VERCMP_MATCH ? "MATCH" : vc == VERCMP_NO_MATCH ? "NO_MATCH" : "ERROR", mode, pi->name, pi->version, pi->arch, PackageVersionComparatorToString(a.packages.package_select), n, v, arch); return vc; } /** @brief Finds a specific package (n,v,a) [name, version, architecture] as specified by Attributes attr Called by VerifyPromisedPatch. Goes through all the installed packages to find matches for the given attributes. The package manager is checked against attr.packages.package_list_command. The package name is checked as a regular expression. then (n,v,a) with ComparePackages. @param ctx [in] The evaluation context @param n [in] the specific name @param v [in] the specific version @param a [in] the specific architecture @param attr [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @param mode [in] the operating mode, informational for logging @returns the version comparison result */ static VersionCmpResult PatchMatch(EvalContext *ctx, const char *n, const char *v, const char *a, Attributes attr, const Promise *pp, const char* mode, PromiseResult *result) { PackageManager *mp; // This REALLY needs some commenting for (mp = INSTALLED_PACKAGE_LISTS; mp != NULL; mp = mp->next) { if (strcmp(mp->manager, attr.packages.package_list_command) == 0) { break; } } Log(LOG_LEVEL_VERBOSE, "PatchMatch: looking for %s to [%s] with given (%s,%s,%s) [name,version,arch] in package manager %s", mode, PackageVersionComparatorToString(attr.packages.package_select), n, v, a, mp->manager); for (PackageItem *pi = mp->patch_list; pi != NULL; pi = pi->next) { if (FullTextMatch(ctx, n, pi->name)) /* Check regexes */ { Log(LOG_LEVEL_VERBOSE, "PatchMatch: regular expression match succeeded for %s against %s", n, pi->name); return VERCMP_MATCH; } else { VersionCmpResult res = ComparePackages(ctx, n, v, a, pi, attr, pp, mode, result); if (res != VERCMP_NO_MATCH) { Log(LOG_LEVEL_VERBOSE, "PatchMatch: patch comparison for %s was decisive: %s", pi->name, res == VERCMP_MATCH ? "MATCH" : "ERROR"); return res; } } } Log(LOG_LEVEL_VERBOSE, "PatchMatch did not match the constraints of promise (%s,%s,%s) [name,version,arch]", n, v, a); return VERCMP_NO_MATCH; } /** @brief Finds a specific package (n,v,a) [name, version, architecture] as specified by Attributes attr Called by CheckPackageState. Goes through all the installed packages to find matches for the given attributes. The package manager is checked against attr.packages.package_list_command. The (n,v,a) search is done with ComparePackages. @param ctx [in] The evaluation context @param n [in] the specific name @param v [in] the specific version @param a [in] the specific architecture @param attr [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @param mode [in] the operating mode, informational for logging @returns the version comparison result */ static VersionCmpResult PackageMatch(EvalContext *ctx, const char *n, const char *v, const char *a, Attributes attr, const Promise *pp, const char* mode, PromiseResult *result) /* * Returns VERCMP_MATCH if any installed packages match (n,v,a), VERCMP_NO_MATCH otherwise, VERCMP_ERROR on error. * The mode is informational */ { PackageManager *mp = NULL; // This REALLY needs some commenting for (mp = INSTALLED_PACKAGE_LISTS; mp != NULL; mp = mp->next) { if (strcmp(mp->manager, attr.packages.package_list_command) == 0) { break; } } Log(LOG_LEVEL_VERBOSE, "PackageMatch: looking for %s (%s,%s,%s) [name,version,arch] in package manager %s", mode, n, v, a, mp->manager); for (PackageItem *pi = mp->pack_list; pi != NULL; pi = pi->next) { VersionCmpResult res = ComparePackages(ctx, n, v, a, pi, attr, pp, mode, result); if (res != VERCMP_NO_MATCH) { Log(LOG_LEVEL_VERBOSE, "PackageMatch: package comparison for %s %s was decisive: %s", mode, pi->name, res == VERCMP_MATCH ? "MATCH" : "ERROR"); return res; } } Log(LOG_LEVEL_VERBOSE, "PackageMatch did not find %s packages to match the constraints of promise (%s,%s,%s) [name,version,arch]", mode, n, v, a); return VERCMP_NO_MATCH; } /** @brief Check if the operation should be scheduled based on the package policy, if the package matches, and if it's installed Called by CheckPackageState. Uses a.packages.package_policy to determine operating mode. The use of matches and installed depends on the package_policy: * PACKAGE_ACTION_DELETE: schedule if (matches AND installed) * PACKAGE_ACTION_REINSTALL: schedule if (matches AND installed) * all other policies: schedule if (not matches OR not installed) @param ctx [in] The evaluation context @param a [in] the Attributes specifying the package policy @param pp [in] the Promise for this operation @param matches [in] whether the package matches @param installed [in] whether the package is installed @returns whether the package operation should be scheduled */ static int WillSchedulePackageOperation(EvalContext *ctx, Attributes a, const Promise *pp, int matches, int installed) { PackageAction policy = a.packages.package_policy; Log(LOG_LEVEL_DEBUG, "WillSchedulePackageOperation: on entry, action %s: package %s matches = %s, installed = %s.", PackageAction2String(policy), pp->promiser, matches ? "yes" : "no", installed ? "yes" : "no"); switch (policy) { case PACKAGE_ACTION_DELETE: if (matches && installed) { Log(LOG_LEVEL_VERBOSE, "WillSchedulePackageOperation: Package %s to be deleted is installed.", pp->promiser); return true; } else { Log(LOG_LEVEL_DEBUG, "WillSchedulePackageOperation: Package %s can't be deleted if it's not installed, NOOP.", pp->promiser); cfPS_HELPER_1ARG(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Package %s to be deleted does not exist anywhere", pp->promiser); } break; case PACKAGE_ACTION_REINSTALL: if (matches && installed) { Log(LOG_LEVEL_VERBOSE, "WillSchedulePackageOperation: Package %s to be reinstalled is already installed.", pp->promiser); return true; } else { Log(LOG_LEVEL_DEBUG, "WillSchedulePackageOperation: Package %s already installed, NOOP.", pp->promiser); cfPS_HELPER_1ARG(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Package '%s' already installed and matches criteria", pp->promiser); } break; default: if (!matches) // why do we schedule a 'not matched' operation? { return true; } else if (!installed) // matches and not installed { return true; } else // matches and installed { Log(LOG_LEVEL_DEBUG, "WillSchedulePackageOperation: Package %s already installed, NOOP.", pp->promiser); cfPS_HELPER_1ARG(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Package '%s' already installed and matches criteria", pp->promiser); } break; } return false; } /** @brief Checks the state of a specific package (name,version,arch) as specified by Attributes a Called by VerifyPromisedPackage. * copies a into a2, overrides a2.packages.package_select to PACKAGE_VERSION_COMPARATOR_EQ * VersionCmpResult installed = check if (name,*,arch) is installed with PackageMatch (note version override!) * if PackageMatch returned an error, fail the promise * VersionCmpResult matches = check if (name,version,arch) is installed with PackageMatch * if PackageMatch returned an error, fail the promise * if WillSchedulePackageOperation with "matches" and "installed" passes, call SchedulePackageOp on the package @param ctx [in] The evaluation context @param a [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @param name [in] the specific name @param version [in] the specific version @param arch [in] the specific architecture @param no_version [in] ignore the version, be cool @returns the promise result */ static PromiseResult CheckPackageState(EvalContext *ctx, Attributes a, const Promise *pp, const char *name, const char *version, const char *arch, bool no_version) { PromiseResult result = PROMISE_RESULT_NOOP; /* Horrible */ Attributes a2 = a; a2.packages.package_select = PACKAGE_VERSION_COMPARATOR_EQ; VersionCmpResult installed = PackageMatch(ctx, name, "*", arch, a2, pp, "[installed]", &result); Log(LOG_LEVEL_VERBOSE, "CheckPackageState: Installed package match for (%s,%s,%s) [name,version,arch] was decisive: %s", name, "*", arch, installed == VERCMP_MATCH ? "MATCH" : "ERROR-OR-NOMATCH"); if (installed == VERCMP_ERROR) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a2, "Failure trying to compare installed package versions"); result = PromiseResultUpdate_HELPER(pp, result, PROMISE_RESULT_FAIL); return result; } VersionCmpResult matches = PackageMatch(ctx, name, version, arch, a2, pp, "[available]", &result); Log(LOG_LEVEL_VERBOSE, "CheckPackageState: Available package match for (%s,%s,%s) [name,version,arch] was decisive: %s", name, version, arch, matches == VERCMP_MATCH ? "MATCH" : "ERROR-OR-NOMATCH"); if (matches == VERCMP_ERROR) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a2, "Failure trying to compare available package versions"); result = PromiseResultUpdate_HELPER(pp, result, PROMISE_RESULT_FAIL); return result; } if (WillSchedulePackageOperation(ctx, a2, pp, matches, installed)) { Log(LOG_LEVEL_VERBOSE, "CheckPackageState: matched package (%s,%s,%s) [name,version,arch]; scheduling operation", name, version, arch); return SchedulePackageOp(ctx, name, version, arch, installed, matches, no_version, a, pp); } return result; } /** @brief Verifies a promised patch operation as defined by a and pp Called by VerifyPackagesPromise for the patch operation. * package name is pp->promiser * installed and matches counts = 0 * copies a into a2 and overrides a2.packages.package_select to PACKAGE_VERSION_COMPARATOR_EQ * promise result starts as NOOP * if package version is given * * for arch = each architecture requested in a2, or (if none given) any architecture "*" * * * installed1 = PatchMatch(a2, name, any version "*", any architecture "*") * * * matches1 = PatchMatch(a2, name, requested version, arch) * * * if either installed1 or matches1 failed, return promise error * * * else, installed += installed1; matches += matches1 * else if package_version_regex is given * * assume that package_name_regex and package_arch_regex are also given and use the 3 regexes to extract name, version, arch * * * installed = PatchMatch(a2, matched name, any version "*", any architecture "*") * * * matches = PatchMatch(a2, matched name, matched version, matched architecture) * * * if either installed or matches failed, return promise error * else (no explicit version is given) (SAME LOOP AS EXPLICIT VERSION LOOP ABOVE) * * no_version = true * * for arch = each architecture requested in a2, or (if none given) any architecture "*" * * * requested version = any version '*' * * * installed1 = PatchMatch(a2, name, any version "*", any architecture "*") * * * matches1 = PatchMatch(a2, name, requested version '*', arch) * * * if either installed1 or matches1 failed, return promise error * * * else, installed += installed1; matches += matches1 * finally, call SchedulePackageOp with the found name, version, arch, installed, matches, no_version @param ctx [in] The evaluation context @param a [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @returns the promise result (failure or NOOP) */ static PromiseResult VerifyPromisedPatch(EvalContext *ctx, Attributes a, const Promise *pp) { char version[CF_MAXVARSIZE]; char name[CF_MAXVARSIZE]; char arch[CF_MAXVARSIZE]; char *package = pp->promiser; int matches = 0, installed = 0, no_version = false; Rlist *rp; /* Horrible */ Attributes a2 = a; a2.packages.package_select = PACKAGE_VERSION_COMPARATOR_EQ; PromiseResult result = PROMISE_RESULT_NOOP; if (a2.packages.package_version) /* The version is specified explicitly */ { // Note this loop will run if rp is NULL for (rp = a2.packages.package_architectures; ; rp = rp->next) { strlcpy(name, pp->promiser, CF_MAXVARSIZE); strlcpy(version, a2.packages.package_version, CF_MAXVARSIZE); strlcpy(arch, NULL == rp ? "*" : RlistScalarValue(rp), CF_MAXVARSIZE); VersionCmpResult installed1 = PatchMatch(ctx, name, "*", "*", a2, pp, "[installed1]", &result); VersionCmpResult matches1 = PatchMatch(ctx, name, version, arch, a2, pp, "[available1]", &result); if ((installed1 == VERCMP_ERROR) || (matches1 == VERCMP_ERROR)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a2, "Failure trying to compare package versions"); result = PromiseResultUpdate_HELPER(pp, result, PROMISE_RESULT_FAIL); return result; } installed += installed1; matches += matches1; if (NULL == rp) break; // Note we exit the loop explicitly here } } else if (a2.packages.package_version_regex) // version is not given, but a version regex is { /* The name, version and arch are to be extracted from the promiser */ strlcpy(version, ExtractFirstReference(a2.packages.package_version_regex, package), CF_MAXVARSIZE); strlcpy(name, ExtractFirstReference(a2.packages.package_name_regex, package), CF_MAXVARSIZE); strlcpy(arch, ExtractFirstReference(a2.packages.package_arch_regex, package), CF_MAXVARSIZE); installed = PatchMatch(ctx, name, "*", "*", a2, pp, "[installed]", &result); matches = PatchMatch(ctx, name, version, arch, a2, pp, "[available]", &result); if ((installed == VERCMP_ERROR) || (matches == VERCMP_ERROR)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a2, "Failure trying to compare package versions"); result = PromiseResultUpdate_HELPER(pp, result, PROMISE_RESULT_FAIL); return result; } } else // the desired package version was not specified { no_version = true; // Note this loop will run if rp is NULL for (rp = a2.packages.package_architectures; ; rp = rp->next) { strlcpy(name, pp->promiser, CF_MAXVARSIZE); strlcpy(version, "*", CF_MAXVARSIZE); strlcpy(arch, NULL == rp ? "*" : RlistScalarValue(rp), CF_MAXVARSIZE); VersionCmpResult installed1 = PatchMatch(ctx, name, "*", "*", a2, pp, "[installed1]", &result); VersionCmpResult matches1 = PatchMatch(ctx, name, version, arch, a2, pp, "[available1]", &result); if ((installed1 == VERCMP_ERROR) || (matches1 == VERCMP_ERROR)) { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a2, "Failure trying to compare package versions"); result = PromiseResultUpdate_HELPER(pp, result, PROMISE_RESULT_FAIL); return result; } installed += installed1; matches += matches1; if (NULL == rp) break; // Note we exit the loop explicitly here } } Log(LOG_LEVEL_VERBOSE, "%d patch(es) matching the name '%s' already installed", installed, name); Log(LOG_LEVEL_VERBOSE, "%d patch(es) match the promise body's criteria fully", matches); SchedulePackageOp(ctx, name, version, arch, installed, matches, no_version, a, pp); return PROMISE_RESULT_NOOP; } /** @brief Verifies a promised package operation as defined by a and pp Called by VerifyPackagesPromise for any non-patch operation. * package name is pp->promiser * promise result starts as NOOP * if package version is given * * if no architecture given, the promise result comes from CheckPackageState with name, version, any architecture '*', no_version=false * * else if architectures were given, the promise result comes from CheckPackageState with name, version, arch, no_version=false FOR EACH ARCHITECTURE * else if package_version_regex is given * * assume that package_name_regex and package_arch_regex are also given and use the 3 regexes to extract name, version, arch * * if the arch extraction failed, use any architecture '*' * * the promise result comes from CheckPackageState with name, version, arch, no_version=false) * else (no explicit version is given) (SAME LOOP AS EXPLICIT VERSION LOOP ABOVE) * * if no architecture given, the promise result comes from CheckPackageState with name, any version "*", any architecture '*', no_version=true * * else if architectures were given, the promise result comes from CheckPackageState with name, any version "*", arch, no_version=true FOR EACH ARCHITECTURE @param ctx [in] The evaluation context @param a [in] the Attributes specifying how to compare @param pp [in] the Promise for this operation @returns the promise result as set by CheckPackageState */ static PromiseResult VerifyPromisedPackage(EvalContext *ctx, Attributes a, const Promise *pp) { const char *package = pp->promiser; PromiseResult result = PROMISE_RESULT_NOOP; if (a.packages.package_version) { /* The version is specified separately */ Log(LOG_LEVEL_VERBOSE, "Package version %s specified explicitly in promise body", a.packages.package_version); if (a.packages.package_architectures == NULL) { Log(LOG_LEVEL_VERBOSE, " ... trying any arch '*'"); result = PromiseResultUpdate_HELPER(pp, result, CheckPackageState(ctx, a, pp, package, a.packages.package_version, "*", false)); } else { for (Rlist *rp = a.packages.package_architectures; rp != NULL; rp = rp->next) { Log(LOG_LEVEL_VERBOSE, " ... trying listed arch '%s'", RlistScalarValue(rp)); result = PromiseResultUpdate_HELPER(pp, result, CheckPackageState(ctx, a, pp, package, a.packages.package_version, RlistScalarValue(rp), false)); } } } else if (a.packages.package_version_regex) { /* The name, version and arch are to be extracted from the promiser */ Log(LOG_LEVEL_VERBOSE, "Package version %s specified implicitly in promiser's name", a.packages.package_version_regex); char version[CF_MAXVARSIZE]; char name[CF_MAXVARSIZE]; char arch[CF_MAXVARSIZE]; strlcpy(version, ExtractFirstReference(a.packages.package_version_regex, package), CF_MAXVARSIZE); strlcpy(name, ExtractFirstReference(a.packages.package_name_regex, package), CF_MAXVARSIZE); strlcpy(arch, ExtractFirstReference(a.packages.package_arch_regex, package), CF_MAXVARSIZE); if (!arch[0]) { strlcpy(arch, "*", CF_MAXVARSIZE); } if (strcmp(arch, "CF_NOMATCH") == 0) // no match on arch regex, use any arch { strlcpy(arch, "*", CF_MAXVARSIZE); } Log(LOG_LEVEL_VERBOSE, " ... trying arch '%s' and version '%s'", arch, version); result = PromiseResultUpdate_HELPER(pp, result, CheckPackageState(ctx, a, pp, name, version, arch, false)); } else { Log(LOG_LEVEL_VERBOSE, "Package version was not specified"); if (a.packages.package_architectures == NULL) { Log(LOG_LEVEL_VERBOSE, " ... trying any arch '*' and any version '*'"); result = PromiseResultUpdate_HELPER(pp, result, CheckPackageState(ctx, a, pp, package, "*", "*", true)); } else { for (Rlist *rp = a.packages.package_architectures; rp != NULL; rp = rp->next) { Log(LOG_LEVEL_VERBOSE, " ... trying listed arch '%s' and any version '*'", RlistScalarValue(rp)); result = PromiseResultUpdate_HELPER(pp, result, CheckPackageState(ctx, a, pp, package, "*", RlistScalarValue(rp), true)); } } } return result; } /** Execute scheduled operations **/ /** @brief Central dispatcher for scheduled operations Called by ExecutePackageSchedule. Almost identical to ExecutePatch. * verify = false * for each PackageManager pm in the schedule * * if pm->pack_list is empty or the scheduled pm->action doesn't match the given action, skip this pm * * estimate the size of the command string from pm->pack_list and pm->policy (SHOULD USE Buffer) * * from the first PackageItem in pm->pack_list, get the Promise pp and its Attributes a * * switch(action) * * * case ADD: * * * * command_string = a.packages.package_add_command + estimated_size room for package names * * * case DELETE: * * * * command_string = a.packages.package_delete_command + estimated_size room for package names * * * case UPDATE: * * * * command_string = a.packages.package_update_command + estimated_size room for package names * * * case VERIFY: * * * * command_string = a.packages.package_verify_command + estimated_size room for package names * * * * verify = true * * if the command string ends with $, run it with ExecPackageCommand(command, verify) and magic the promise evaluation * * else, switch(pm->policy) * * * case INDIVIDUAL: * * * * for each PackageItem in the pack_list, build the command and run it with ExecPackageCommand(command, verify) and magic the promise evaluation * * * * NOTE with file repositories and ADD/UPDATE operations, the package name gets the repo path too * * * * NOTE special treatment of PACKAGE_IGNORED_CFE_INTERNAL * * * case BULK: * * * * for all PackageItems in the pack_list, build the command and run it with ExecPackageCommand(command, verify) and magic the promise evaluation * * * * NOTE with file repositories and ADD/UPDATE operations, the package name gets the repo path too * * * * NOTE special treatment of PACKAGE_IGNORED_CFE_INTERNAL * * clean up command_string * if the operation was not a verification, InvalidateSoftwareCache @param ctx [in] The evaluation context @param schedule [in] the PackageManager list with the operations schedule @param action [in] the PackageAction desired @returns boolean success/fail (fail only on ProgrammingError, should never happen) */ static bool ExecuteSchedule(EvalContext *ctx, const PackageManager *schedule, PackageAction action) { bool verify = false; for (const PackageManager *pm = schedule; pm != NULL; pm = pm->next) { if (pm->action != action) { continue; } if (pm->pack_list == NULL) { continue; } size_t estimated_size = 0; for (const PackageItem *pi = pm->pack_list; pi != NULL; pi = pi->next) { size_t size = strlen(pi->name) + strlen(" "); switch (pm->policy) { case PACKAGE_ACTION_POLICY_INDIVIDUAL: if (size > estimated_size) { estimated_size = size + CF_MAXVARSIZE; } break; case PACKAGE_ACTION_POLICY_BULK: estimated_size += size + CF_MAXVARSIZE; break; default: break; } } const Promise *const pp = pm->pack_list->pp; Attributes a = GetPackageAttributes(ctx, pp); char *command_string = NULL; switch (action) { case PACKAGE_ACTION_ADD: Log(LOG_LEVEL_VERBOSE, "Execute scheduled package addition"); if (a.packages.package_add_command == NULL) { ProgrammingError("Package add command undefined"); return false; } Log(LOG_LEVEL_INFO, "Installing %-.39s...", pp->promiser); command_string = xmalloc(estimated_size + strlen(a.packages.package_add_command) + 2); strcpy(command_string, a.packages.package_add_command); break; case PACKAGE_ACTION_DELETE: Log(LOG_LEVEL_VERBOSE, "Execute scheduled package deletion"); if (a.packages.package_delete_command == NULL) { ProgrammingError("Package delete command undefined"); return false; } Log(LOG_LEVEL_INFO, "Deleting %-.39s...", pp->promiser); command_string = xmalloc(estimated_size + strlen(a.packages.package_delete_command) + 2); strcpy(command_string, a.packages.package_delete_command); break; case PACKAGE_ACTION_UPDATE: Log(LOG_LEVEL_VERBOSE, "Execute scheduled package update"); if (a.packages.package_update_command == NULL) { ProgrammingError("Package update command undefined"); return false; } Log(LOG_LEVEL_INFO, "Updating %-.39s...", pp->promiser); command_string = xcalloc(1, estimated_size + strlen(a.packages.package_update_command) + 2); strcpy(command_string, a.packages.package_update_command); break; case PACKAGE_ACTION_VERIFY: Log(LOG_LEVEL_VERBOSE, "Execute scheduled package verification"); if (a.packages.package_verify_command == NULL) { ProgrammingError("Package verify command undefined"); return false; } command_string = xmalloc(estimated_size + strlen(a.packages.package_verify_command) + 2); strcpy(command_string, a.packages.package_verify_command); verify = true; break; default: ProgrammingError("Unknown action attempted"); return false; } /* if the command ends with $ then we assume the package manager does not accept package names */ if (*(command_string + strlen(command_string) - 1) == '$') { *(command_string + strlen(command_string) - 1) = '\0'; Log(LOG_LEVEL_VERBOSE, "Command does not allow arguments"); PromiseResult result = PROMISE_RESULT_NOOP; EvalContextStackPushPromiseFrame(ctx, pp, false); if (EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL)) { if (ExecPackageCommand(ctx, command_string, verify, true, a, pp, &result)) { Log(LOG_LEVEL_VERBOSE, "Package schedule execution ok (outcome cannot be promised by cf-agent)"); } else { Log(LOG_LEVEL_ERR, "Package schedule execution failed"); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); EvalContextLogPromiseIterationOutcome(ctx, pp, result); } else { strcat(command_string, " "); Log(LOG_LEVEL_VERBOSE, "Command prefix '%s'", command_string); switch (pm->policy) { case PACKAGE_ACTION_POLICY_INDIVIDUAL: for (const PackageItem *pi = pm->pack_list; pi != NULL; pi = pi->next) { const Promise *const ppi = pi->pp; Attributes a = GetPackageAttributes(ctx, ppi); char *offset = command_string + strlen(command_string); if ((a.packages.package_file_repositories) && ((action == PACKAGE_ACTION_ADD) || (action == PACKAGE_ACTION_UPDATE))) { const char *sp = PrefixLocalRepository(a.packages.package_file_repositories, pi->name); if (sp != NULL) { strcat(offset, sp); } else { continue; } } else { strcat(offset, pi->name); } PromiseResult result = PROMISE_RESULT_NOOP; EvalContextStackPushPromiseFrame(ctx, pp, false); if (EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL)) { if (ExecPackageCommand(ctx, command_string, verify, true, a, ppi, &result)) { Log(LOG_LEVEL_VERBOSE, "Package schedule execution ok for '%s' (outcome cannot be promised by cf-agent)", pi->name); } else if (0 == strncmp(pi->name, PACKAGE_IGNORED_CFE_INTERNAL, strlen(PACKAGE_IGNORED_CFE_INTERNAL))) { Log(LOG_LEVEL_DEBUG, "ExecuteSchedule: Ignoring outcome for special package '%s'", pi->name); } else { Log(LOG_LEVEL_ERR, "Package schedule execution failed for '%s'", pi->name); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); EvalContextLogPromiseIterationOutcome(ctx, ppi, result); *offset = '\0'; } break; case PACKAGE_ACTION_POLICY_BULK: { for (const PackageItem *pi = pm->pack_list; pi != NULL; pi = pi->next) { if (pi->name) { char *offset = command_string + strlen(command_string); if (a.packages.package_file_repositories && (action == PACKAGE_ACTION_ADD || action == PACKAGE_ACTION_UPDATE)) { const char *sp = PrefixLocalRepository(a.packages.package_file_repositories, pi->name); if (sp != NULL) { strcpy(offset, sp); } else { break; } } else { strcpy(offset, pi->name); } strcat(command_string, " "); } } PromiseResult result = PROMISE_RESULT_NOOP; EvalContextStackPushPromiseFrame(ctx, pp, false); if (EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL)) { bool ok = ExecPackageCommand(ctx, command_string, verify, true, a, pp, &result); for (const PackageItem *pi = pm->pack_list; pi != NULL; pi = pi->next) { if (ok) { Log(LOG_LEVEL_VERBOSE, "Bulk package schedule execution ok for '%s' (outcome cannot be promised by cf-agent)", pi->name); } else if (0 == strncmp(pi->name, PACKAGE_IGNORED_CFE_INTERNAL, strlen(PACKAGE_IGNORED_CFE_INTERNAL))) { Log(LOG_LEVEL_DEBUG, "ExecuteSchedule: Ignoring outcome for special package '%s'", pi->name); } else { Log(LOG_LEVEL_ERR, "Bulk package schedule execution failed somewhere - unknown outcome for '%s'", pi->name); } } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); EvalContextLogPromiseIterationOutcome(ctx, pp, result); } break; default: break; } } if (command_string) { free(command_string); } } /* We have performed some modification operation on packages, our cache is invalid */ if (!verify) { InvalidateSoftwareCache(); } return true; } /** @brief Central dispatcher for scheduled patch operations Called by ExecutePackageSchedule. Almost identical to ExecuteSchedule except it only accepts the PATCH PackageAction and operates on the PackageManagers' patch_list. * for each PackageManager pm in the schedule * * if pm->patch_list is empty or the scheduled pm->action doesn't match the given action, skip this pm * * estimate the size of the command string from pm->patch_list and pm->policy (SHOULD USE Buffer) * * from the first PackageItem in pm->patch_list, get the Promise pp and its Attributes a * * switch(action) * * * case PATCH: * * * * command_string = a.packages.package_patch_command + estimated_size room for package names * * if the command string ends with $, run it with ExecPackageCommand(command, verify) and magic the promise evaluation * * else, switch(pm->policy) * * * case INDIVIDUAL: * * * * for each PackageItem in the patch_list, build the command and run it with ExecPackageCommand(command, verify) and magic the promise evaluation * * * * NOTE with file repositories and ADD/UPDATE operations, the package name gets the repo path too * * * * NOTE special treatment of PACKAGE_IGNORED_CFE_INTERNAL * * * case BULK: * * * * for all PackageItems in the patch_list, build the command and run it with ExecPackageCommand(command, verify) and magic the promise evaluation * * * * NOTE with file repositories and ADD/UPDATE operations, the package name gets the repo path too * * * * NOTE special treatment of PACKAGE_IGNORED_CFE_INTERNAL * * clean up command_string * InvalidateSoftwareCache @param ctx [in] The evaluation context @param schedule [in] the PackageManager list with the operations schedule @param action [in] the PackageAction desired @returns boolean success/fail (fail only on ProgrammingError, should never happen) */ static bool ExecutePatch(EvalContext *ctx, const PackageManager *schedule, PackageAction action) { for (const PackageManager *pm = schedule; pm != NULL; pm = pm->next) { if (pm->action != action) { continue; } if (pm->patch_list == NULL) { continue; } size_t estimated_size = 0; for (const PackageItem *pi = pm->patch_list; pi != NULL; pi = pi->next) { size_t size = strlen(pi->name) + strlen(" "); switch (pm->policy) { case PACKAGE_ACTION_POLICY_INDIVIDUAL: if (size > estimated_size) { estimated_size = size; } break; case PACKAGE_ACTION_POLICY_BULK: estimated_size += size; break; default: break; } } char *command_string = NULL; const Promise *const pp = pm->patch_list->pp; Attributes a = GetPackageAttributes(ctx, pp); switch (action) { case PACKAGE_ACTION_PATCH: Log(LOG_LEVEL_VERBOSE, "Execute scheduled package patch"); if (a.packages.package_patch_command == NULL) { ProgrammingError("Package patch command undefined"); return false; } command_string = xmalloc(estimated_size + strlen(a.packages.package_patch_command) + 2); strcpy(command_string, a.packages.package_patch_command); break; default: ProgrammingError("Unknown action attempted"); return false; } /* if the command ends with $ then we assume the package manager does not accept package names */ if (command_string[strlen(command_string) - 1] == '$') { command_string[strlen(command_string) - 1] = '\0'; Log(LOG_LEVEL_VERBOSE, "Command does not allow arguments"); PromiseResult result = PROMISE_RESULT_NOOP; EvalContextStackPushPromiseFrame(ctx, pp, false); if (EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL)) { if (ExecPackageCommand(ctx, command_string, false, true, a, pp, &result)) { Log(LOG_LEVEL_VERBOSE, "Package patching seemed to succeed (outcome cannot be promised by cf-agent)"); } else { Log(LOG_LEVEL_ERR, "Package patching failed"); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); EvalContextLogPromiseIterationOutcome(ctx, pp, result); } else { strcat(command_string, " "); Log(LOG_LEVEL_VERBOSE, "Command prefix '%s'", command_string); switch (pm->policy) { case PACKAGE_ACTION_POLICY_INDIVIDUAL: for (const PackageItem *pi = pm->patch_list; pi != NULL; pi = pi->next) { char *offset = command_string + strlen(command_string); strcat(offset, pi->name); PromiseResult result = PROMISE_RESULT_NOOP; EvalContextStackPushPromiseFrame(ctx, pp, false); if (EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL)) { if (ExecPackageCommand(ctx, command_string, false, true, a, pp, &result)) { Log(LOG_LEVEL_VERBOSE, "Package schedule execution ok for '%s' (outcome cannot be promised by cf-agent)", pi->name); } else if (0 == strncmp(pi->name, PACKAGE_IGNORED_CFE_INTERNAL, strlen(PACKAGE_IGNORED_CFE_INTERNAL))) { Log(LOG_LEVEL_DEBUG, "ExecutePatch: Ignoring outcome for special package '%s'", pi->name); } else { Log(LOG_LEVEL_ERR, "Package schedule execution failed for '%s'", pi->name); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); EvalContextLogPromiseIterationOutcome(ctx, pp, result); *offset = '\0'; } break; case PACKAGE_ACTION_POLICY_BULK: for (const PackageItem *pi = pm->patch_list; pi != NULL; pi = pi->next) { if (pi->name) { strcat(command_string, pi->name); strcat(command_string, " "); } } PromiseResult result = PROMISE_RESULT_NOOP; EvalContextStackPushPromiseFrame(ctx, pp, false); if (EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL)) { bool ok = ExecPackageCommand(ctx, command_string, false, true, a, pp, &result); for (const PackageItem *pi = pm->patch_list; pi != NULL; pi = pi->next) { if (ok) { Log(LOG_LEVEL_VERBOSE, "Bulk package schedule execution ok for '%s' (outcome cannot be promised by cf-agent)", pi->name); } else if (0 == strncmp(pi->name, PACKAGE_IGNORED_CFE_INTERNAL, strlen(PACKAGE_IGNORED_CFE_INTERNAL))) { Log(LOG_LEVEL_DEBUG, "ExecutePatch: Ignoring outcome for special package '%s'", pi->name); } else { Log(LOG_LEVEL_ERR, "Bulk package schedule execution failed somewhere - unknown outcome for '%s'", pi->name); } } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); EvalContextLogPromiseIterationOutcome(ctx, pp, result); break; default: break; } } if (command_string) { free(command_string); } } /* We have performed some operation on packages, our cache is invalid */ InvalidateSoftwareCache(); return true; } /** @brief Ordering manager for scheduled package operations Called by ExecuteScheduledPackages. * ExecuteSchedule(schedule, DELETE) * ExecuteSchedule(schedule, ADD) * ExecuteSchedule(schedule, UPDATE) * ExecutePatch(schedule, PATCH) * ExecuteSchedule(schedule, VERIFY) @param ctx [in] The evaluation context @param schedule [in] the PackageManager list with the operations schedule */ static void ExecutePackageSchedule(EvalContext *ctx, PackageManager *schedule) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); Log(LOG_LEVEL_VERBOSE, " Offering these package-promise suggestions to the managers"); Log(LOG_LEVEL_VERBOSE, " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); } else { Log(LOG_LEVEL_VERBOSE, "Offering the following package-promise suggestions to the managers"); } /* Normal ordering */ Log(LOG_LEVEL_VERBOSE, "Deletion schedule..."); if (!ExecuteSchedule(ctx, schedule, PACKAGE_ACTION_DELETE)) { Log(LOG_LEVEL_ERR, "Aborting package schedule"); return; } Log(LOG_LEVEL_VERBOSE, "Addition schedule..."); if (!ExecuteSchedule(ctx, schedule, PACKAGE_ACTION_ADD)) { return; } Log(LOG_LEVEL_VERBOSE, "Update schedule..."); if (!ExecuteSchedule(ctx, schedule, PACKAGE_ACTION_UPDATE)) { return; } Log(LOG_LEVEL_VERBOSE, "Patch schedule..."); if (!ExecutePatch(ctx, schedule, PACKAGE_ACTION_PATCH)) { return; } Log(LOG_LEVEL_VERBOSE, "Verify schedule..."); if (!ExecuteSchedule(ctx, schedule, PACKAGE_ACTION_VERIFY)) { return; } } /** * @brief Execute the full package schedule. * * Called by cf-agent only. * */ void ExecuteScheduledPackages(EvalContext *ctx) { if (PACKAGE_SCHEDULE) { ExecutePackageSchedule(ctx, PACKAGE_SCHEDULE); } } /** Cleanup **/ /** * @brief Clean the package schedule and installed lists. * * Called by cf-agent only. Cleans bookkeeping data. * */ void CleanScheduledPackages(void) { DeletePackageManagers(PACKAGE_SCHEDULE); PACKAGE_SCHEDULE = NULL; DeletePackageManagers(INSTALLED_PACKAGE_LISTS); INSTALLED_PACKAGE_LISTS = NULL; } /** Utils **/ static PackageManager *GetPackageManager(PackageManager **lists, char *mgr, PackageAction pa, PackageActionPolicy policy) { PackageManager *np; Log(LOG_LEVEL_VERBOSE, "Looking for a package manager called '%s'", mgr); if (mgr == NULL || mgr[0] == '\0') { Log(LOG_LEVEL_ERR, "Attempted to create a package manager with no name"); return NULL; } for (np = *lists; np != NULL; np = np->next) { if ((strcmp(np->manager, mgr) == 0) && (policy == np->policy)) { return np; } } np = xcalloc(1, sizeof(PackageManager)); np->manager = xstrdup(mgr); np->action = pa; np->policy = policy; np->next = *lists; *lists = np; return np; } static void DeletePackageItems(PackageItem * pi) { while (pi) { PackageItem *next = pi->next; free(pi->name); free(pi->version); free(pi->arch); PromiseDestroy(pi->pp); free(pi); pi = next; } } static void DeletePackageManagers(PackageManager *np) { while (np) { PackageManager *next = np->next; DeletePackageItems(np->pack_list); DeletePackageItems(np->patch_list); DeletePackageItems(np->patch_avail); free(np->manager); free(np); np = next; } } const char *PrefixLocalRepository(const Rlist *repositories, const char *package) { static char quotedPath[CF_MAXVARSIZE]; /* GLOBAL_R, no need to initialize */ struct stat sb; char path[CF_BUFSIZE]; for (const Rlist *rp = repositories; rp != NULL; rp = rp->next) { if (strlcpy(path, RlistScalarValue(rp), sizeof(path)) < sizeof(path)) { AddSlash(path); if (strlcat(path, package, sizeof(path)) < sizeof(path) && stat(path, &sb) != -1) { snprintf(quotedPath, sizeof(quotedPath), "\"%s\"", path); return quotedPath; } } } return NULL; } bool ExecPackageCommand(EvalContext *ctx, char *command, int verify, int setCmdClasses, Attributes a, const Promise *pp, PromiseResult *result) { bool retval = true; char lineSafe[CF_BUFSIZE], *cmd; FILE *pfp; int packmanRetval = 0; if ((!a.packages.package_commands_useshell) && (!IsExecutable(CommandArg0(command)))) { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "The proposed package schedule command '%s' was not executable", command); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); return false; } if (DONTDO) { return true; } /* Use this form to avoid limited, intermediate argument processing - long lines */ if (a.packages.package_commands_useshell) { Log(LOG_LEVEL_VERBOSE, "Running %s in shell", command); if ((pfp = cf_popen_sh(command, "r")) == NULL) { cfPS_HELPER_2ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Couldn't start command '%20s'. (cf_popen_sh: %s)", command, GetErrorStr()); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); return false; } } else { if ((pfp = cf_popen(command, "r", true)) == NULL) { cfPS_HELPER_2ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Couldn't start command '%20s'. (cf_popen: %s)", command, GetErrorStr()); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); return false; } } Log(LOG_LEVEL_VERBOSE, "Executing %-.60s...", command); /* Look for short command summary */ for (cmd = command; (*cmd != '\0') && (*cmd != ' '); cmd++) { } while ((*(cmd - 1) != FILE_SEPARATOR) && (cmd >= command)) { cmd--; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pfp); if (res == -1) { if (!feof(pfp)) { cfPS_HELPER_2ARG(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to read output from command '%20s'. (fread: %s)", command, GetErrorStr()); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); cf_pclose(pfp); free(line); return false; } else { break; } } ReplaceStr(line, lineSafe, sizeof(lineSafe), "%", "%%"); Log(LOG_LEVEL_INFO, "Q:%20.20s ...:%s", cmd, lineSafe); if (verify && (line[0] != '\0')) { if (a.packages.package_noverify_regex) { if (FullTextMatch(ctx, a.packages.package_noverify_regex, line)) { cfPS_HELPER_2ARG(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Package verification error in %-.40s ... :%s", cmd, lineSafe); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); retval = false; } } } } free(line); packmanRetval = cf_pclose(pfp); if (verify && (a.packages.package_noverify_returncode != CF_NOINT)) { if (a.packages.package_noverify_returncode == packmanRetval) { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Package verification error (returned %d)", packmanRetval); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); retval = false; } else { cfPS_HELPER_1ARG(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Package verification succeeded (returned %d)", packmanRetval); *result = PromiseResultUpdate_HELPER(pp, *result, PROMISE_RESULT_FAIL); } } else if (verify && (a.packages.package_noverify_regex)) { if (retval) // set status if we succeeded above { cfPS_HELPER_0ARG(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Package verification succeeded (no match with package_noverify_regex)"); } } else if (setCmdClasses) // generic return code check { if (REPORT_THIS_PROMISE(pp)) { retval = VerifyCommandRetcode(ctx, packmanRetval, a, pp, result); } } return retval; } int PrependPackageItem(EvalContext *ctx, PackageItem ** list, const char *name, const char *version, const char *arch, const Promise *pp) { if (!list || !name[0] || !version[0] || !arch[0]) { return false; } Log(LOG_LEVEL_VERBOSE, "Package (%s,%s,%s) [name,version,arch] found", name, version, arch); PackageItem *pi = xmalloc(sizeof(PackageItem)); pi->next = *list; pi->name = xstrdup(name); pi->version = xstrdup(version); pi->arch = xstrdup(arch); *list = pi; /* Finally we need these for later schedule exec, once this iteration context has gone */ pi->pp = DeRefCopyPromise(ctx, pp); return true; } static int PackageInItemList(PackageItem * list, char *name, char *version, char *arch) { if (!name[0] || !version[0] || !arch[0]) { return false; } for (PackageItem *pi = list; pi != NULL; pi = pi->next) { if (strcmp(pi->name, name) == 0 && strcmp(pi->version, version) == 0 && strcmp(pi->arch, arch) == 0) { return true; } } return false; } static int PrependPatchItem(EvalContext *ctx, PackageItem ** list, char *item, PackageItem * chklist, const char *default_arch, Attributes a, const Promise *pp) { char name[CF_MAXVARSIZE]; char arch[CF_MAXVARSIZE]; char version[CF_MAXVARSIZE]; char vbuff[CF_MAXVARSIZE]; strlcpy(vbuff, ExtractFirstReference(a.packages.package_patch_name_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", name); /* trim */ strlcpy(vbuff, ExtractFirstReference(a.packages.package_patch_version_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", version); /* trim */ if (a.packages.package_patch_arch_regex) { strlcpy(vbuff, ExtractFirstReference(a.packages.package_patch_arch_regex, item), CF_MAXVARSIZE ); sscanf(vbuff, "%s", arch); /* trim */ } else { strlcpy(arch, default_arch, CF_MAXVARSIZE ); } if ((strcmp(name, "CF_NOMATCH") == 0) || (strcmp(version, "CF_NOMATCH") == 0) || (strcmp(arch, "CF_NOMATCH") == 0)) { return false; } Log(LOG_LEVEL_DEBUG, "PrependPatchItem: Patch line '%s', with name '%s', version '%s', arch '%s'", item, name, version, arch); if (PackageInItemList(chklist, name, version, arch)) { Log(LOG_LEVEL_VERBOSE, "Patch for (%s,%s,%s) [name,version,arch] found, but it appears to be installed already", name, version, arch); return false; } return PrependPackageItem(ctx, list, name, version, arch, pp); } static int PrependMultiLinePackageItem(EvalContext *ctx, PackageItem ** list, char *item, int reset, const char *default_arch, Attributes a, const Promise *pp) { static char name[CF_MAXVARSIZE] = ""; /* GLOBAL_X */ static char arch[CF_MAXVARSIZE] = ""; /* GLOBAL_X */ static char version[CF_MAXVARSIZE] = ""; /* GLOBAL_X */ static char vbuff[CF_MAXVARSIZE] = ""; /* GLOBAL_X */ if (reset) { if ((strcmp(name, "CF_NOMATCH") == 0) || (strcmp(version, "CF_NOMATCH") == 0)) { return false; } if ((strcmp(name, "") != 0) || (strcmp(version, "") != 0)) { Log(LOG_LEVEL_DEBUG, "PrependMultiLinePackageItem: Extracted package name '%s', version '%s', arch '%s'", name, version, arch); PrependPackageItem(ctx, list, name, version, arch, pp); } strcpy(name, "CF_NOMATCH"); strcpy(version, "CF_NOMATCH"); strcpy(arch, default_arch); } if (FullTextMatch(ctx, a.packages.package_list_name_regex, item)) { strlcpy(vbuff, ExtractFirstReference(a.packages.package_list_name_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", name); /* trim */ } if (FullTextMatch(ctx, a.packages.package_list_version_regex, item)) { strlcpy(vbuff, ExtractFirstReference(a.packages.package_list_version_regex, item), CF_MAXVARSIZE ); sscanf(vbuff, "%s", version); /* trim */ } if ((a.packages.package_list_arch_regex) && (FullTextMatch(ctx, a.packages.package_list_arch_regex, item))) { if (a.packages.package_list_arch_regex) { strlcpy(vbuff, ExtractFirstReference(a.packages.package_list_arch_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", arch); /* trim */ } } return false; } static int PrependListPackageItem(EvalContext *ctx, PackageItem ** list, char *item, const char *default_arch, Attributes a, const Promise *pp) { char name[CF_MAXVARSIZE]; char arch[CF_MAXVARSIZE]; char version[CF_MAXVARSIZE]; char vbuff[CF_MAXVARSIZE]; strlcpy(vbuff, ExtractFirstReference(a.packages.package_list_name_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", name); /* trim */ strlcpy(vbuff, ExtractFirstReference(a.packages.package_list_version_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", version); /* trim */ if (a.packages.package_list_arch_regex) { strlcpy(vbuff, ExtractFirstReference(a.packages.package_list_arch_regex, item), CF_MAXVARSIZE); sscanf(vbuff, "%s", arch); /* trim */ } else { strlcpy(arch, default_arch, CF_MAXVARSIZE); } if ((strcmp(name, "CF_NOMATCH") == 0) || (strcmp(version, "CF_NOMATCH") == 0) || (strcmp(arch, "CF_NOMATCH") == 0)) { return false; } Log(LOG_LEVEL_DEBUG, "PrependListPackageItem: Package line '%s', name '%s', version '%s', arch '%s'", item, name, version, arch); return PrependPackageItem(ctx, list, name, version, arch, pp); } static char *GetDefaultArch(const char *command) { if (command == NULL) { return xstrdup("default"); } Log(LOG_LEVEL_VERBOSE, "Obtaining default architecture for package manager '%s'", command); FILE *fp = cf_popen_sh(command, "r"); if (fp == NULL) { return NULL; } size_t arch_size = CF_SMALLBUF; char *arch = xmalloc(arch_size); ssize_t res = CfReadLine(&arch, &arch_size, fp); if (res == -1) { cf_pclose(fp); free(arch); return NULL; } Log(LOG_LEVEL_VERBOSE, "Default architecture for package manager is '%s'", arch); cf_pclose(fp); return arch; } cfengine-3.6.2/cf-agent/verify_acl.c0000644000175100017510000002712212316547775017014 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include // Valid operations (first char of mode) #define CF_VALID_OPS_METHOD_OVERWRITE "=+-" #define CF_VALID_OPS_METHOD_APPEND "=+-" static int CheckACLSyntax(const char *file, Acl acl, const Promise *pp); static void SetACLDefaults(const char *path, Acl *acl); static int CheckACESyntax(char *ace, char *valid_nperms, char *valid_ops, int deny_support, int mask_support, const Promise *pp); static int CheckModeSyntax(char **mode_p, char *valid_nperms, char *valid_ops, const Promise *pp); static int CheckPermTypeSyntax(char *permt, int deny_support, const Promise *pp); static int CheckAclDefault(const char *path, Acl *acl, const Promise *pp); PromiseResult VerifyACL(EvalContext *ctx, const char *file, Attributes a, const Promise *pp) { if (!CheckACLSyntax(file, a.acl, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Syntax error in access control list for '%s'", file); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_INTERRUPTED; } SetACLDefaults(file, &a.acl); PromiseResult result = PROMISE_RESULT_NOOP; // decide which ACL API to use switch (a.acl.acl_type) { case ACL_TYPE_NONE: // fallthrough: acl_type defaults to generic case ACL_TYPE_GENERIC: #if defined(__linux__) result = PromiseResultUpdate(result, CheckPosixLinuxACL(ctx, file, a.acl, a, pp)); #elif defined(__MINGW32__) result = PromiseResultUpdate(result, Nova_CheckNtACL(ctx, file, a.acl, a, pp)); #else Log(LOG_LEVEL_INFO, "ACLs are not yet supported on this system."); #endif break; case ACL_TYPE_POSIX: #if defined(__linux__) result = PromiseResultUpdate(result, CheckPosixLinuxACL(ctx, file, a.acl, a, pp)); #else Log(LOG_LEVEL_INFO, "Posix ACLs are not supported on this system"); #endif break; case ACL_TYPE_NTFS_: #ifdef __MINGW32__ result = PromiseResultUpdate(result, Nova_CheckNtACL(ctx, file, a.acl, a, pp)); #else Log(LOG_LEVEL_INFO, "NTFS ACLs are not supported on this system"); #endif break; default: Log(LOG_LEVEL_ERR, "Unknown ACL type - software error"); break; } return result; } static int CheckACLSyntax(const char *file, Acl acl, const Promise *pp) { int valid = true; int deny_support = false; int mask_support = false; char *valid_ops = NULL; char *valid_nperms = NULL; Rlist *rp; // set unset fields to defautls SetACLDefaults(file, &acl); // find valid values for op switch (acl.acl_method) { case ACL_METHOD_OVERWRITE: valid_ops = CF_VALID_OPS_METHOD_OVERWRITE; break; case ACL_METHOD_APPEND: valid_ops = CF_VALID_OPS_METHOD_APPEND; break; default: // never executed: should be set to a default value by now break; } switch (acl.acl_type) { case ACL_TYPE_GENERIC: // generic ACL type: cannot include native or deny-type permissions valid_nperms = ""; deny_support = false; mask_support = false; break; case ACL_TYPE_POSIX: valid_nperms = CF_VALID_NPERMS_POSIX; deny_support = false; // posix does not support deny-type permissions mask_support = true; // mask-ACE is allowed in POSIX break; case ACL_TYPE_NTFS_: valid_nperms = CF_VALID_NPERMS_NTFS; deny_support = true; mask_support = false; break; default: // never executed: should be set to a default value by now break; } // check that acl_default is set to a valid value if (!CheckAclDefault(file, &acl, pp)) { return false; } for (rp = acl.acl_entries; rp != NULL; rp = rp->next) { valid = CheckACESyntax(RlistScalarValue(rp), valid_ops, valid_nperms, deny_support, mask_support, pp); if (!valid) // wrong syntax in this ace { Log(LOG_LEVEL_ERR, "The ACE '%s' contains errors", RlistScalarValue(rp)); PromiseRef(LOG_LEVEL_ERR, pp); break; } } for (rp = acl.acl_default_entries; rp != NULL; rp = rp->next) { valid = CheckACESyntax(RlistScalarValue(rp), valid_ops, valid_nperms, deny_support, mask_support, pp); if (!valid) // wrong syntax in this ace { Log(LOG_LEVEL_ERR, "The ACE '%s' contains errors", RlistScalarValue(rp)); PromiseRef(LOG_LEVEL_ERR, pp); break; } } return valid; } /** * Set unset fields with documented defaults, to these defaults. **/ static void SetACLDefaults(const char *path, Acl *acl) { // default: acl_method => append if (acl->acl_method == ACL_METHOD_NONE) { acl->acl_method = ACL_METHOD_APPEND; } // default: acl_type => generic if (acl->acl_type == ACL_TYPE_NONE) { acl->acl_type = ACL_TYPE_GENERIC; } // default on directories: acl_default => nochange if ((acl->acl_default == ACL_DEFAULT_NONE) && (IsDir(path))) { acl->acl_default = ACL_DEFAULT_NO_CHANGE; } } static int CheckAclDefault(const char *path, Acl *acl, const Promise *pp) /* Checks that acl_default is set to a valid value for this acl type. Returns true if so, or false otherwise. */ { int valid = false; switch (acl->acl_default) { case ACL_DEFAULT_NONE: // unset is always valid valid = true; break; case ACL_DEFAULT_SPECIFY: // NOTE: we assume all acls support specify // fallthrough case ACL_DEFAULT_ACCESS: // fallthrough default: if (IsDir(path)) { valid = true; } else { Log(LOG_LEVEL_ERR, "acl_default can only be set on directories."); PromiseRef(LOG_LEVEL_ERR, pp); valid = false; } break; } return valid; } static int CheckACESyntax(char *ace, char *valid_ops, char *valid_nperms, int deny_support, int mask_support, const Promise *pp) { char *str; int chkid; int valid_mode; int valid_permt; str = ace; chkid = false; // first element must be "user", "group" or "all" if (strncmp(str, "user:", 5) == 0) { str += 5; chkid = true; } else if (strncmp(str, "group:", 6) == 0) { str += 6; chkid = true; } else if (strncmp(str, "all:", 4) == 0) { str += 4; chkid = false; } else if (strncmp(str, "mask:", 5) == 0) { if (mask_support) { str += 5; chkid = false; } else { Log(LOG_LEVEL_ERR, "This ACL type does not support mask ACE."); PromiseRef(LOG_LEVEL_ERR, pp); return false; } } else { Log(LOG_LEVEL_ERR, "ACE '%s' does not start with user:/group:/all", ace); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if (chkid) // look for following "id:" { if (*str == ':') { Log(LOG_LEVEL_ERR, "ACE '%s': id cannot be empty or contain ':'", ace); return false; } // skip id-string (no check: allow any id-string) while (true) { str++; if (*str == ':') { str++; break; } else if (*str == '\0') { Log(LOG_LEVEL_ERR, "Nothing following id string in ACE '%s'", ace); return false; } } } // check the mode-string (also skips to next field) valid_mode = CheckModeSyntax(&str, valid_ops, valid_nperms, pp); if (!valid_mode) { Log(LOG_LEVEL_ERR, "Malformed mode-string in ACE '%s'", ace); PromiseRef(LOG_LEVEL_ERR, pp); return false; } if (*str == '\0') // mode was the last field { return true; } str++; // last field; must be a perm_type field valid_permt = CheckPermTypeSyntax(str, deny_support, pp); if (!valid_permt) { Log(LOG_LEVEL_ERR, "Malformed perm_type syntax in ACE '%s'", ace); return false; } return true; } static int CheckModeSyntax(char **mode_p, char *valid_ops, char *valid_nperms, const Promise *pp) /* Checks the syntax of a ':' or NULL terminated mode string. Moves the string pointer to the character following the mode (i.e. ':' or '\0') */ { char *mode; int valid; valid = false; mode = *mode_p; // mode is allowed to be empty if ((*mode == '\0') || (*mode == ':')) { return true; } while (true) { mode = ScanPastChars(valid_ops, mode); mode = ScanPastChars(CF_VALID_GPERMS, mode); if (*mode == CF_NATIVE_PERMS_SEP_START) { mode++; mode = ScanPastChars(valid_nperms, mode); if (*mode == CF_NATIVE_PERMS_SEP_END) { mode++; } else { Log(LOG_LEVEL_ERR, "Invalid native permission '%c', or missing native end separator", *mode); PromiseRef(LOG_LEVEL_ERR, pp); valid = false; break; } } if ((*mode == '\0') || (*mode == ':')) // end of mode-string { valid = true; break; } else if (*mode == ',') // one more iteration { mode++; } else { Log(LOG_LEVEL_ERR, "Mode string contains invalid characters"); PromiseRef(LOG_LEVEL_ERR, pp); valid = false; break; } } *mode_p = mode; // move pointer to past mode-field return valid; } static int CheckPermTypeSyntax(char *permt, int deny_support, const Promise *pp) /* Checks if the given string corresponds to the perm_type syntax. Only "allow" or "deny", followed by NULL-termination are valid. In addition, "deny" is only valid for ACL types supporting it. */ { int valid; valid = false; if (strcmp(permt, "allow") == 0) { valid = true; } else if (strcmp(permt, "deny") == 0) { if (deny_support) { valid = true; } else { Log(LOG_LEVEL_ERR, "Deny permission not supported by this ACL type"); PromiseRef(LOG_LEVEL_ERR, pp); } } return valid; } cfengine-3.6.2/cf-agent/retcode.c0000664000175100017510000000735712411001073016274 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include int VerifyCommandRetcode(EvalContext *ctx, int retcode, Attributes a, const Promise *pp, PromiseResult *result) { bool result_retcode = true; if ((a.classes.retcode_kept) || (a.classes.retcode_repaired) || (a.classes.retcode_failed)) { int matched = false; char retcodeStr[PRINTSIZE(retcode)]; xsnprintf(retcodeStr, sizeof(retcodeStr), "%d", retcode); if (RlistKeyIn(a.classes.retcode_kept, retcodeStr)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Command related to promiser '%s' returned code defined as promise kept %d", pp->promiser, retcode); result_retcode = true; matched = true; } if (RlistKeyIn(a.classes.retcode_repaired, retcodeStr)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Command related to promiser '%s' returned code defined as promise repaired %d", pp->promiser, retcode); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); result_retcode = true; matched = true; } if (RlistKeyIn(a.classes.retcode_failed, retcodeStr)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Command related to promiser '%s' returned code defined as promise failed %d", pp->promiser, retcode); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); result_retcode = false; matched = true; } if (!matched) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Command related to promiser '%s' returned code not defined as promise kept, not kept or repaired; setting to failed: %d", pp->promiser, retcode); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); result_retcode = false; } } else // default: 0 is success, != 0 is failure { if (retcode == 0) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Finished command related to promiser '%s' -- succeeded", pp->promiser); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); result_retcode = true; } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Finished command related to promiser '%s' -- an error occurred, returned %d", pp->promiser, retcode); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); result_retcode = false; } } return result_retcode; } cfengine-3.6.2/cf-agent/agent-diagnostics.c0000644000175100017510000001762312352557236020272 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include AgentDiagnosticsResult AgentDiagnosticsResultNew(bool success, char *message) { return (AgentDiagnosticsResult) { success, message }; } static void AgentDiagnosticsResultDestroy(AgentDiagnosticsResult result) { free(result.message); } void AgentDiagnosticsRun(const char *workdir, const AgentDiagnosticCheck checks[], Writer *output) { { char diagnostics_path[CF_BUFSIZE] = { 0 }; snprintf(diagnostics_path, CF_BUFSIZE, "%s/diagnostics", workdir); MapName(diagnostics_path); struct stat sb; if (stat(diagnostics_path, &sb) != 0) { if (mkdir(diagnostics_path, DEFAULTMODE) != 0) { WriterWriteF(output, "Cannot create diagnostics output directory '%s'", diagnostics_path); return; } } } for (int i = 0; checks[i].description; i++) { AgentDiagnosticsResult result = checks[i].check(workdir); WriterWriteF(output, "[ %s ] %s: %s\n", result.success ? "YES" : "NO ", checks[i].description, result.message); AgentDiagnosticsResultDestroy(result); } } AgentDiagnosticsResult AgentDiagnosticsCheckIsBootstrapped(const char *workdir) { char *policy_server = ReadPolicyServerFile(workdir); return AgentDiagnosticsResultNew(policy_server != NULL, policy_server != NULL ? policy_server : xstrdup("Not bootstrapped")); } AgentDiagnosticsResult AgentDiagnosticsCheckAmPolicyServer(const char *workdir) { bool am_policy_server = GetAmPolicyHub(workdir); return AgentDiagnosticsResultNew(am_policy_server, am_policy_server ? xstrdup("Acting as a policy server") : xstrdup("Not acting as a policy server")); } AgentDiagnosticsResult AgentDiagnosticsCheckPrivateKey(const char *workdir) { char *path = PrivateKeyFile(workdir); struct stat sb; AgentDiagnosticsResult res; if (stat(path, &sb) != 0) { res = AgentDiagnosticsResultNew(false, StringFormat("No private key found at '%s'", path)); } else if (sb.st_mode != (S_IFREG | S_IWUSR | S_IRUSR)) { res = AgentDiagnosticsResultNew(false, StringFormat("Private key found at '%s', but had incorrect permissions '%o'", path, sb.st_mode)); } else { res = AgentDiagnosticsResultNew(true, StringFormat("OK at '%s'", path)); } free(path); return res; } AgentDiagnosticsResult AgentDiagnosticsCheckPublicKey(const char *workdir) { char *path = PublicKeyFile(workdir); struct stat sb; AgentDiagnosticsResult res; if (stat(path, &sb) != 0) { res = AgentDiagnosticsResultNew(false, StringFormat("No public key found at '%s'", path)); } else if (sb.st_mode != (S_IFREG | S_IWUSR | S_IRUSR)) { res = AgentDiagnosticsResultNew(false, StringFormat("Public key found at '%s', but had incorrect permissions '%o'", path, sb.st_mode)); } else if (sb.st_size != 426) { res = AgentDiagnosticsResultNew(false, StringFormat("Public key at '%s' had size %lld bytes, expected 426 bytes", path, (long long)sb.st_size)); } else { res = AgentDiagnosticsResultNew(true, StringFormat("OK at '%s'", path)); } free(path); return res; } static AgentDiagnosticsResult AgentDiagnosticsCheckDB(const char *workdir, dbid id) { char *dbpath = DBIdToPath(workdir, id); char *error = DBPrivDiagnose(dbpath); if (error) { free(dbpath); return AgentDiagnosticsResultNew(false, error); } else { int ret = CheckTokyoDBCoherence(dbpath); free(dbpath); if (ret) { return AgentDiagnosticsResultNew(false, xstrdup("Internal DB coherence problem")); } else { if (id == dbid_lastseen) { if (IsLastSeenCoherent() == false) { return AgentDiagnosticsResultNew(false, xstrdup("Lastseen DB data coherence problem")); } } return AgentDiagnosticsResultNew(true, xstrdup("OK")); } } } AgentDiagnosticsResult AgentDiagnosticsCheckDBPersistentClasses(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_state); } AgentDiagnosticsResult AgentDiagnosticsCheckDBChecksums(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_checksums); } AgentDiagnosticsResult AgentDiagnosticsCheckDBClasses(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_classes); } AgentDiagnosticsResult AgentDiagnosticsCheckDBLastSeen(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_lastseen); } AgentDiagnosticsResult AgentDiagnosticsCheckDBObservations(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_observations); } AgentDiagnosticsResult AgentDiagnosticsCheckDBFileStats(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_filestats); } AgentDiagnosticsResult AgentDiagnosticsCheckDBLocks(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_locks); } AgentDiagnosticsResult AgentDiagnosticsCheckDBPerformance(const char *workdir) { return AgentDiagnosticsCheckDB(workdir, dbid_performance); } const AgentDiagnosticCheck *AgentDiagnosticsAllChecks(void) { static const AgentDiagnosticCheck checks[] = { { "Check that agent is bootstrapped", &AgentDiagnosticsCheckIsBootstrapped }, { "Check if agent is acting as a policy server", &AgentDiagnosticsCheckAmPolicyServer }, { "Check private key", &AgentDiagnosticsCheckPrivateKey }, { "Check public key", &AgentDiagnosticsCheckPublicKey }, { "Check persistent classes DB", &AgentDiagnosticsCheckDBPersistentClasses }, { "Check checksums DB", &AgentDiagnosticsCheckDBChecksums }, { "Check classes DB", &AgentDiagnosticsCheckDBClasses }, { "Check observations DB", &AgentDiagnosticsCheckDBObservations }, { "Check file stats DB", &AgentDiagnosticsCheckDBFileStats }, { "Check locks DB", &AgentDiagnosticsCheckDBLocks }, { "Check performance DB", &AgentDiagnosticsCheckDBPerformance }, { "Check lastseen DB", &AgentDiagnosticsCheckDBLastSeen }, { NULL, NULL } }; return checks; } ENTERPRISE_VOID_FUNC_4ARG_DEFINE_STUB(void, AgentDiagnosticsRunAllChecksNova, ARG_UNUSED const char *, workdir, ARG_UNUSED Writer *, output, ARG_UNUSED AgentDiagnosticsRunFunction, AgentDiagnosticsRunPtr, ARG_UNUSED AgentDiagnosticsResultNewFunction, AgentDiagnosticsResultNewPtr) { } cfengine-3.6.2/cf-agent/files_operators.h0000644000175100017510000000321212332665147020060 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_OPERATORS_H #define CFENGINE_FILES_OPERATORS_H #include #include int MoveObstruction(EvalContext *ctx, char *from, Attributes attr, const Promise *pp, PromiseResult *result); typedef bool (*SaveCallbackFn)(const char *dest_filename, void *param, NewLineMode new_line_mode); bool SaveAsFile(SaveCallbackFn callback, void *param, const char *file, Attributes a, NewLineMode new_line_mode); bool SaveItemListAsFile(Item *liststart, const char *file, Attributes a, NewLineMode new_line_mode); int CompareToFile(EvalContext *ctx, const Item *liststart, const char *file, Attributes a, const Promise *pp, PromiseResult *result); #endif cfengine-3.6.2/cf-agent/verify_files_utils.h0000664000175100017510000000501712411001073020551 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_FILES_UTILS_H #define CFENGINE_VERIFY_FILES_UTILS_H #include #include /* AgentConnection */ #include extern Item *VSETUIDLIST; extern const Rlist *SINGLE_COPY_LIST; void SetFileAutoDefineList(const Rlist *auto_define_list); void VerifyFileLeaf(EvalContext *ctx, char *path, struct stat *sb, Attributes attr, const Promise *pp, PromiseResult *result); int DepthSearch(EvalContext *ctx, char *name, struct stat *sb, int rlevel, Attributes attr, const Promise *pp, dev_t rootdevice, PromiseResult *result); bool CfCreateFile(EvalContext *ctx, char *file, const Promise *pp, Attributes attr, PromiseResult *result_out); void SetSearchDevice(struct stat *sb, const Promise *pp); PromiseResult ScheduleCopyOperation(EvalContext *ctx, char *destination, Attributes attr, const Promise *pp); PromiseResult ScheduleLinkChildrenOperation(EvalContext *ctx, char *destination, char *source, int rec, Attributes attr, const Promise *pp); PromiseResult ScheduleLinkOperation(EvalContext *ctx, char *destination, char *source, Attributes attr, const Promise *pp); bool CopyRegularFile(EvalContext *ctx, const char *source, const char *dest, struct stat sstat, struct stat dstat, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn, PromiseResult *result); /* To be implemented in Nova for Win32 */ bool VerifyOwner(EvalContext *ctx, const char *file, const Promise *pp, Attributes attr, struct stat *sb, PromiseResult *result); #endif cfengine-3.6.2/cf-agent/match_scope.h0000644000175100017510000000250712316547775017163 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MATCH_SCOPE_H #define CFENGINE_MATCH_SCOPE_H #include int FullTextMatch(EvalContext *ctx, const char *regptr, const char *cmpptr); /* Sets variables */ int BlockTextMatch(EvalContext *ctx, const char *regexp, const char *teststring, int *s, int *e); /* Sets variables */ bool ValidateRegEx(const char *regex); /* Pure */ #endif cfengine-3.6.2/cf-agent/cf_sql.c0000664000175100017510000002721712411001073016113 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #ifdef HAVE_MYSQL_H # include #elif defined(HAVE_MYSQL_MYSQL_H) # include #endif #ifdef HAVE_PGSQL_LIBPQ_FE_H # include #elif defined(HAVE_LIBPQ_FE_H) # include #endif /* CFEngine connectors for sql databases. Note that there are significant differences in db admin functions in the various implementations. e.g. sybase/mysql "use database, create database" not in postgres. */ /*****************************************************************************/ #ifdef HAVE_LIBMYSQLCLIENT typedef struct { MYSQL conn; MYSQL_RES *res; } DbMysqlConn; /*****************************************************************************/ static DbMysqlConn *CfConnectMysqlDB(const char *host, const char *user, const char *password, const char *database) { DbMysqlConn *c; Log(LOG_LEVEL_VERBOSE, "This is a MySQL database"); c = xcalloc(1, sizeof(DbMysqlConn)); mysql_init(&c->conn); if (!mysql_real_connect(&c->conn, host, user, password, database, 0, NULL, 0)) { Log(LOG_LEVEL_ERR, "Failed to connect to existing MySQL database '%s'", mysql_error(&c->conn)); free(c); return NULL; } return c; } /*****************************************************************************/ static void CfCloseMysqlDB(DbMysqlConn *c) { mysql_close(&c->conn); free(c); } /*****************************************************************************/ static void CfNewQueryMysqlDb(CfdbConn *c, const char *query) { DbMysqlConn *mc = c->data; if (mysql_query(&mc->conn, query) != 0) { Log(LOG_LEVEL_INFO, "MySQL query failed '%s'. (mysql_query: %s)", query, mysql_error(&mc->conn)); } else { mc->res = mysql_store_result(&mc->conn); if (mc->res) { c->result = true; c->maxcolumns = mysql_num_fields(mc->res); c->maxrows = mysql_num_rows(mc->res); } } } /*****************************************************************************/ static void CfFetchMysqlRow(CfdbConn *c) { int i; MYSQL_ROW thisrow; DbMysqlConn *mc = c->data; if (c->maxrows > 0) { thisrow = mysql_fetch_row(mc->res); if (thisrow) { c->rowdata = xmalloc(sizeof(char *) * c->maxcolumns); for (i = 0; i < c->maxcolumns; i++) { c->rowdata[i] = (char *) thisrow[i]; } } else { c->rowdata = NULL; } } } /*****************************************************************************/ static void CfDeleteMysqlQuery(CfdbConn *c) { DbMysqlConn *mc = c->data; if (mc->res) { mysql_free_result(mc->res); mc->res = NULL; } } #else static void *CfConnectMysqlDB(ARG_UNUSED const char *host, ARG_UNUSED const char *user, ARG_UNUSED const char *password, ARG_UNUSED const char *database) { Log(LOG_LEVEL_INFO, "There is no MySQL support compiled into this version"); return NULL; } static void CfCloseMysqlDB(ARG_UNUSED void *c) { } static void CfNewQueryMysqlDb(ARG_UNUSED CfdbConn *c, ARG_UNUSED const char *query) { } static void CfFetchMysqlRow(ARG_UNUSED CfdbConn *c) { } static void CfDeleteMysqlQuery(ARG_UNUSED CfdbConn *c) { } #endif #if defined(HAVE_LIBPQ) &&\ (defined(HAVE_PGSQL_LIBPQ_FE_H) || defined(HAVE_LIBPQ_FE_H)) typedef struct { PGconn *conn; PGresult *res; } DbPostgresqlConn; /*****************************************************************************/ static DbPostgresqlConn *CfConnectPostgresqlDB(const char *host, const char *user, const char *password, const char *database) { DbPostgresqlConn *c; char format[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "This is a PotsgreSQL database"); c = xcalloc(1, sizeof(DbPostgresqlConn)); if (strcmp(host, "localhost") == 0) { /* Some authentication problem - ?? */ if (database) { snprintf(format, CF_BUFSIZE - 1, "dbname=%s user=%s password=%s", database, user, password); } else { snprintf(format, CF_BUFSIZE - 1, "user=%s password=%s", user, password); } } else { if (database) { snprintf(format, CF_BUFSIZE - 1, "dbname=%s host=%s user=%s password=%s", database, host, user, password); } else { snprintf(format, CF_BUFSIZE - 1, "host=%s user=%s password=%s", host, user, password); } } c->conn = PQconnectdb(format); if (PQstatus(c->conn) == CONNECTION_BAD) { Log(LOG_LEVEL_ERR, "Failed to connect to existing PostgreSQL database. (PQconnectdb: %s)", PQerrorMessage(c->conn)); free(c); return NULL; } return c; } /*****************************************************************************/ static void CfClosePostgresqlDb(DbPostgresqlConn *c) { PQfinish(c->conn); free(c); } /*****************************************************************************/ static void CfNewQueryPostgresqlDb(CfdbConn *c, const char *query) { DbPostgresqlConn *pc = c->data; pc->res = PQexec(pc->conn, query); if (PQresultStatus(pc->res) != PGRES_COMMAND_OK && PQresultStatus(pc->res) != PGRES_TUPLES_OK) { Log(LOG_LEVEL_INFO, "PostgreSQL query '%s' failed. (PQExec: %s)", query, PQerrorMessage(pc->conn)); } else { c->result = true; c->maxcolumns = PQnfields(pc->res); c->maxrows = PQntuples(pc->res); } } /*****************************************************************************/ static void CfFetchPostgresqlRow(CfdbConn *c) { int i; DbPostgresqlConn *pc = c->data; if (c->row >= c->maxrows) { c->rowdata = NULL; return; } if (c->maxrows > 0) { c->rowdata = xmalloc(sizeof(char *) * c->maxcolumns); } for (i = 0; i < c->maxcolumns; i++) { c->rowdata[i] = PQgetvalue(pc->res, c->row, i); } } /*****************************************************************************/ static void CfDeletePostgresqlQuery(CfdbConn *c) { DbPostgresqlConn *pc = c->data; PQclear(pc->res); } /*****************************************************************************/ #else static void *CfConnectPostgresqlDB(ARG_UNUSED const char *host, ARG_UNUSED const char *user, ARG_UNUSED const char *password, ARG_UNUSED const char *database) { Log(LOG_LEVEL_INFO, "There is no PostgreSQL support compiled into this version"); return NULL; } static void CfClosePostgresqlDb(ARG_UNUSED void *c) { } static void CfNewQueryPostgresqlDb(ARG_UNUSED CfdbConn *c, ARG_UNUSED const char *query) { } static void CfFetchPostgresqlRow(ARG_UNUSED CfdbConn *c) { } static void CfDeletePostgresqlQuery(ARG_UNUSED CfdbConn *c) { } #endif /*****************************************************************************/ int CfConnectDB(CfdbConn *cfdb, DatabaseType dbtype, char *remotehost, char *dbuser, char *passwd, char *db) { cfdb->connected = false; cfdb->type = dbtype; /* If db == NULL, no database was specified, so we assume it has not been created yet. Need to open a generic database and create */ if (db == NULL) { db = "no db specified"; } Log(LOG_LEVEL_VERBOSE, "Connect to SQL database '%s', user '%s', host '%s', type %d", db, dbuser, remotehost, dbtype); switch (dbtype) { case DATABASE_TYPE_MYSQL: cfdb->data = CfConnectMysqlDB(remotehost, dbuser, passwd, db); break; case DATABASE_TYPE_POSTGRES: cfdb->data = CfConnectPostgresqlDB(remotehost, dbuser, passwd, db); break; default: Log(LOG_LEVEL_VERBOSE, "There is no SQL database selected"); break; } if (cfdb->data) cfdb->connected = true; cfdb->blank = xstrdup(""); return true; } /*****************************************************************************/ void CfCloseDB(CfdbConn *cfdb) { if (!cfdb->connected) { return; } switch (cfdb->type) { case DATABASE_TYPE_MYSQL: CfCloseMysqlDB(cfdb->data); break; case DATABASE_TYPE_POSTGRES: CfClosePostgresqlDb(cfdb->data); break; default: Log(LOG_LEVEL_VERBOSE, "There is no SQL database selected"); break; } cfdb->connected = false; free(cfdb->blank); } /*****************************************************************************/ void CfVoidQueryDB(CfdbConn *cfdb, char *query) { if (!cfdb->connected) { return; } /* If we don't need to retrieve table entries...*/ CfNewQueryDB(cfdb, query); CfDeleteQuery(cfdb); } /*****************************************************************************/ void CfNewQueryDB(CfdbConn *cfdb, char *query) { cfdb->result = false; cfdb->row = 0; cfdb->column = 0; cfdb->rowdata = NULL; cfdb->maxcolumns = 0; cfdb->maxrows = 0; Log(LOG_LEVEL_DEBUG, "Before query '%s' succeeded, maxrows %d, maxcolumns %d", query, cfdb->maxrows, cfdb->maxcolumns); switch (cfdb->type) { case DATABASE_TYPE_MYSQL: CfNewQueryMysqlDb(cfdb, query); break; case DATABASE_TYPE_POSTGRES: CfNewQueryPostgresqlDb(cfdb, query); break; default: Log(LOG_LEVEL_VERBOSE, "There is no SQL database selected"); break; } Log(LOG_LEVEL_DEBUG, "Query '%s' succeeded. maxrows %d, maxcolumns %d", query, cfdb->maxrows, cfdb->maxcolumns); } /*****************************************************************************/ char **CfFetchRow(CfdbConn *cfdb) { switch (cfdb->type) { case DATABASE_TYPE_MYSQL: CfFetchMysqlRow(cfdb); break; case DATABASE_TYPE_POSTGRES: CfFetchPostgresqlRow(cfdb); break; default: Log(LOG_LEVEL_VERBOSE, "There is no SQL database selected"); break; } cfdb->row++; return cfdb->rowdata; } /*****************************************************************************/ char *CfFetchColumn(CfdbConn *cfdb, int col) { if ((cfdb->rowdata) && (cfdb->rowdata[col])) { return cfdb->rowdata[col]; } else { return NULL; } } /*****************************************************************************/ void CfDeleteQuery(CfdbConn *cfdb) { switch (cfdb->type) { case DATABASE_TYPE_MYSQL: CfDeleteMysqlQuery(cfdb); break; case DATABASE_TYPE_POSTGRES: CfDeletePostgresqlQuery(cfdb); break; default: Log(LOG_LEVEL_VERBOSE, "There is no SQL database selected"); break; } if (cfdb->rowdata) { free(cfdb->rowdata); cfdb->rowdata = NULL; } } cfengine-3.6.2/cf-agent/load_avahi.c0000644000175100017510000000613512316547775016761 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include static const char *paths[] = { "/usr/lib/x86_64-linux-gnu/libavahi-client.so.3", "/usr/lib/libavahi-client.so.3", "/usr/lib64/libavahi-client.so.3", /* 32-bit variants */ "/usr/lib/i386-linux-gnu/libavahi-client.so.3" }; static const char *getavahipath(); int loadavahi() { const char *path = getavahipath(); avahi_handle = dlopen(path, RTLD_LAZY); if (!avahi_handle) { return -1; } avahi_simple_poll_quit_ptr = dlsym(avahi_handle, "avahi_simple_poll_quit"); avahi_address_snprint_ptr = dlsym(avahi_handle, "avahi_address_snprint"); avahi_service_resolver_free_ptr = dlsym(avahi_handle, "avahi_service_resolver_free"); avahi_client_errno_ptr = dlsym(avahi_handle, "avahi_client_errno"); avahi_strerror_ptr = dlsym(avahi_handle, "avahi_strerror"); avahi_service_resolver_new_ptr = dlsym(avahi_handle, "avahi_service_resolver_new"); avahi_service_browser_get_client_ptr = dlsym(avahi_handle, "avahi_service_browser_get_client"); avahi_service_resolver_get_client_ptr = dlsym(avahi_handle, "avahi_service_resolver_get_client"); avahi_simple_poll_new_ptr = dlsym(avahi_handle, "avahi_simple_poll_new"); avahi_simple_poll_get_ptr = dlsym(avahi_handle, "avahi_simple_poll_get"); avahi_client_new_ptr = dlsym(avahi_handle, "avahi_client_new"); avahi_simple_poll_loop_ptr = dlsym(avahi_handle, "avahi_simple_poll_loop"); avahi_service_browser_free_ptr = dlsym(avahi_handle, "avahi_service_browser_free"); avahi_client_free_ptr = dlsym(avahi_handle, "avahi_client_free"); avahi_simple_poll_free_ptr = dlsym(avahi_handle, "avahi_simple_poll_free"); avahi_service_browser_new_ptr = dlsym(avahi_handle, "avahi_service_browser_new"); return 0; } static const char *getavahipath() { const char *env = getenv("AVAHI_PATH"); struct stat sb; if (stat(env, &sb) == 0) { return env; } for (int i = 0; i < sizeof(paths)/sizeof(paths[0]); i++) { if (stat(paths[i], &sb) == 0) { return paths[i]; } } return NULL; } cfengine-3.6.2/cf-agent/cf-agent-windows-functions.h0000644000175100017510000000253212316547775022056 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFAGENT_WINDOWS_FUNCTIONS_H #define CFAGENT_WINDOWS_FUNCTIONS_H #ifdef __MINGW32__ PromiseResult VerifyWindowsService(EvalContext *ctx, Attributes a, Promise *pp); PromiseResult Nova_CheckNtACL(EvalContext *ctx, const char *file_path, Acl acl, Attributes a, const Promise *pp); #endif // __MINGW32__ #endif // CFAGENT_WINDOWS_FUNCTIONS_H cfengine-3.6.2/cf-agent/files_operators.c0000644000175100017510000003301012332665147020052 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int MoveObstruction(EvalContext *ctx, char *from, Attributes attr, const Promise *pp, PromiseResult *result) { struct stat sb; char stamp[CF_BUFSIZE], saved[CF_BUFSIZE]; time_t now_stamp = time((time_t *) NULL); if (lstat(from, &sb) == 0) { if (!attr.move_obstructions) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Object '%s' exists and is obstructing our promise", from); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } if (!S_ISDIR(sb.st_mode)) { if (DONTDO) { return false; } saved[0] = '\0'; strcpy(saved, from); if (attr.copy.backup == BACKUP_OPTION_TIMESTAMP || attr.edits.backup == BACKUP_OPTION_TIMESTAMP) { snprintf(stamp, CF_BUFSIZE, "_%jd_%s", (intmax_t) CFSTARTTIME, CanonifyName(ctime(&now_stamp))); strcat(saved, stamp); } strcat(saved, CF_SAVED); cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, attr, "Moving file object '%s' to '%s'", from, saved); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if (rename(from, saved) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't rename '%s' to '%s'. (rename: %s)", from, saved, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } if (ArchiveToRepository(saved, attr)) { unlink(saved); } return true; } if (S_ISDIR(sb.st_mode)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, attr, "Moving directory '%s' to '%s%s'", from, from, CF_SAVED); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); if (DONTDO) { return false; } saved[0] = '\0'; strcpy(saved, from); snprintf(stamp, CF_BUFSIZE, "_%jd_%s", (intmax_t) CFSTARTTIME, CanonifyName(ctime(&now_stamp))); strcat(saved, stamp); strcat(saved, CF_SAVED); strcat(saved, ".dir"); if (stat(saved, &sb) != -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't save directory '%s', since '%s' exists already", from, saved); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); Log(LOG_LEVEL_ERR, "Unable to force link to existing directory '%s'", from); return false; } if (rename(from, saved) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't rename '%s' to '%s'. (rename: %s)", from, saved, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } } } return true; } /*********************************************************************/ bool SaveAsFile(SaveCallbackFn callback, void *param, const char *file, Attributes a, NewLineMode new_line_mode) { struct stat statbuf; char new[CF_BUFSIZE], backup[CF_BUFSIZE]; char stamp[CF_BUFSIZE]; time_t stamp_now; Buffer *deref_file = BufferNewFrom(file, strlen(file)); Buffer *pretty_file = BufferNew(); int ret = false; BufferPrintf(pretty_file, "'%s'", file); stamp_now = time((time_t *) NULL); while (1) { if (lstat(BufferData(deref_file), &statbuf) == -1) { Log(LOG_LEVEL_ERR, "Can no longer access file %s, which needed editing. (lstat: %s)", BufferData(pretty_file), GetErrorStr()); goto end; } #ifndef __MINGW32__ if (S_ISLNK(statbuf.st_mode)) { char buf[statbuf.st_size + 1]; // Careful. readlink() doesn't add '\0' byte. ssize_t linksize = readlink(BufferData(deref_file), buf, statbuf.st_size); if (linksize == 0) { Log(LOG_LEVEL_WARNING, "readlink() failed with 0 bytes. Should not happen (bug?)."); goto end; } else if (linksize < 0) { Log(LOG_LEVEL_ERR, "Could not read link %s. (readlink: %s)", BufferData(pretty_file), GetErrorStr()); goto end; } buf[linksize] = '\0'; if (!IsAbsPath(buf)) { char dir[BufferSize(deref_file) + 1]; strcpy(dir, BufferData(deref_file)); ChopLastNode(dir); BufferPrintf(deref_file, "%s/%s", dir, buf); } else { BufferSet(deref_file, buf, linksize); } BufferPrintf(pretty_file, "'%s' (from symlink '%s')", BufferData(deref_file), file); } else #endif { break; } } strcpy(backup, BufferData(deref_file)); if (a.edits.backup == BACKUP_OPTION_TIMESTAMP) { snprintf(stamp, CF_BUFSIZE, "_%jd_%s", (intmax_t) CFSTARTTIME, CanonifyName(ctime(&stamp_now))); strcat(backup, stamp); } strcat(backup, ".cf-before-edit"); strcpy(new, BufferData(deref_file)); strcat(new, ".cf-after-edit"); unlink(new); /* Just in case of races */ if ((*callback)(new, param, new_line_mode) == false) { goto end; } if (!CopyFilePermissionsDisk(BufferData(deref_file), new)) { Log(LOG_LEVEL_ERR, "Can't copy file permissions from %s to '%s' - so promised edits could not be moved into place.", BufferData(pretty_file), new); goto end; } unlink(backup); #ifndef __MINGW32__ if (link(BufferData(deref_file), backup) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't link %s to '%s' - falling back to copy. (link: %s)", BufferData(pretty_file), backup, GetErrorStr()); #else /* No hardlinks on Windows, go straight to copying */ { #endif if (!CopyRegularFileDisk(BufferData(deref_file), backup)) { Log(LOG_LEVEL_ERR, "Can't copy %s to '%s' - so promised edits could not be moved into place.", BufferData(pretty_file), backup); goto end; } if (!CopyFilePermissionsDisk(BufferData(deref_file), backup)) { Log(LOG_LEVEL_ERR, "Can't copy permissions %s to '%s' - so promised edits could not be moved into place.", BufferData(pretty_file), backup); goto end; } } if (a.edits.backup == BACKUP_OPTION_ROTATE) { RotateFiles(backup, a.edits.rotate); unlink(backup); } if (a.edits.backup != BACKUP_OPTION_NO_BACKUP) { if (ArchiveToRepository(backup, a)) { unlink(backup); } } else { unlink(backup); } if (rename(new, BufferData(deref_file)) == -1) { Log(LOG_LEVEL_ERR, "Can't rename '%s' to %s - so promised edits could not be moved into place. (rename: %s)", new, BufferData(pretty_file), GetErrorStr()); goto end; } ret = true; end: BufferDestroy(pretty_file); BufferDestroy(deref_file); return ret; } /*********************************************************************/ static bool SaveItemListCallback(const char *dest_filename, void *param, NewLineMode new_line_mode) { Item *liststart = param, *ip; FILE *fp; //saving list to file if ((fp = safe_fopen(dest_filename, (new_line_mode == NewLineMode_Native) ? "wt" : "w")) == NULL) { Log(LOG_LEVEL_ERR, "Unable to open destination file '%s' for writing. (fopen: %s)", dest_filename, GetErrorStr()); return false; } for (ip = liststart; ip != NULL; ip = ip->next) { if (fprintf(fp, "%s\n", ip->name) < 0) { Log(LOG_LEVEL_ERR, "Unable to write into destination file '%s'. (fprintf: %s)", dest_filename, GetErrorStr()); fclose(fp); return false; } } if (fclose(fp) == -1) { Log(LOG_LEVEL_ERR, "Unable to close file '%s' after writing. (fclose: %s)", dest_filename, GetErrorStr()); return false; } return true; } /*********************************************************************/ bool SaveItemListAsFile(Item *liststart, const char *file, Attributes a, NewLineMode new_line_mode) { return SaveAsFile(&SaveItemListCallback, liststart, file, a, new_line_mode); } // Some complex logic here to enable warnings of diffs to be given static Item *NextItem(const Item *ip) { if (ip) { return ip->next; } else { return NULL; } } static int ItemListsEqual(EvalContext *ctx, const Item *list1, const Item *list2, int warnings, Attributes a, const Promise *pp, PromiseResult *result) { int retval = true; const Item *ip1 = list1; const Item *ip2 = list2; while (true) { if ((ip1 == NULL) && (ip2 == NULL)) { return retval; } if ((ip1 == NULL) || (ip2 == NULL)) { if (warnings) { if ((ip1 == list1) || (ip2 == list2)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "File content wants to change from from/to full/empty but only a warning promised"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); } else { if (ip1 != NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, " ! edit_line change warning promised: (remove) %s", ip1->name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); } if (ip2 != NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, " ! edit_line change warning promised: (add) %s", ip2->name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); } } } if (warnings) { if (ip1 || ip2) { retval = false; ip1 = NextItem(ip1); ip2 = NextItem(ip2); continue; } } return false; } if (strcmp(ip1->name, ip2->name) != 0) { if (!warnings) { // No need to wait return false; } else { // If we want to see warnings, we need to scan the whole file cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "edit_line warning promised: - %s", ip1->name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); retval = false; } } ip1 = NextItem(ip1); ip2 = NextItem(ip2); } return retval; } /* returns true if file on disk is identical to file in memory */ int CompareToFile(EvalContext *ctx, const Item *liststart, const char *file, Attributes a, const Promise *pp, PromiseResult *result) { struct stat statbuf; Item *cmplist = NULL; if (stat(file, &statbuf) == -1) { return false; } if ((liststart == NULL) && (statbuf.st_size == 0)) { return true; } if (liststart == NULL) { return false; } if (!LoadFileAsItemList(&cmplist, file, a.edits)) { return false; } if (!ItemListsEqual(ctx, cmplist, liststart, (a.transaction.action == cfa_warn), a, pp, result)) { DeleteItemList(cmplist); return false; } DeleteItemList(cmplist); return (true); } cfengine-3.6.2/cf-agent/files_links.h0000644000175100017510000000354112316547775017177 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_LINKS_H #define CFENGINE_FILES_LINKS_H #include PromiseResult VerifyLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp); PromiseResult VerifyAbsoluteLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp); PromiseResult VerifyRelativeLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp); PromiseResult VerifyHardLink(EvalContext *ctx, char *destination, const char *source, Attributes attr, const Promise *pp); bool KillGhostLink(EvalContext *ctx, const char *name, Attributes attr, const const Promise *pp, PromiseResult *result); bool MakeHardLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result); int ExpandLinks(char *dest, const char *from, int level); #endif cfengine-3.6.2/cf-agent/verify_acl.h0000644000175100017510000000260212316547775017015 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef VERIFY_ACL_H #define VERIFY_ACL_H #include // Valid generic permissions #define CF_VALID_GPERMS "rwx" // Native perms separators in mode #define CF_NATIVE_PERMS_SEP_START '(' #define CF_NATIVE_PERMS_SEP_END ')' #define CF_VALID_NPERMS_POSIX "rwx" #define CF_VALID_NPERMS_NTFS "drtxTwabBpcoD" PromiseResult VerifyACL(EvalContext *ctx, const char *file, Attributes a, const Promise *pp); #endif cfengine-3.6.2/cf-agent/files_repository.h0000664000175100017510000000256412243421446020265 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_REPOSITORY_H #define CFENGINE_FILES_REPOSITORY_H void SetRepositoryLocation(const char *path); void SetRepositoryChar(char c); int ArchiveToRepository(char *file, Attributes attr); bool FileInRepository(const char *filename); /* Returns false if backing up files to repository is not set up */ bool GetRepositoryPath(const char *file, Attributes attr, char *destination); #endif cfengine-3.6.2/cf-agent/verify_methods.c0000664000175100017510000001724512411001073017673 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include // HashVariables #include #include #include #include static void GetReturnValue(EvalContext *ctx, const Bundle *callee, const Promise *caller); /*****************************************************************************/ /* * This function should only be called from the evaluator so that methods promises * never report REPAIRED compliance (the promises inside will do that already). * * Promise types that delegate to bundles (services and users) should call VerifyMethod, * which maintains the REPAIRED compliance so that it bubbles up correctly to the parent * promise type. */ PromiseResult VerifyMethodsPromise(EvalContext *ctx, const Promise *pp) { Attributes a = GetMethodAttributes(ctx, pp); const Constraint *cp = PromiseGetConstraint(pp, "usebundle"); if (!cp) { Log(LOG_LEVEL_VERBOSE, "Promise had no attribute 'usebundle', cannot call method"); return PROMISE_RESULT_FAIL; } PromiseResult result = VerifyMethod(ctx, cp->rval, a, pp); return result; } /*****************************************************************************/ PromiseResult VerifyMethod(EvalContext *ctx, const Rval call, Attributes a, const Promise *pp) { assert(a.havebundle); const Rlist *args = NULL; Buffer *method_name = BufferNew(); switch (call.type) { case RVAL_TYPE_FNCALL: { const FnCall *fp = RvalFnCallValue(call); ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, fp->name, method_name); args = fp->args; } break; case RVAL_TYPE_SCALAR: { ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, RvalScalarValue(call), method_name); args = NULL; } break; default: BufferDestroy(method_name); return PROMISE_RESULT_NOOP; } char lockname[CF_BUFSIZE]; GetLockName(lockname, "method", pp->promiser, args); CfLock thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { BufferDestroy(method_name); return PROMISE_RESULT_SKIPPED; } PromiseBanner(pp); const Bundle *bp = EvalContextResolveBundleExpression(ctx, PromiseGetPolicy(pp), BufferData(method_name), "agent"); if (!bp) { bp = EvalContextResolveBundleExpression(ctx, PromiseGetPolicy(pp), BufferData(method_name), "common"); } PromiseResult result = PROMISE_RESULT_NOOP; if (bp) { if (a.transaction.action == cfa_warn) // don't skip for dry-runs (ie ignore DONTDO) { result = PROMISE_RESULT_WARN; cfPS(ctx, LOG_LEVEL_ERR, result, pp, a, "Bundle '%s' should be invoked, but only a warning was promised!", BufferData(method_name)); } else { BannerSubBundle(bp, args); EvalContextStackPushBundleFrame(ctx, bp, args, a.inherit); BundleResolve(ctx, bp); result = ScheduleAgentOperations(ctx, bp); GetReturnValue(ctx, bp, pp); EvalContextStackPopFrame(ctx); switch (result) { case PROMISE_RESULT_SKIPPED: // if a bundle returns 'skipped', meaning that all promises were locked in the bundle, // we explicitly consider the method 'kept' result = PROMISE_RESULT_NOOP; // intentional fallthru case PROMISE_RESULT_NOOP: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Method '%s' verified", bp->name); break; case PROMISE_RESULT_WARN: cfPS(ctx, LOG_LEVEL_WARNING, PROMISE_RESULT_WARN, pp, a, "Method '%s' invoked repairs, but only warnings promised", bp->name); break; case PROMISE_RESULT_CHANGE: cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Method '%s' invoked repairs", bp->name); break; case PROMISE_RESULT_FAIL: case PROMISE_RESULT_DENIED: cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Method '%s' failed in some repairs", bp->name); break; default: // PROMISE_RESULT_INTERRUPTED, TIMEOUT cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Method '%s' aborted in some repairs", bp->name); break; } } for (const Rlist *rp = bp->args; rp; rp = rp->next) { const char *lval = RlistScalarValue(rp); VarRef *ref = VarRefParseFromBundle(lval, bp); EvalContextVariableRemove(ctx, ref); VarRefDestroy(ref); } } else { if (IsCf3VarString(BufferData(method_name))) { Log(LOG_LEVEL_ERR, "A variable seems to have been used for the name of the method. In this case, the promiser also needs to contain the unique name of the method"); } cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "A method attempted to use a bundle '%s' that was apparently not defined", BufferData(method_name)); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } YieldCurrentLock(thislock); BufferDestroy(method_name); return result; } /***********************************************************************/ static void GetReturnValue(EvalContext *ctx, const Bundle *callee, const Promise *caller) { char *result = PromiseGetConstraintAsRval(caller, "useresult", RVAL_TYPE_SCALAR); if (result) { VarRef *ref = VarRefParseFromBundle("last-result", callee); VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, ref->ns, ref->scope, ref->lval); Variable *result_var = NULL; while ((result_var = VariableTableIteratorNext(iter))) { assert(result_var->ref->num_indices == 1); if (result_var->ref->num_indices != 1) { continue; } VarRef *new_ref = VarRefParseFromBundle(result, PromiseGetBundle(caller)); VarRefAddIndex(new_ref, result_var->ref->indices[0]); EvalContextVariablePut(ctx, new_ref, result_var->rval.item, result_var->type, "source=bundle"); VarRefDestroy(new_ref); } VarRefDestroy(ref); VariableTableIteratorDestroy(iter); } } cfengine-3.6.2/cf-agent/cf-agent.c0000664000175100017510000016150112411001073016323 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef enum { TYPE_SEQUENCE_META, TYPE_SEQUENCE_VARS, TYPE_SEQUENCE_DEFAULTS, TYPE_SEQUENCE_CONTEXTS, TYPE_SEQUENCE_INTERFACES, TYPE_SEQUENCE_USERS, TYPE_SEQUENCE_FILES, TYPE_SEQUENCE_PACKAGES, TYPE_SEQUENCE_ENVIRONMENTS, TYPE_SEQUENCE_METHODS, TYPE_SEQUENCE_PROCESSES, TYPE_SEQUENCE_SERVICES, TYPE_SEQUENCE_COMMANDS, TYPE_SEQUENCE_STORAGE, TYPE_SEQUENCE_DATABASES, TYPE_SEQUENCE_REPORTS, TYPE_SEQUENCE_NONE } TypeSequence; #ifdef HAVE_AVAHI_CLIENT_CLIENT_H #ifdef HAVE_AVAHI_COMMON_ADDRESS_H #include #endif #endif #include extern int PR_KEPT; extern int PR_REPAIRED; extern int PR_NOTKEPT; static bool ALLCLASSESREPORT = false; /* GLOBAL_P */ static bool ALWAYS_VALIDATE = false; /* GLOBAL_P */ static bool CFPARANOID = false; /* GLOBAL_P */ static const Rlist *ACCESSLIST = NULL; /* GLOBAL_P */ static int CFA_BACKGROUND = 0; /* GLOBAL_X */ static int CFA_BACKGROUND_LIMIT = 1; /* GLOBAL_P */ static Item *PROCESSREFRESH = NULL; /* GLOBAL_P */ static const char *const AGENT_TYPESEQUENCE[] = { "meta", "vars", "defaults", "classes", /* Maelstrom order 2 */ "interfaces", "users", "files", "packages", "guest_environments", "methods", "processes", "services", "commands", "storage", "databases", "reports", NULL }; /*******************************************************************/ /* Agent specific variables */ /*******************************************************************/ static void ThisAgentInit(void); static GenericAgentConfig *CheckOpts(int argc, char **argv); static char **TranslateOldBootstrapOptionsSeparate(int *argc_new, char **argv); static char **TranslateOldBootstrapOptionsConcatenated(int argc, char **argv); static void FreeStringArray(int size, char **array); static void CheckAgentAccess(const Rlist *list, const Policy *policy); static void KeepControlPromises(EvalContext *ctx, const Policy *policy); static PromiseResult KeepAgentPromise(EvalContext *ctx, const Promise *pp, void *param); static int NewTypeContext(TypeSequence type); static void DeleteTypeContext(EvalContext *ctx, TypeSequence type); static void ClassBanner(EvalContext *ctx, TypeSequence type); static PromiseResult ParallelFindAndVerifyFilesPromises(EvalContext *ctx, const Promise *pp); static bool VerifyBootstrap(void); static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config); static void KeepPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config); static int NoteBundleCompliance(const Bundle *bundle, int save_pr_kept, int save_pr_repaired, int save_pr_notkept); static void AllClassesReport(const EvalContext *ctx); static bool HasAvahiSupport(void); static int AutomaticBootstrap(GenericAgentConfig *config); /*******************************************************************/ /* Command line options */ /*******************************************************************/ static const char *const CF_AGENT_SHORT_DESCRIPTION = "evaluate CFEngine policy code and actuate change to the system."; static const char *const CF_AGENT_MANPAGE_LONG_DESCRIPTION = "cf-agent evaluates policy code and makes changes to the system. Policy bundles are evaluated in the order of the " "provided bundlesequence (this is normally specified in the common control body). " "For each bundle, cf-agent groups promise statements according to their type. Promise types are then evaluated in a preset " "order to ensure fast system convergence to policy.\n"; static const struct option OPTIONS[] = { {"bootstrap", required_argument, 0, 'B'}, {"bundlesequence", required_argument, 0, 'b'}, {"debug", no_argument, 0, 'd'}, {"define", required_argument, 0, 'D'}, {"self-diagnostics", optional_argument, 0, 'x'}, {"dry-run", no_argument, 0, 'n'}, {"file", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {"inform", no_argument, 0, 'I'}, {"negate", required_argument, 0, 'N'}, {"no-lock", no_argument, 0, 'K'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"legacy-output", no_argument, 0, 'l'}, {"color", optional_argument, 0, 'C'}, {"no-extensions", no_argument, 0, 'E'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { "Bootstrap CFEngine to the given policy server IP, hostname or :avahi (automatic detection)", "Set or override bundlesequence from command line", "Enable debugging output", "Define a list of comma separated classes to be defined at the start of execution", "Run checks to diagnose a CFEngine agent installation", "All talk and no action mode - make no changes, only inform of promises not kept", "Specify an alternative input file than the default", "Print the help message", "Print basic information about changes made to the system, i.e. promises repaired", "Define a list of comma separated classes to be undefined at the start of execution", "Ignore locking constraints during execution (ifelapsed/expireafter) if \"too soon\" to run", "Output verbose information about the behaviour of the agent", "Output the version of the software", "Use legacy output format", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", "Disable extension loading (used while upgrading)", NULL }; /*******************************************************************/ int main(int argc, char *argv[]) { #ifdef HAVE_LIBXML2 xmlInitParser(); #endif struct timespec start = BeginMeasure(); GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); Policy *policy = NULL; if (GenericAgentCheckPolicy(config, ALWAYS_VALIDATE, true)) { policy = LoadPolicy(ctx, config); } else if (config->tty_interactive) { exit(EXIT_FAILURE); } else { Log(LOG_LEVEL_ERR, "CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe"); EvalContextClassPutHard(ctx, "failsafe_fallback", "attribute_name=Errors,source=agent"); GenericAgentConfigSetInputFile(config, GetInputDir(), "failsafe.cf"); policy = LoadPolicy(ctx, config); } assert(policy); ThisAgentInit(); BeginAudit(); KeepPromises(ctx, policy, config); if (ALLCLASSESREPORT) { AllClassesReport(ctx); } // only note class usage when default policy is run Nova_NoteClassUsage(ctx, config); Nova_NoteVarUsageDB(ctx, config); Nova_TrackExecution(config->input_file); PurgeLocks(); BackupLockDatabase(); PolicyDestroy(policy); /* Can we safely do this earlier ? */ int ret = 0; if (config->agent_specific.agent.bootstrap_policy_server && !VerifyBootstrap()) { RemovePolicyServerFile(GetWorkDir()); WriteAmPolicyHubFile(GetWorkDir(), false); ret = 1; } EndAudit(ctx, CFA_BACKGROUND); GenerateDiffReports(config); Nova_NoteAgentExecutionPerformance(config->input_file, start); GenericAgentFinalize(ctx, config); #ifdef HAVE_LIBXML2 xmlCleanupParser(); #endif return ret; } /*******************************************************************/ /* Level 1 */ /*******************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_AGENT); /* DEPRECATED: --policy-server (-s) is deprecated in community version 3.5.0. Support rewrite from some common old bootstrap options (until community version 3.6.0?). */ int argc_new = argc; char **argv_tmp = TranslateOldBootstrapOptionsSeparate(&argc_new, argv); char **argv_new = TranslateOldBootstrapOptionsConcatenated(argc_new, argv_tmp); FreeStringArray(argc_new, argv_tmp); /* true if cf-agent is executed by cf-serverd in response to a cf-runagent invocation. * In that case, prohibit file-input, no-lock and dry-runs to prevent remote execution of * arbitrary policy and DoS attacks. */ bool cfruncommand = false; while ((c = getopt_long(argc_new, argv_new, "dvnKIf:D:N:VxMB:b:hlC::E", OPTIONS, NULL)) != EOF) { switch ((char) c) { case 'l': LEGACY_OUTPUT = true; break; case 'f': GenericAgentConfigSetInputFile(config, GetInputDir(), optarg); MINUSF = true; break; case 'b': if (optarg) { Rlist *bundlesequence = RlistFromSplitString(optarg, ','); GenericAgentConfigSetBundleSequence(config, bundlesequence); RlistDestroy(bundlesequence); } break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case 'B': { if (!BootstrapAllowed()) { Log(LOG_LEVEL_ERR, "Not enough privileges to bootstrap CFEngine"); exit(EXIT_FAILURE); } if(strcmp(optarg, ":avahi") == 0) { if(!HasAvahiSupport()) { Log(LOG_LEVEL_ERR, "Avahi support is not built in, please see options to the configure script and rebuild CFEngine"); exit(EXIT_FAILURE); } int err = AutomaticBootstrap(config); if (err < 0) { Log(LOG_LEVEL_ERR, "Automatic bootstrap failed, error code '%d'", err); exit(EXIT_FAILURE); } break; } if(IsLoopbackAddress(optarg)) { Log(LOG_LEVEL_ERR, "Cannot bootstrap to a loopback address"); exit(EXIT_FAILURE); } // temporary assure that network functions are working OpenNetwork(); char mapped_policy_server[CF_MAX_IP_LEN] = ""; if (Hostname2IPString(mapped_policy_server, optarg, sizeof(mapped_policy_server)) == -1) { Log(LOG_LEVEL_ERR, "Could not resolve hostname '%s', unable to bootstrap", optarg); exit(EXIT_FAILURE); } CloseNetwork(); MINUSF = true; config->ignore_locks = true; GenericAgentConfigSetInputFile(config, GetInputDir(), "promises.cf"); config->agent_specific.agent.bootstrap_policy_server = xstrdup(mapped_policy_server); } break; case 'K': config->ignore_locks = true; break; case 'D': { StringSet *defined_classes = StringSetFromString(optarg, ','); cfruncommand = StringSetContains(defined_classes, "cfruncommand"); config->heap_soft = defined_classes; } break; case 'N': config->heap_negated = StringSetFromString(optarg, ','); break; case 'I': LogSetGlobalLevel(LOG_LEVEL_INFO); break; case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); break; case 'n': DONTDO = true; config->ignore_locks = true; break; case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-agent", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-agent", time(NULL), CF_AGENT_SHORT_DESCRIPTION, CF_AGENT_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, true); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'x': { const char *workdir = GetWorkDir(); const char *inputdir = GetInputDir(); const char *logdir = GetLogDir(); strcpy(CFWORKDIR, workdir); Writer *out = FileWriter(stdout); WriterWriteF(out, "self-diagnostics for agent using workdir '%s'\n", workdir); WriterWriteF(out, "self-diagnostics for agent using inputdir '%s'\n", inputdir); WriterWriteF(out, "self-diagnostics for agent using logdir '%s'\n", logdir); AgentDiagnosticsRun(workdir, AgentDiagnosticsAllChecks(), out); AgentDiagnosticsRunAllChecksNova(workdir, out, &AgentDiagnosticsRun, &AgentDiagnosticsResultNew); FileWriterDetach(out); } exit(EXIT_SUCCESS); case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; case 'E': extension_libraries_disable(); break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-agent", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_FAILURE); } } if (!GenericAgentConfigParseArguments(config, argc_new - optind, argv_new + optind)) { Log(LOG_LEVEL_ERR, "Too many arguments"); exit(EXIT_FAILURE); } if (cfruncommand) { /* Do not allow remote cf-agent executions that imply no-lock * or execution of a file other that promises.cf. */ if (config->ignore_locks) { Log(LOG_LEVEL_ERR, "Remote execution cannot ignore locks"); exit(EXIT_FAILURE); } if (MINUSF) // GenericAgentConfigSetInputFile also sets MINUSF { Log(LOG_LEVEL_ERR, "Specifying input files is not allowed for remote execution"); exit(EXIT_FAILURE); } } FreeStringArray(argc_new, argv_new); return config; } static char **TranslateOldBootstrapOptionsSeparate(int *argc_new, char **argv) { int i; int policy_server_argnum = 0; int server_address_argnum = 0; int bootstrap_argnum = 0; int argc = *argc_new; for(i = 0; i < argc; i++) { if(strcmp(argv[i], "--policy-server") == 0 || strcmp(argv[i], "-s") == 0) { policy_server_argnum = i; } if(strcmp(argv[i], "--bootstrap") == 0 || strcmp(argv[i], "-B") == 0) { bootstrap_argnum = i; } } if(policy_server_argnum > 0) { if(policy_server_argnum + 1 < argc) { server_address_argnum = policy_server_argnum + 1; } } char **argv_new; if(bootstrap_argnum > 0 && server_address_argnum > 0) { Log(LOG_LEVEL_WARNING, "Deprecated bootstrap options detected. The --policy-server (-s) option is deprecated from CFEngine community version 3.5.0." "Please provide the address argument to --bootstrap (-B) instead. Rewriting your arguments now, but you need to adjust them as this support will be removed soon."); *argc_new = argc - 1; // --policy-server deprecated argv_new = xcalloc(1, sizeof(char *) * (*argc_new + 1)); int new_i = 0; for(i = 0; i < argc; i++) { if(i == bootstrap_argnum) { argv_new[new_i++] = xstrdup(argv[bootstrap_argnum]); argv_new[new_i++] = xstrdup(argv[server_address_argnum]); } else if(i == server_address_argnum) { // skip: handled above } else if(i == policy_server_argnum) { // skip: deprecated } else { argv_new[new_i++] = xstrdup(argv[i]); } } } else { argv_new = xcalloc(1, sizeof(char *) * (*argc_new + 1)); for(i = 0; i < argc; i++) { argv_new[i] = xstrdup(argv[i]); } } return argv_new; } static char **TranslateOldBootstrapOptionsConcatenated(int argc, char **argv) { char **argv_new = xcalloc(1, sizeof(char *) * (argc + 1)); for(int i = 0; i < argc; i++) { if(strcmp(argv[i], "-Bs") == 0) { Log(LOG_LEVEL_WARNING, "Deprecated bootstrap options detected. The --policy-server (-s) option is deprecated from CFEngine community version 3.5.0." "Please provide the address argument to --bootstrap (-B) instead. Rewriting your arguments now, but you need to adjust them as this support will be removed soon."); argv_new[i] = xstrdup("-B"); } else { argv_new[i] = xstrdup(argv[i]); } } return argv_new; } static void FreeStringArray(int size, char **array) { for(int i = 0; i < size; i++) { free(array[i]); } free(array); } /*******************************************************************/ static void ThisAgentInit(void) { FILE *fp; char filename[CF_BUFSIZE]; #ifdef HAVE_SETSID Log(LOG_LEVEL_VERBOSE, "Setting session ID, becoming process group leader"); setsid(); #endif signal(SIGINT, HandleSignalsForAgent); signal(SIGTERM, HandleSignalsForAgent); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForAgent); signal(SIGUSR2, HandleSignalsForAgent); CFA_MAXTHREADS = 30; EDITFILESIZE = 100000; /* do not set signal(SIGCHLD,SIG_IGN) in agent near popen() - or else pclose will fail to return status which we need for setting returns */ snprintf(filename, CF_BUFSIZE, "%s/cfagent.%s.log", GetLogDir(), VSYSNAME.nodename); MapName(filename); if ((fp = fopen(filename, "a")) != NULL) { fclose(fp); } } /*******************************************************************/ static void KeepPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { KeepControlPromises(ctx, policy); KeepPromiseBundles(ctx, policy, config); } /*******************************************************************/ /* Level 2 */ /*******************************************************************/ static void KeepControlPromises(EvalContext *ctx, const Policy *policy) { Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_AGENT); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } if (EvalContextVariableControlCommonGet(ctx, CommonControlFromString(cp->lval))) { /* Already handled in generic_agent */ continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_agent"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in agent control body", cp->lval); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_MAXCONNECTIONS].lval) == 0) { CFA_MAXTHREADS = (int) IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting maxconnections to %d", CFA_MAXTHREADS); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_CHECKSUM_ALERT_TIME].lval) == 0) { CF_PERSISTENCE = (int) IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting checksum_alert_time to %d", CF_PERSISTENCE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_AGENTFACILITY].lval) == 0) { SetFacility(value); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_AGENTACCESS].lval) == 0) { ACCESSLIST = value; CheckAgentAccess(ACCESSLIST, policy); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_REFRESH_PROCESSES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting refresh_processes when starting to..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { Log(LOG_LEVEL_VERBOSE, "%s", RlistScalarValue(rp)); // TODO: why is this only done in verbose mode? // original commit says 'optimization'. if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { PrependItem(&PROCESSREFRESH, RlistScalarValue(rp), NULL); } } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_ABORTCLASSES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting abort classes from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE] = ""; strlcpy(name, RlistScalarValue(rp), CF_MAXVARSIZE); EvalContextHeapAddAbort(ctx, name, cp->classes); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_ABORTBUNDLECLASSES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting abort bundle classes from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { char name[CF_MAXVARSIZE] = ""; strlcpy(name, RlistScalarValue(rp), CF_MAXVARSIZE); EvalContextHeapAddAbortCurrentBundle(ctx, name, cp->classes); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_ADDCLASSES].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Add classes ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { Log(LOG_LEVEL_VERBOSE, "... %s", RlistScalarValue(rp)); EvalContextClassPutSoft(ctx, RlistScalarValue(rp), CONTEXT_SCOPE_NAMESPACE, "source=environment"); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_ALWAYSVALIDATE].lval) == 0) { ALWAYS_VALIDATE = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting alwaysvalidate to '%s'", ALWAYS_VALIDATE ? "true" : "false"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_ALLCLASSESREPORT].lval) == 0) { ALLCLASSESREPORT = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting allclassesreport to '%s'", ALLCLASSESREPORT ? "true" : "false"); } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_SECUREINPUT].lval) == 0) { CFPARANOID = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting secure input to '%s'", CFPARANOID ? "true" : "false"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_BINDTOINTERFACE].lval) == 0) { strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE)); Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_HASHUPDATES].lval) == 0) { bool enabled = BooleanFromString(value); SetChecksumUpdatesDefault(ctx, enabled); Log(LOG_LEVEL_VERBOSE, "Setting checksum updates to '%s'", enabled ? "true" : "false"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_CHILDLIBPATH].lval) == 0) { char output[CF_BUFSIZE]; snprintf(output, CF_BUFSIZE, "Setting LD_LIBRARY_PATH to '%s'", (const char *)value); if (putenv(xstrdup(output)) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting '%s'", output); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_DEFAULTCOPYTYPE].lval) == 0) { DEFAULT_COPYTYPE = value; Log(LOG_LEVEL_VERBOSE, "Setting defaultcopytype to '%s'", DEFAULT_COPYTYPE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_FSINGLECOPY].lval) == 0) { SINGLE_COPY_LIST = value; Log(LOG_LEVEL_VERBOSE, "Setting file single copy list"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_FAUTODEFINE].lval) == 0) { SetFileAutoDefineList(value); Log(LOG_LEVEL_VERBOSE, "Setting file auto define list"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_DRYRUN].lval) == 0) { DONTDO = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting dryrun to %c", DONTDO); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_INFORM].lval) == 0) { bool inform = BooleanFromString(value); if (inform) { LogSetGlobalLevel(MAX(LOG_LEVEL_INFO, LogGetGlobalLevel())); } else { if (LogGetGlobalLevel() >= LOG_LEVEL_INFO) { LogSetGlobalLevel(LOG_LEVEL_NOTICE); } } Log(LOG_LEVEL_VERBOSE, "body agent control, inform => '%s', sets new log level to '%s'", inform ? "true" : "false", LogLevelToString(LogGetGlobalLevel())); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_VERBOSE].lval) == 0) { bool verbose = BooleanFromString(value); if (verbose) { LogSetGlobalLevel(MAX(LOG_LEVEL_VERBOSE, LogGetGlobalLevel())); } else { if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { LogSetGlobalLevel(LOG_LEVEL_INFO); } } Log(LOG_LEVEL_VERBOSE, "body agent control, verbose => '%s', sets new log level to '%s'", verbose ? "true" : "false", LogLevelToString(LogGetGlobalLevel())); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_REPOSITORY].lval) == 0) { SetRepositoryLocation(value); Log(LOG_LEVEL_VERBOSE, "SET repository = %s", (const char *)value); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_SKIPIDENTIFY].lval) == 0) { bool enabled = BooleanFromString(value); SetSkipIdentify(enabled); Log(LOG_LEVEL_VERBOSE, "Setting skipidentify to '%s'", enabled ? "true" : "false"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_SUSPICIOUSNAMES].lval) == 0) { for (const Rlist *rp = value; rp != NULL; rp = rp->next) { AddFilenameToListOfSuspicious(RlistScalarValue(rp)); Log(LOG_LEVEL_VERBOSE, "Considering '%s' as suspicious file", RlistScalarValue(rp)); } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_REPCHAR].lval) == 0) { char c = *(char *)value; SetRepositoryChar(c); Log(LOG_LEVEL_VERBOSE, "Setting repchar to '%c'", c); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_MOUNTFILESYSTEMS].lval) == 0) { CF_MOUNTALL = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting mountfilesystems to '%s'", CF_MOUNTALL ? "true" : "false"); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_EDITFILESIZE].lval) == 0) { EDITFILESIZE = IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting edit file size to %d", EDITFILESIZE); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_IFELAPSED].lval) == 0) { VIFELAPSED = IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting ifelapsed to %d", VIFELAPSED); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_EXPIREAFTER].lval) == 0) { VEXPIREAFTER = IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting expireafter to %d", VEXPIREAFTER); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_TIMEOUT].lval) == 0) { CONNTIMEOUT = IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting timeout = %jd", (intmax_t) CONNTIMEOUT); continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_MAX_CHILDREN].lval) == 0) { CFA_BACKGROUND_LIMIT = IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting max_children to %d", CFA_BACKGROUND_LIMIT); if (CFA_BACKGROUND_LIMIT > 10) { Log(LOG_LEVEL_ERR, "Silly value for max_children in agent control promise (%d > 10)", CFA_BACKGROUND_LIMIT); CFA_BACKGROUND_LIMIT = 1; } continue; } if (strcmp(cp->lval, CFA_CONTROLBODY[AGENT_CONTROL_ENVIRONMENT].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting environment variables from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { assert(strchr(RlistScalarValue(rp), '=')); /* Valid for putenv() */ if (putenv(xstrdup(RlistScalarValue(rp))) != 0) { Log(LOG_LEVEL_ERR, "Failed to set environment variable '%s'. (putenv: %s)", RlistScalarValue(rp), GetErrorStr()); } } continue; } } } const void *value = NULL; if ((value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER))) { LASTSEENEXPIREAFTER = IntFromString(value) * 60; } if ((value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE))) { FIPS_MODE = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to '%s'", FIPS_MODE ? "true" : "false"); } if ((value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT))) { SetSyslogPort(IntFromString(value)); Log(LOG_LEVEL_VERBOSE, "Setting syslog_port to '%s'", (const char *)value); } if ((value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST))) { /* Don't resolve syslog_host now, better do it per log request. */ if (!SetSyslogHost(value)) { Log(LOG_LEVEL_ERR, "FAILed to set syslog_host, '%s' too long", (const char *)value); } else { Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value); } } Nova_Initialize(ctx); } /*********************************************************************/ static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { const Rlist *bundlesequence = NULL; if (config->bundlesequence) { Log(LOG_LEVEL_INFO, "Using command line specified bundlesequence"); bundlesequence = config->bundlesequence; } else if (!(bundlesequence = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BUNDLESEQUENCE))) { Log(LOG_LEVEL_ERR, "No bundlesequence in the common control body"); exit(EXIT_FAILURE); } bool ok = true; for (const Rlist *rp = bundlesequence; rp; rp = rp->next) { const char *name = NULL; switch (rp->val.type) { case RVAL_TYPE_SCALAR: name = RlistScalarValue(rp); if (strcmp(name, CF_NULL_VALUE) == 0) { continue; } break; case RVAL_TYPE_FNCALL: name = RlistFnCallValue(rp)->name; break; default: name = NULL; { Writer *w = StringWriter(); WriterWrite(w, "Illegal item found in bundlesequence: "); RvalWrite(w, rp->val); Log(LOG_LEVEL_ERR, "%s", StringWriterData(w)); WriterClose(w); } ok = false; break; } if (!config->ignore_missing_bundles) { const Bundle *bp = EvalContextResolveBundleExpression(ctx, policy, name, "agent"); if (!bp) { bp = EvalContextResolveBundleExpression(ctx, policy, name, "common"); } if (!bp) { Log(LOG_LEVEL_ERR, "Bundle '%s' listed in the bundlesequence was not found", name); ok = false; } } } if (!ok) { FatalError(ctx, "Errors in agent bundles"); } if (LEGACY_OUTPUT) { Writer *w = StringWriter(); RlistWrite(w, bundlesequence); Log(LOG_LEVEL_VERBOSE, " -> Bundlesequence => %s", StringWriterData(w)); WriterClose(w); } else { Writer *w = StringWriter(); WriterWrite(w, "Using bundlesequence => "); RlistWrite(w, bundlesequence); Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w)); WriterClose(w); } /* If all is okay, go ahead and evaluate */ for (const Rlist *rp = bundlesequence; rp; rp = rp->next) { const char *name = NULL; const Rlist *args = NULL; switch (rp->val.type) { case RVAL_TYPE_FNCALL: name = RlistFnCallValue(rp)->name; args = RlistFnCallValue(rp)->args; break; default: name = RlistScalarValue(rp); args = NULL; break; } const Bundle *bp = EvalContextResolveBundleExpression(ctx, policy, name, "agent"); if (!bp) { bp = EvalContextResolveBundleExpression(ctx, policy, name, "common"); } if (bp) { BannerBundle(bp, args); EvalContextStackPushBundleFrame(ctx, bp, args, false); ScheduleAgentOperations(ctx, bp); EvalContextStackPopFrame(ctx); } else { if (config->ignore_missing_bundles) { Log(LOG_LEVEL_VERBOSE, "Ignoring missing bundle '%s'", name); } else { FatalError(ctx, "Bundlesequence contained unknown bundle reference '%s'", name); } } } } static void AllClassesReport(const EvalContext *ctx) { char context_report_file[CF_BUFSIZE]; snprintf(context_report_file, CF_BUFSIZE, "%s/state/allclasses.txt", CFWORKDIR); FILE *fp = NULL; if ((fp = fopen(context_report_file, "w")) == NULL) { Log(LOG_LEVEL_INFO, "Could not open allclasses cache file"); } else { Writer *writer = FileWriter(fp); ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); WriterWriteF(writer, "%s\n", expr); free(expr); } ClassTableIteratorDestroy(iter); WriterClose(writer); } } PromiseResult ScheduleAgentOperations(EvalContext *ctx, const Bundle *bp) // NB - this function can be called recursively through "methods" { int save_pr_kept = PR_KEPT; int save_pr_repaired = PR_REPAIRED; int save_pr_notkept = PR_NOTKEPT; if (PROCESSREFRESH == NULL || (PROCESSREFRESH && IsRegexItemIn(ctx, PROCESSREFRESH, bp->name))) { DeleteItemList(PROCESSTABLE); PROCESSTABLE = NULL; } PromiseResult result = PROMISE_RESULT_SKIPPED; for (int pass = 1; pass < CF_DONEPASSES; pass++) { Log(LOG_LEVEL_VERBOSE, "Evaluating bundle pass %d", pass); for (TypeSequence type = 0; AGENT_TYPESEQUENCE[type] != NULL; type++) { ClassBanner(ctx, type); const PromiseType *sp = BundleGetPromiseType((Bundle *)bp, AGENT_TYPESEQUENCE[type]); if (!sp || SeqLength(sp->promises) == 0) { continue; } BannerPromiseType(bp->name, sp->name, pass); if (!NewTypeContext(type)) { continue; } EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); PromiseResult promise_result = ExpandPromise(ctx, pp, KeepAgentPromise, NULL); result = PromiseResultUpdate(result, promise_result); if (Abort(ctx)) { DeleteTypeContext(ctx, type); EvalContextStackPopFrame(ctx); NoteBundleCompliance(bp, save_pr_kept, save_pr_repaired, save_pr_notkept); return result; } } DeleteTypeContext(ctx, type); EvalContextStackPopFrame(ctx); if (type == TYPE_SEQUENCE_CONTEXTS) { BundleResolve(ctx, bp); } } } NoteBundleCompliance(bp, save_pr_kept, save_pr_repaired, save_pr_notkept); return result; } /*********************************************************************/ #ifdef __MINGW32__ static void CheckAgentAccess(const Rlist *list, const Policy *policy) { } #else static void CheckAgentAccess(const Rlist *list, const Policy *policy) { uid_t uid = getuid(); for (const Rlist *rp = list; rp != NULL; rp = rp->next) { if (Str2Uid(RlistScalarValue(rp), NULL, NULL) == uid) { return; } } { StringSet *input_files = PolicySourceFiles(policy); StringSetIterator iter = StringSetIteratorInit(input_files); const char *input_file = NULL; while ((input_file = StringSetIteratorNext(&iter))) { struct stat sb; stat(input_file, &sb); if (ACCESSLIST) { bool access = false; for (const Rlist *rp2 = ACCESSLIST; rp2 != NULL; rp2 = rp2->next) { if (Str2Uid(RlistScalarValue(rp2), NULL, NULL) == sb.st_uid) { access = true; break; } } if (!access) { Log(LOG_LEVEL_ERR, "File '%s' is not owned by an authorized user (security exception)", input_file); exit(EXIT_FAILURE); } } else if (CFPARANOID && IsPrivileged()) { if (sb.st_uid != getuid()) { Log(LOG_LEVEL_ERR, "File '%s' is not owned by uid %ju (security exception)", input_file, (uintmax_t)getuid()); exit(EXIT_FAILURE); } } } StringSetDestroy(input_files); } Log(LOG_LEVEL_ERR, "You are denied access to run this policy"); exit(EXIT_FAILURE); } #endif /* !__MINGW32__ */ /*********************************************************************/ /**************************************************************/ static PromiseResult DefaultVarPromise(EvalContext *ctx, const Promise *pp) { char *regex = PromiseGetConstraintAsRval(pp, "if_match_regex", RVAL_TYPE_SCALAR); bool okay = true; DataType value_type = CF_DATA_TYPE_NONE; const void *value = NULL; { VarRef *ref = VarRefParseFromScope(pp->promiser, "this"); value = EvalContextVariableGet(ctx, ref, &value_type); VarRefDestroy(ref); } switch (value_type) { case CF_DATA_TYPE_STRING: case CF_DATA_TYPE_INT: case CF_DATA_TYPE_REAL: if (regex && !FullTextMatch(ctx, regex, value)) { return PROMISE_RESULT_NOOP; } if (regex == NULL) { return PROMISE_RESULT_NOOP; } break; case CF_DATA_TYPE_STRING_LIST: case CF_DATA_TYPE_INT_LIST: case CF_DATA_TYPE_REAL_LIST: if (regex) { for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (FullTextMatch(ctx, regex, RlistScalarValue(rp))) { okay = false; break; } } if (okay) { return PROMISE_RESULT_NOOP; } } break; default: break; } { VarRef *ref = VarRefParseFromBundle(pp->promiser, PromiseGetBundle(pp)); EvalContextVariableRemove(ctx, ref); VarRefDestroy(ref); } return VerifyVarPromise(ctx, pp, true); } static PromiseResult KeepAgentPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert(param == NULL); struct timespec start = BeginMeasure(); PromiseResult result = PROMISE_RESULT_NOOP; if (strcmp("meta", pp->parent_promise_type->name) == 0 || strcmp("vars", pp->parent_promise_type->name) == 0) { result = VerifyVarPromise(ctx, pp, true); } else if (strcmp("defaults", pp->parent_promise_type->name) == 0) { result = DefaultVarPromise(ctx, pp); } else if (strcmp("classes", pp->parent_promise_type->name) == 0) { result = VerifyClassPromise(ctx, pp, NULL); } else if (strcmp("processes", pp->parent_promise_type->name) == 0) { result = VerifyProcessesPromise(ctx, pp); } else if (strcmp("storage", pp->parent_promise_type->name) == 0) { result = FindAndVerifyStoragePromises(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("packages", pp->parent_promise_type->name) == 0) { result = VerifyPackagesPromise(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("users", pp->parent_promise_type->name) == 0) { result = VerifyUsersPromise(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("files", pp->parent_promise_type->name) == 0) { result = ParallelFindAndVerifyFilesPromises(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("commands", pp->parent_promise_type->name) == 0) { result = VerifyExecPromise(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("databases", pp->parent_promise_type->name) == 0) { result = VerifyDatabasePromises(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("methods", pp->parent_promise_type->name) == 0) { result = VerifyMethodsPromise(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("services", pp->parent_promise_type->name) == 0) { result = VerifyServicesPromise(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("guest_environments", pp->parent_promise_type->name) == 0) { result = VerifyEnvironmentsPromise(ctx, pp); EndMeasurePromise(start, pp); } else if (strcmp("reports", pp->parent_promise_type->name) == 0) { result = VerifyReportPromise(ctx, pp); } else { result = PROMISE_RESULT_NOOP; } EvalContextLogPromiseIterationOutcome(ctx, pp, result); return result; } /*********************************************************************/ /* Type context */ /*********************************************************************/ static int NewTypeContext(TypeSequence type) { // get maxconnections switch (type) { case TYPE_SEQUENCE_ENVIRONMENTS: NewEnvironmentsContext(); break; case TYPE_SEQUENCE_FILES: ConnectionsInit(); break; case TYPE_SEQUENCE_PROCESSES: if (!LoadProcessTable(&PROCESSTABLE)) { Log(LOG_LEVEL_ERR, "Unable to read the process table - cannot keep process promises"); return false; } break; case TYPE_SEQUENCE_STORAGE: #ifndef __MINGW32__ // TODO: Run if implemented on Windows if (SeqLength(GetGlobalMountedFSList())) { DeleteMountInfo(GetGlobalMountedFSList()); SeqClear(GetGlobalMountedFSList()); } #endif /* !__MINGW32__ */ break; default: break; } return true; } /*********************************************************************/ static void DeleteTypeContext(EvalContext *ctx, TypeSequence type) { switch (type) { case TYPE_SEQUENCE_ENVIRONMENTS: DeleteEnvironmentsContext(); break; case TYPE_SEQUENCE_FILES: ConnectionsCleanup(); break; case TYPE_SEQUENCE_PROCESSES: break; case TYPE_SEQUENCE_STORAGE: DeleteStorageContext(); break; case TYPE_SEQUENCE_PACKAGES: ExecuteScheduledPackages(ctx); CleanScheduledPackages(); break; default: break; } } /**************************************************************/ static void ClassBanner(EvalContext *ctx, TypeSequence type) { if (type != TYPE_SEQUENCE_INTERFACES) /* Just parsed all local classes */ { return; } if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, " + Private classes augmented:"); ClassTableIterator *iter = EvalContextClassTableIteratorNewLocal(ctx); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { Log(LOG_LEVEL_VERBOSE, " + %s", cls->name); } ClassTableIteratorDestroy(iter); } else { bool have_classes = false; Writer *w = StringWriter(); WriterWrite(w, "Private classes augmented:"); ClassTableIterator *iter = EvalContextClassTableIteratorNewLocal(ctx); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { WriterWriteChar(w, ' '); WriterWrite(w, cls->name); have_classes = true; } ClassTableIteratorDestroy(iter); if (have_classes) { Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w)); } WriterClose(w); } } /**************************************************************/ /* Thread context */ /**************************************************************/ #ifdef __MINGW32__ static PromiseResult ParallelFindAndVerifyFilesPromises(EvalContext *ctx, const Promise *pp) { int background = PromiseGetConstraintAsBoolean(ctx, "background", pp); if (background) { Log(LOG_LEVEL_VERBOSE, "Background processing of files promises is not supported on Windows"); } return FindAndVerifyFilesPromises(ctx, pp); } #else /* !__MINGW32__ */ static PromiseResult ParallelFindAndVerifyFilesPromises(EvalContext *ctx, const Promise *pp) { int background = PromiseGetConstraintAsBoolean(ctx, "background", pp); pid_t child = 1; PromiseResult result = PROMISE_RESULT_SKIPPED; if (background) { if (CFA_BACKGROUND < CFA_BACKGROUND_LIMIT) { CFA_BACKGROUND++; Log(LOG_LEVEL_VERBOSE, "Spawning new process..."); child = fork(); if (child == 0) { ALARM_PID = -1; result = PromiseResultUpdate(result, FindAndVerifyFilesPromises(ctx, pp)); Log(LOG_LEVEL_VERBOSE, "Exiting backgrounded promise"); PromiseRef(LOG_LEVEL_VERBOSE, pp); _exit(EXIT_SUCCESS); // TODO: need to solve this } } else { Log(LOG_LEVEL_VERBOSE, "Promised parallel execution promised but exceeded the max number of promised background tasks, so serializing"); background = 0; } } else { result = PromiseResultUpdate(result, FindAndVerifyFilesPromises(ctx, pp)); } return result; } #endif /* !__MINGW32__ */ /**************************************************************/ static bool VerifyBootstrap(void) { if (NULL_OR_EMPTY(POLICY_SERVER)) { Log(LOG_LEVEL_ERR, "Bootstrapping failed, no policy server is specified"); return false; } // we should at least have gotten promises.cf from the policy hub { char filename[CF_MAXVARSIZE]; snprintf(filename, sizeof(filename), "%s/promises.cf", GetInputDir()); MapName(filename); struct stat sb; if (stat(filename, &sb) == -1) { Log(LOG_LEVEL_ERR, "Bootstrapping failed, no input file at '%s' after bootstrap", filename); return false; } } // embedded failsafe.cf (bootstrap.c) contains a promise to start cf-execd (executed while running this cf-agent) DeleteItemList(PROCESSTABLE); PROCESSTABLE = NULL; LoadProcessTable(&PROCESSTABLE); if (!IsProcessNameRunning(".*cf-execd.*")) { Log(LOG_LEVEL_ERR, "Bootstrapping failed, cf-execd is not running"); return false; } Log(LOG_LEVEL_NOTICE, "Bootstrap to '%s' completed successfully!", POLICY_SERVER); return true; } /**************************************************************/ /* Compliance comp */ /**************************************************************/ static int NoteBundleCompliance(const Bundle *bundle, int save_pr_kept, int save_pr_repaired, int save_pr_notkept) { double delta_pr_kept, delta_pr_repaired, delta_pr_notkept; double bundle_compliance = 0.0; delta_pr_kept = (double) (PR_KEPT - save_pr_kept); delta_pr_notkept = (double) (PR_NOTKEPT - save_pr_notkept); delta_pr_repaired = (double) (PR_REPAIRED - save_pr_repaired); if (delta_pr_kept + delta_pr_notkept + delta_pr_repaired <= 0) { Log(LOG_LEVEL_VERBOSE, "Zero promises executed for bundle '%s'", bundle->name); return PROMISE_RESULT_NOOP; } Log(LOG_LEVEL_VERBOSE, "Bundle Accounting Summary for '%s'", bundle->name); Log(LOG_LEVEL_VERBOSE, "Promises kept in '%s' = %.0lf", bundle->name, delta_pr_kept); Log(LOG_LEVEL_VERBOSE, "Promises not kept in '%s' = %.0lf", bundle->name, delta_pr_notkept); Log(LOG_LEVEL_VERBOSE, "Promises repaired in '%s' = %.0lf", bundle->name, delta_pr_repaired); bundle_compliance = (delta_pr_kept + delta_pr_repaired) / (delta_pr_kept + delta_pr_notkept + delta_pr_repaired); Log(LOG_LEVEL_VERBOSE, "Aggregate compliance (promises kept/repaired) for bundle '%s' = %.1lf%%", bundle->name, bundle_compliance * 100.0); LastSawBundle(bundle, bundle_compliance); // return the worst case for the bundle status if (delta_pr_notkept > 0) { return PROMISE_RESULT_FAIL; } if (delta_pr_repaired > 0) { return PROMISE_RESULT_CHANGE; } return PROMISE_RESULT_NOOP; } #if defined(HAVE_AVAHI_CLIENT_CLIENT_H) && defined(HAVE_AVAHI_COMMON_ADDRESS_H) static bool HasAvahiSupport(void) { return true; } static int AutomaticBootstrap(GenericAgentConfig *config) { List *foundhubs = NULL; int hubcount = ListHubs(&foundhubs); int ret; switch(hubcount) { case -1: Log(LOG_LEVEL_ERR, "Error while trying to find a Policy Server"); ret = -1; break; case 0: Log(LOG_LEVEL_ERR, "No hubs were found. Exiting."); ret = -1; break; case 1: { char *hostname = ((HostProperties*)foundhubs)->Hostname; char *ipaddr = ((HostProperties*)foundhubs)->IPAddress; Log(LOG_LEVEL_NOTICE, "Autodiscovered hub installed on hostname '%s', IP address '%s'", hostname, ipaddr); if (strlen(ipaddr) < sizeof(POLICY_SERVER)) { config->agent_specific.agent.bootstrap_policy_server = xstrdup(ipaddr); ret = 0; } else { Log(LOG_LEVEL_ERR, "Invalid autodiscovered hub IP address '%s'", ipaddr); ret = -1; } break; } default: Log(LOG_LEVEL_ERR, "Found more than one hub registered in the network. Please bootstrap manually using IP from the list below."); PrintList(foundhubs); ret = -1; }; if (avahi_handle) { /* * This case happens when dlopen does not manage to open the library. */ dlclose(avahi_handle); } ListDestroy(&foundhubs); return ret; } #else static bool HasAvahiSupport(void) { return false; } static int AutomaticBootstrap(ARG_UNUSED GenericAgentConfig *config) { ProgrammingError("Attempted automated bootstrap on a non-avahi build of CFEngine"); } #endif // Avahi cfengine-3.6.2/cf-agent/verify_databases.c0000664000175100017510000007653712411001073020170 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int CheckDatabaseSanity(Attributes a, const Promise *pp); static PromiseResult VerifySQLPromise(EvalContext *ctx, Attributes a, const Promise *pp); static int VerifyDatabasePromise(CfdbConn *cfdb, char *database, Attributes a); static int ValidateSQLTableName(char *table_path, char *db, char *table); static int VerifyTablePromise(EvalContext *ctx, CfdbConn *cfdb, char *table_path, Rlist *columns, Attributes a, const Promise *pp, PromiseResult *result); static int ValidateSQLTableName(char *table_path, char *db, char *table); static void QueryTableColumns(char *s, char *db, char *table); static int NewSQLColumns(char *table, Rlist *columns, char ***name_table, char ***type_table, int **size_table, int **done); static void DeleteSQLColumns(char **name_table, char **type_table, int *size_table, int *done, int len); static void CreateDBQuery(DatabaseType type, char *query); static int CreateTableColumns(CfdbConn *cfdb, char *table, Rlist *columns); static int CheckSQLDataType(char *type, char *ref_type, const Promise *pp); static int TableExists(CfdbConn *cfdb, char *name); static Rlist *GetSQLTables(CfdbConn *cfdb); static void ListTables(int type, char *query); static int ValidateRegistryPromiser(char *s, const Promise *pp); static int CheckRegistrySanity(Attributes a, const Promise *pp); /*****************************************************************************/ PromiseResult VerifyDatabasePromises(EvalContext *ctx, const Promise *pp) { PromiseBanner(pp); Attributes a = GetDatabaseAttributes(ctx, pp); if (!CheckDatabaseSanity(a, pp)) { return PROMISE_RESULT_FAIL; } if (strcmp(a.database.type, "sql") == 0) { return VerifySQLPromise(ctx, a, pp); } else if (strcmp(a.database.type, "ms_registry") == 0) { #if defined(__MINGW32__) return VerifyRegistryPromise(ctx, a, pp); #endif return PROMISE_RESULT_NOOP; } else { ProgrammingError("Unknown database type '%s'", a.database.type); } } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static PromiseResult VerifySQLPromise(EvalContext *ctx, Attributes a, const Promise *pp) { char database[CF_MAXVARSIZE], table[CF_MAXVARSIZE], query[CF_BUFSIZE]; char *sp; int count = 0; CfdbConn cfdb; CfLock thislock; char lockname[CF_BUFSIZE]; snprintf(lockname, CF_BUFSIZE - 1, "db-%s", pp->promiser); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } database[0] = '\0'; table[0] = '\0'; for (sp = pp->promiser; *sp != '\0'; sp++) { if (strchr("./\\", *sp)) { count++; strlcpy(table, sp + 1, CF_MAXVARSIZE); sscanf(pp->promiser, "%[^.\\/]", database); if (strlen(database) == 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "SQL database promiser syntax should be of the form \"database.table\""); PromiseRef(LOG_LEVEL_ERR, pp); YieldCurrentLock(thislock); return PROMISE_RESULT_FAIL; } } } PromiseResult result = PROMISE_RESULT_NOOP; if (count > 1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "SQL database promiser syntax should be of the form \"database.table\""); PromiseRef(LOG_LEVEL_ERR, pp); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } if (strlen(database) == 0) { strlcpy(database, pp->promiser, CF_MAXVARSIZE); } if (a.database.operation == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Missing database_operation in database promise"); PromiseRef(LOG_LEVEL_ERR, pp); YieldCurrentLock(thislock); return PROMISE_RESULT_FAIL; } if (strcmp(a.database.operation, "delete") == 0) { /* Just deal with one */ strcpy(a.database.operation, "drop"); } /* Connect to the server */ CfConnectDB(&cfdb, a.database.db_server_type, a.database.db_server_host, a.database.db_server_owner, a.database.db_server_password, database); if (!cfdb.connected) { /* If we haven't said create then db should already exist */ if ((a.database.operation) && (strcmp(a.database.operation, "create") != 0)) { Log(LOG_LEVEL_ERR, "Could not connect an existing database '%s' - check server configuration?", database); PromiseRef(LOG_LEVEL_ERR, pp); CfCloseDB(&cfdb); YieldCurrentLock(thislock); return PROMISE_RESULT_FAIL; } } /* Check change of existential constraints */ if ((a.database.operation) && (strcmp(a.database.operation, "create") == 0)) { CfConnectDB(&cfdb, a.database.db_server_type, a.database.db_server_host, a.database.db_server_owner, a.database.db_server_password, a.database.db_connect_db); if (!cfdb.connected) { Log(LOG_LEVEL_ERR, "Could not connect to the sql_db server for '%s'", database); return PROMISE_RESULT_FAIL; } /* Don't drop the db if we really want to drop a table */ if ((strlen(table) == 0) || ((strlen(table) > 0) && (strcmp(a.database.operation, "drop") != 0))) { VerifyDatabasePromise(&cfdb, database, a); } /* Close the database here to commit the change - might have to reopen */ CfCloseDB(&cfdb); } /* Now check the structure of the named table, if any */ if (strlen(table) == 0) { YieldCurrentLock(thislock); return result; } CfConnectDB(&cfdb, a.database.db_server_type, a.database.db_server_host, a.database.db_server_owner, a.database.db_server_password, database); if (!cfdb.connected) { Log(LOG_LEVEL_INFO, "Database '%s' is not connected", database); } else { snprintf(query, CF_MAXVARSIZE - 1, "%s.%s", database, table); if (VerifyTablePromise(ctx, &cfdb, query, a.database.columns, a, pp, &result)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Table '%s' is as promised", query); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Table '%s' is not as promised", query); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } /* Finally check any row constraints on this table */ if (a.database.rows) { Log(LOG_LEVEL_INFO, "Database row operations are not currently supported. Please contact cfengine with suggestions."); } CfCloseDB(&cfdb); } YieldCurrentLock(thislock); return result; } static int VerifyDatabasePromise(CfdbConn *cfdb, char *database, Attributes a) { char query[CF_BUFSIZE], name[CF_MAXVARSIZE]; int found = false; Log(LOG_LEVEL_VERBOSE, "Verifying promised database"); if (!cfdb->connected) { Log(LOG_LEVEL_INFO, "Database '%s' is not connected", database); return false; } CreateDBQuery(cfdb->type, query); CfNewQueryDB(cfdb, query); if (cfdb->maxcolumns < 1) { Log(LOG_LEVEL_ERR, "The schema did not promise the expected number of fields - got %d expected >= %d", cfdb->maxcolumns, 1); return false; } while (CfFetchRow(cfdb)) { strlcpy(name, CfFetchColumn(cfdb, 0), CF_MAXVARSIZE); Log(LOG_LEVEL_VERBOSE, "Discovered a database called '%s'", name); if (strcmp(name, database) == 0) { found = true; } } if (found) { Log(LOG_LEVEL_VERBOSE, "Database '%s' exists on this connection", database); return true; } else { Log(LOG_LEVEL_VERBOSE, "Database '%s' does not seem to exist on this connection", database); } if ((a.database.operation) && (strcmp(a.database.operation, "drop") == 0)) { if (((a.transaction.action) != cfa_warn) && (!DONTDO)) { Log(LOG_LEVEL_VERBOSE, "Attempting to delete the database '%s'", database); snprintf(query, CF_MAXVARSIZE - 1, "drop database %s", database); CfVoidQueryDB(cfdb, query); return cfdb->result; } else { Log(LOG_LEVEL_ERR, "Need to delete the database '%s' but only a warning was promised", database); return false; } } if ((a.database.operation) && (strcmp(a.database.operation, "create") == 0)) { if (((a.transaction.action) != cfa_warn) && (!DONTDO)) { Log(LOG_LEVEL_VERBOSE, "Attempting to create the database '%s'", database); snprintf(query, CF_MAXVARSIZE - 1, "create database %s", database); CfVoidQueryDB(cfdb, query); return cfdb->result; } else { Log(LOG_LEVEL_ERR, "Need to create the database '%s' but only a warning was promised", database); return false; } } return false; } /*****************************************************************************/ static int CheckDatabaseSanity(Attributes a, const Promise *pp) { Rlist *rp; int retval = true, commas = 0; if ((a.database.type) && (strcmp(a.database.type, "ms_registry") == 0)) { retval = CheckRegistrySanity(a, pp); } else if ((a.database.type) && (strcmp(a.database.type, "sql") == 0)) { if ((strchr(pp->promiser, '.') == NULL) && (strchr(pp->promiser, '/') == NULL) && (strchr(pp->promiser, '\\') == NULL)) { if (a.database.columns) { Log(LOG_LEVEL_ERR, "Row values promised for an SQL table, but only the root database was promised"); retval = false; } if (a.database.rows) { Log(LOG_LEVEL_ERR, "Columns promised for an SQL table, but only the root database was promised"); retval = false; } } if (a.database.db_server_host == NULL) { Log(LOG_LEVEL_ERR, "No server host is promised for connecting to the SQL server"); retval = false; } if (a.database.db_server_owner == NULL) { Log(LOG_LEVEL_ERR, "No database login user is promised for connecting to the SQL server"); retval = false; } if (a.database.db_server_password == NULL) { Log(LOG_LEVEL_ERR, "No database authentication password is promised for connecting to the SQL server"); retval = false; } for (rp = a.database.columns; rp != NULL; rp = rp->next) { commas = CountChar(RlistScalarValue(rp), ','); if ((commas > 2) || (commas < 1)) { Log(LOG_LEVEL_ERR, "SQL Column format should be NAME,TYPE[,SIZE]"); retval = false; } } } if ((a.database.operation) && (strcmp(a.database.operation, "create") == 0)) { } if ((a.database.operation) && ((strcmp(a.database.operation, "delete") == 0) || (strcmp(a.database.operation, "drop") == 0))) { if (pp->comment == NULL) { Log(LOG_LEVEL_ERR, "When specifying a delete/drop from an SQL database you must add a comment. Take a backup of the database before making this change. This is a highly destructive operation."); retval = false; } } return retval; } static int CheckRegistrySanity(Attributes a, const Promise *pp) { bool retval = true; ValidateRegistryPromiser(pp->promiser, pp); if ((a.database.operation) && (strcmp(a.database.operation, "create") == 0)) { if (a.database.rows == NULL) { Log(LOG_LEVEL_INFO, "No row values promised for the MS registry database"); } if (a.database.columns != NULL) { Log(LOG_LEVEL_ERR, "Columns are only used to delete promised values for the MS registry database"); retval = false; } } if ((a.database.operation) && ((strcmp(a.database.operation, "delete") == 0) || (strcmp(a.database.operation, "drop") == 0))) { if (a.database.columns == NULL) { Log(LOG_LEVEL_INFO, "No columns were promised deleted in the MS registry database"); } if (a.database.rows != NULL) { Log(LOG_LEVEL_ERR, "Rows cannot be deleted in the MS registry database, only entire columns"); retval = false; } } for (Rlist *rp = a.database.rows; rp != NULL; rp = rp->next) { if (CountChar(RlistScalarValue(rp), ',') != 2) { Log(LOG_LEVEL_ERR, "Registry row format should be NAME,REG_SZ,VALUE, not '%s'", RlistScalarValue(rp)); retval = false; } } for (Rlist *rp = a.database.columns; rp != NULL; rp = rp->next) { if (CountChar(RlistScalarValue(rp), ',') > 0) { Log(LOG_LEVEL_ERR, "MS registry column format should be NAME only in deletion"); retval = false; } } return retval; } static int ValidateRegistryPromiser(char *key, const Promise *pp) { static char *const valid[] = { "HKEY_CLASSES_ROOT", "HKEY_CURRENT_CONFIG", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS", NULL }; char root_key[CF_MAXVARSIZE]; char *sp; int i; /* First remove the root key */ strlcpy(root_key, key, CF_MAXVARSIZE ); sp = strchr(root_key, '\\'); *sp = '\0'; for (i = 0; valid[i] != NULL; i++) { if (strcmp(root_key, valid[i]) == 0) { return true; } } Log(LOG_LEVEL_ERR, "Non-editable registry prefix '%s'", root_key); PromiseRef(LOG_LEVEL_ERR, pp); return false; } /*****************************************************************************/ /* Linker troubles require this code to be here in the main body */ /*****************************************************************************/ static int VerifyTablePromise(EvalContext *ctx, CfdbConn *cfdb, char *table_path, Rlist *columns, Attributes a, const Promise *pp, PromiseResult *result) { char name[CF_MAXVARSIZE], type[CF_MAXVARSIZE], query[CF_MAXVARSIZE], table[CF_MAXVARSIZE], db[CF_MAXVARSIZE]; int i, count, size, no_of_cols, *size_table, *done, identified, retval = true; char **name_table, **type_table; Log(LOG_LEVEL_VERBOSE, "Verifying promised table structure for '%s'", table_path); if (!ValidateSQLTableName(table_path, db, table)) { Log(LOG_LEVEL_ERR, "The structure of the promiser did not match that for an SQL table, i.e. 'database.table'"); return false; } else { Log(LOG_LEVEL_VERBOSE, "Assuming database '%s' with table '%s'", db, table); } /* Verify the existence of the tables within the database */ if (!TableExists(cfdb, table)) { Log(LOG_LEVEL_ERR, "The database did not contain the promised table '%s'", table_path); if ((a.database.operation) && (strcmp(a.database.operation, "create") == 0)) { if ((!DONTDO) && ((a.transaction.action) != cfa_warn)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_CHANGE, pp, a, "Database.table '%s' doesn't seem to exist, creating", table_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return CreateTableColumns(cfdb, table, columns); } else { Log(LOG_LEVEL_ERR, "Database.table '%s' doesn't seem to exist, but only a warning was promised", table_path); } } return false; } /* Get a list of the columns in the table */ QueryTableColumns(query, db, table); CfNewQueryDB(cfdb, query); if (cfdb->maxcolumns != 3) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Could not make sense of the columns"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); CfDeleteQuery(cfdb); return false; } /* Assume that the Rlist has been validated and consists of a,b,c */ count = 0; no_of_cols = RlistLen(columns); if (!NewSQLColumns(table, columns, &name_table, &type_table, &size_table, &done)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Could not make sense of the columns"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } /* Obtain columns from the named table - if any */ while (CfFetchRow(cfdb)) { char *sizestr; name[0] = '\0'; type[0] = '\0'; size = CF_NOINT; strlcpy(name, CfFetchColumn(cfdb, 0), CF_MAXVARSIZE); strlcpy(type, CfFetchColumn(cfdb, 1), CF_MAXVARSIZE); ToLowerStrInplace(type); sizestr = CfFetchColumn(cfdb, 2); if (sizestr) { size = IntFromString(sizestr); } Log(LOG_LEVEL_VERBOSE, "Discovered database column (%s,%s,%d)", name, type, size); if (sizestr && (size == CF_NOINT)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Integer size of SQL datatype could not be determined or was not specified - invalid promise."); DeleteSQLColumns(name_table, type_table, size_table, done, no_of_cols); CfDeleteQuery(cfdb); return false; } identified = false; for (i = 0; i < no_of_cols; i++) { if (done[i]) { continue; } if (strcmp(name, name_table[i]) == 0) { CheckSQLDataType(type, type_table[i], pp); if (size != size_table[i]) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Promised column '%s' in database.table '%s' has a non-matching array size (%d != %d)", name, table_path, size, size_table[i]); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } else { Log(LOG_LEVEL_VERBOSE, "Promised column '%s' in database.table '%s' is as promised", name, table_path); } count++; done[i] = true; identified = true; break; } } if (!identified) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Column '%s' found in database.table '%s' is not part of its promise.", name, table_path); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); if ((a.database.operation) && (strcmp(a.database.operation, "drop") == 0)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "CFEngine will not promise to repair this, as the operation is potentially too destructive."); // Future allow deletion? *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } retval = false; } } CfDeleteQuery(cfdb); /* Now look for deviations - only if we have promised to create missing */ if ((a.database.operation) && (strcmp(a.database.operation, "drop") == 0)) { return retval; } if (count != no_of_cols) { for (i = 0; i < no_of_cols; i++) { if (!done[i]) { Log(LOG_LEVEL_ERR, "Promised column '%s' missing from database table '%s'", name_table[i], pp->promiser); if ((!DONTDO) && ((a.transaction.action) != cfa_warn)) { if (size_table[i] > 0) { snprintf(query, CF_MAXVARSIZE - 1, "ALTER TABLE %s ADD %s %s(%d)", table, name_table[i], type_table[i], size_table[i]); } else { snprintf(query, CF_MAXVARSIZE - 1, "ALTER TABLE %s ADD %s %s", table, name_table[i], type_table[i]); } CfVoidQueryDB(cfdb, query); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_CHANGE, pp, a, "Adding promised column '%s' to database table '%s'", name_table[i], table); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); retval = true; } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Promised column '%s' missing from database table '%s' but only a warning was promised", name_table[i], table); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); retval = false; } } } } DeleteSQLColumns(name_table, type_table, size_table, done, no_of_cols); return retval; } /*****************************************************************************/ static int TableExists(CfdbConn *cfdb, char *name) { Rlist *rp, *list = NULL; int match = false; list = GetSQLTables(cfdb); for (rp = list; rp != NULL; rp = rp->next) { if (strcmp(name, RlistScalarValue(rp)) == 0) { match = true; } } RlistDestroy(list); return match; } /*****************************************************************************/ static int CreateTableColumns(CfdbConn *cfdb, char *table, Rlist *columns) { char entry[CF_MAXVARSIZE], query[CF_BUFSIZE]; int i, *size_table, *done; char **name_table, **type_table; int no_of_cols = RlistLen(columns); Log(LOG_LEVEL_ERR, "Trying to create table '%s'", table); if (!NewSQLColumns(table, columns, &name_table, &type_table, &size_table, &done)) { return false; } if (no_of_cols > 0) { snprintf(query, CF_BUFSIZE - 1, "create table %s(", table); for (i = 0; i < no_of_cols; i++) { Log(LOG_LEVEL_VERBOSE, "Forming column template %s %s %d", name_table[i], type_table[i], size_table[i]);; if (size_table[i] > 0) { snprintf(entry, CF_MAXVARSIZE - 1, "%s %s(%d)", name_table[i], type_table[i], size_table[i]); } else { snprintf(entry, CF_MAXVARSIZE - 1, "%s %s", name_table[i], type_table[i]); } strcat(query, entry); if (i < no_of_cols - 1) { strcat(query, ","); } } strcat(query, ")"); } CfVoidQueryDB(cfdb, query); DeleteSQLColumns(name_table, type_table, size_table, done, no_of_cols); return true; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static Rlist *GetSQLTables(CfdbConn *cfdb) { Rlist *list = NULL; char query[CF_MAXVARSIZE]; ListTables(cfdb->type, query); CfNewQueryDB(cfdb, query); if (cfdb->maxcolumns != 1) { Log(LOG_LEVEL_ERR, "Could not make sense of the columns"); CfDeleteQuery(cfdb); return NULL; } while (CfFetchRow(cfdb)) { RlistPrepend(&list, CfFetchColumn(cfdb, 0), RVAL_TYPE_SCALAR); } CfDeleteQuery(cfdb); return list; } /*****************************************************************************/ static void CreateDBQuery(DatabaseType type, char *query) { switch (type) { case DATABASE_TYPE_MYSQL: snprintf(query, CF_MAXVARSIZE - 1, "show databases"); break; case DATABASE_TYPE_POSTGRES: /* This gibberish is the simplest thing I can find in postgres */ snprintf(query, CF_MAXVARSIZE - 1, "SELECT pg_database.datname FROM pg_database"); break; default: snprintf(query, CF_MAXVARSIZE, "NULL QUERY"); break; } } /*****************************************************************************/ static int ValidateSQLTableName(char *table_path, char *db, char *table) { char *sp; int dot = false, back = false, fwd = false; /* Valid separators . / or \ only */ if ((sp = strchr(table_path, '/'))) { fwd = true; *sp = '.'; } if ((sp = strchr(table_path, '\\'))) { back = true; *sp = '.'; } if ((sp = strchr(table_path, '.'))) { dot = true; sp++; } /* Should contain a single separator */ if (dot + back + fwd != 1) { return false; } memset(db, 0, CF_MAXVARSIZE); strncpy(db, table_path, sp - table_path - 1); strlcpy(table, sp, CF_MAXVARSIZE); return true; } /*****************************************************************************/ static void QueryTableColumns(char *s, char *db, char *table) { snprintf(s, CF_MAXVARSIZE - 1, "SELECT column_name,data_type,character_maximum_length FROM information_schema.columns WHERE table_name ='%s' AND table_schema = '%s'", table, db); } /*****************************************************************************/ static int NewSQLColumns(char *table, Rlist *columns, char ***name_table, char ***type_table, int **size_table, int **done) { int i, no_of_cols = RlistLen(columns); Rlist *cols, *rp; *name_table = (char **) xmalloc(sizeof(char *) * (no_of_cols + 1)); *type_table = (char **) xmalloc(sizeof(char *) * (no_of_cols + 1)); *size_table = (int *) xmalloc(sizeof(int) * (no_of_cols + 1)); *done = (int *) xmalloc(sizeof(int) * (no_of_cols + 1)); for (i = 0, rp = columns; rp != NULL; rp = rp->next, i++) { (*done)[i] = 0; cols = RlistFromSplitString(RlistScalarValue(rp), ','); if (!cols) { Log(LOG_LEVEL_ERR, "No columns promised for table '%s' - makes no sense", table); return false; } if (cols->val.item == NULL) { Log(LOG_LEVEL_ERR, "Malformed column promise for table '%s' - found not even a name", table); free(*name_table); free(*type_table); free(*size_table); free(*done); return false; } (*name_table)[i] = xstrdup(RlistScalarValue(cols)); if (cols->next == NULL) { Log(LOG_LEVEL_ERR, "Malformed column '%s' promised for table '%s' - missing a type", (*name_table)[i], table); free(*name_table); free(*type_table); free(*size_table); free(*done); return false; } (*type_table)[i] = xstrdup(RlistScalarValue(cols->next)); if (cols->next->next == NULL) { (*size_table)[i] = 0; } else { if (cols->next->next->val.item) { (*size_table)[i] = IntFromString(RlistScalarValue(cols->next->next)); } else { (*size_table)[i] = 0; } } RlistDestroy(cols); } return true; } /*****************************************************************************/ static void DeleteSQLColumns(char **name_table, char **type_table, int *size_table, int *done, int len) { int i; if ((name_table == NULL) || (type_table == NULL) || (size_table == NULL)) { return; } for (i = 0; i < len; i++) { if (name_table[i] != NULL) { free(name_table[i]); } if (type_table[i] != NULL) { free(type_table[i]); } } free(name_table); free(type_table); free(size_table); free(done); } /*****************************************************************************/ static int CheckSQLDataType(char *type, char *ref_type, const Promise *pp) { static char *const aliases[3][2] = { {"varchar", "character@varying"}, {"varchar", "character varying"}, {NULL, NULL} }; int i; for (i = 0; aliases[i][0] != NULL; i++) { if ((strcmp(ref_type, aliases[i][0]) == 0) || (strcmp(ref_type, aliases[i][1]) == 0) || (strcmp(type, aliases[i][0]) == 0) || (strcmp(type, aliases[i][1]) == 0)) { if ((strcmp(type, ref_type) != 0) && (strcmp(aliases[i][0], ref_type) != 0)) { Log(LOG_LEVEL_VERBOSE, "Promised column in database '%s' has a non-matching type (%s != %s)", pp->promiser, ref_type, type); } } else { if (strcmp(type, ref_type) != 0) { Log(LOG_LEVEL_VERBOSE, "Promised column in database '%s' has a non-matching type (%s != %s)", pp->promiser, ref_type, type); } } } return true; } /*****************************************************************************/ static void ListTables(int type, char *query) { switch (type) { case DATABASE_TYPE_MYSQL: snprintf(query, CF_MAXVARSIZE - 1, "show tables"); break; case DATABASE_TYPE_POSTGRES: /* This gibberish is the simplest thing I can find in postgres */ snprintf(query, CF_MAXVARSIZE - 1, "SELECT c.relname as \"Name\" FROM pg_catalog.pg_class c JOIN pg_catalog.pg_roles r ON r.oid = c.relowner LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = 'public'"); break; default: snprintf(query, CF_MAXVARSIZE, "NULL QUERY"); break; } } cfengine-3.6.2/cf-agent/comparray.c0000664000175100017510000000543212243421446016651 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /*******************************************************************/ /* */ /* Compressed Arrays */ /* */ /*******************************************************************/ #include /*******************************************************************/ int FixCompressedArrayValue(int i, char *value, CompressedArray **start) { CompressedArray *ap; for (ap = *start; ap != NULL; ap = ap->next) { if (ap->key == i) { /* value already fixed */ return false; } } ap = xmalloc(sizeof(CompressedArray)); ap->key = i; ap->value = xstrdup(value); ap->next = *start; *start = ap; return true; } /*******************************************************************/ void DeleteCompressedArray(CompressedArray *start) { if (start != NULL) { DeleteCompressedArray(start->next); start->next = NULL; if (start->value != NULL) { free(start->value); } free(start); } } /*******************************************************************/ int CompressedArrayElementExists(CompressedArray *start, int key) { CompressedArray *ap; for (ap = start; ap != NULL; ap = ap->next) { if (ap->key == key) { return true; } } return false; } /*******************************************************************/ char *CompressedArrayValue(CompressedArray *start, int key) { CompressedArray *ap; for (ap = start; ap != NULL; ap = ap->next) { if (ap->key == key) { return ap->value; } } return NULL; } cfengine-3.6.2/cf-agent/nfs.c0000664000175100017510000006034612400110676015442 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* seconds */ #define RPCTIMEOUT 60 static int FSTAB_EDITS = 0; /* GLOBAL_X */ static Item *FSTABLIST = NULL; /* GLOBAL_X */ static void AugmentMountInfo(Seq *list, char *host, char *source, char *mounton, char *options); static int MatchFSInFstab(char *match); static void DeleteThisItem(Item **liststart, Item *entry); static const char *const VMOUNTCOMM[] = { [PLATFORM_CONTEXT_UNKNOWN] = "", [PLATFORM_CONTEXT_OPENVZ] = "/bin/mount -va", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/sbin/mount -ea", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/usr/sbin/mount -t nfs", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/bin/mount -va", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/usr/sbin/mount -a", /* solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/usr/sbin/mount -a", /* solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/sbin/mount -va", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/sbin/mount -a", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/etc/mount -va", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/bin/sh /etc/fstab", /* NT - possible security issue */ [PLATFORM_CONTEXT_SYSTEMV] = "/sbin/mountall", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/sbin/mount", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/etc/mountall", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/sbin/mount -va", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/bin/mount -v", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/sbin/mount -va", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "mingw-invalid", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/bin/mount -a", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "", /* android */ }; static const char *const VUNMOUNTCOMM[] = { [PLATFORM_CONTEXT_UNKNOWN] = "", [PLATFORM_CONTEXT_OPENVZ] = "/bin/umount", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/sbin/umount", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/usr/sbin/umount", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/bin/umount", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/etc/umount", /* solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/etc/umount", /* solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/sbin/umount", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/sbin/umount", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/etc/umount", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/bin/umount", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "/sbin/umount", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/sbin/umount", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/etc/umount", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/sbin/umount", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/bin/umount", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/sbin/umount", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "mingw-invalid", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/bin/umount", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "/system/xbin/umount", /* android */ }; static const char *const VMOUNTOPTS[] = { [PLATFORM_CONTEXT_UNKNOWN] = "", [PLATFORM_CONTEXT_OPENVZ] = "defaults", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "bg,hard,intr", /* hpux */ [PLATFORM_CONTEXT_AIX] = "bg,hard,intr", /* aix */ [PLATFORM_CONTEXT_LINUX] = "defaults", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "bg,hard,intr", /* solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "bg,hard,intr", /* solaris */ [PLATFORM_CONTEXT_FREEBSD] = "bg,intr", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "-i,-b", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "bg,hard,intr", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "bg,hard,intr", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "-i,-b", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "bg,hard,intr", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "-i,-b", /* darwin */ [PLATFORM_CONTEXT_QNX] = "bg,hard,intr", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "bg,intr", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "mingw-invalid", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "defaults", /* vmstate */ [PLATFORM_CONTEXT_ANDROID] = "defaults", /* android */ }; bool LoadMountInfo(Seq *list) /* This is, in fact, the most portable way to read the mount info! */ /* Depressing, isn't it? */ { FILE *pp; char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE], buf3[CF_BUFSIZE]; char host[CF_MAXVARSIZE], source[CF_BUFSIZE], mounton[CF_BUFSIZE]; int i, nfs = false; for (i = 0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++) { buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i]; } buf1[i] = '\0'; SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(buf1, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Can't open '%s'. (cf_popen: %s)", buf1, GetErrorStr()); return false; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); for (;;) { buf1[0] = buf2[0] = buf3[0] = source[0] = '\0'; nfs = false; ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Unable to read list of mounted filesystems. (fread: %s)", GetErrorStr()); cf_pclose(pp); free(vbuff); return false; } else { break; } } if (strstr(vbuff, "nfs")) { nfs = true; } sscanf(vbuff, "%s%s%s", buf1, buf2, buf3); if ((vbuff[0] == '\0') || (vbuff[0] == '\n')) { break; } if (strstr(vbuff, "not responding")) { Log(LOG_LEVEL_ERR, "%s", vbuff); } if (strstr(vbuff, "be root")) { Log(LOG_LEVEL_ERR, "Mount access is denied. You must be root. Use the -n option to run safely"); } if ((strstr(vbuff, "retrying")) || (strstr(vbuff, "denied")) || (strstr(vbuff, "backgrounding"))) { continue; } if ((strstr(vbuff, "exceeded")) || (strstr(vbuff, "busy"))) { continue; } if (strstr(vbuff, "RPC")) { Log(LOG_LEVEL_INFO, "There was an RPC timeout. Aborting mount operations."); Log(LOG_LEVEL_INFO, "Session failed while trying to talk to remote host"); Log(LOG_LEVEL_INFO, "%s", vbuff); cf_pclose(pp); free(vbuff); return false; } #if defined(__sun) || defined(__hpux) if (IsAbsoluteFileName(buf3)) { strcpy(host, "localhost"); strcpy(mounton, buf1); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf1); } #elif defined(_AIX) /* skip header */ if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf2); } else { strcpy(host, buf1); strcpy(source, buf1); strcpy(mounton, buf3); } #elif defined(__CYGWIN__) strcpy(mounton, buf2); strcpy(host, buf1); #elif defined(sco) || defined(__SCO_DS) Log(LOG_LEVEL_ERR, "Don't understand SCO mount format, no data"); #else if (IsAbsoluteFileName(buf1)) { strcpy(host, "localhost"); strcpy(mounton, buf3); } else { sscanf(buf1, "%[^:]:%s", host, source); strcpy(mounton, buf3); } #endif Log(LOG_LEVEL_DEBUG, "LoadMountInfo: host '%s', source '%s', mounton '%s'", host, source, mounton); if (nfs) { AugmentMountInfo(list, host, source, mounton, "nfs"); } else { AugmentMountInfo(list, host, source, mounton, NULL); } } free(vbuff); alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); return true; } /*******************************************************************/ static void AugmentMountInfo(Seq *list, char *host, char *source, char *mounton, char *options) { Mount *entry = xcalloc(1, sizeof(Mount)); if (host) { entry->host = xstrdup(host); } if (source) { entry->source = xstrdup(source); } if (mounton) { entry->mounton = xstrdup(mounton); } if (options) { entry->options = xstrdup(options); } SeqAppend(list, entry); } /*******************************************************************/ void DeleteMountInfo(Seq *list) { for (size_t i = 0; i < SeqLength(list); i++) { Mount *entry = SeqAt(list, i); if (entry->host) { free(entry->host); } if (entry->source) { free(entry->source); } if (entry->mounton) { free(entry->mounton); } if (entry->options) { free(entry->options); } } SeqClear(list); } /*******************************************************************/ int VerifyInFstab(EvalContext *ctx, char *name, Attributes a, const Promise *pp, PromiseResult *result) /* Ensure filesystem IS in fstab, and return no of changes */ { char fstab[CF_BUFSIZE]; char *host, *rmountpt, *mountpt, *fstype, *opts; if (!FSTABLIST) { if (!LoadFileAsItemList(&FSTABLIST, VFSTAB[VSYSTEMHARDCLASS], a.edits)) { Log(LOG_LEVEL_ERR, "Couldn't open '%s'", VFSTAB[VSYSTEMHARDCLASS]); return false; } else { FSTAB_EDITS = 0; } } if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; fstype = a.mount.mount_type; #if defined(__QNX__) || defined(__QNXNTO__) snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s %s\t%s 0 0", host, rmountpt, mountpt, fstype, opts); #elif defined(_CRAY) char fstype_upper[CF_BUFSIZE]; strlcpy(fstype_upper, fstype, CF_BUFSIZE); ToUpperStrInplace(fstype_upper); snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s %s\t%s", host, rmountpt, mountpt, fstype_upper, opts); break; #elif defined(__hpux) snprintf(fstab, CF_BUFSIZE, "%s:%s %s \t %s \t %s 0 0", host, rmountpt, mountpt, fstype, opts); #elif defined(_AIX) snprintf(fstab, CF_BUFSIZE, "%s:\n\tdev\t= %s\n\ttype\t= %s\n\tvfs\t= %s\n\tnodename\t= %s\n\tmount\t= true\n\toptions\t= %s\n\taccount\t= false\n", mountpt, rmountpt, fstype, fstype, host, opts); #elif defined(__linux__) snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s \t %s \t %s", host, rmountpt, mountpt, fstype, opts); #elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) snprintf(fstab, CF_BUFSIZE, "%s:%s \t %s \t %s \t %s 0 0", host, rmountpt, mountpt, fstype, opts); #elif defined(__sun) || defined(sco) || defined(__SCO_DS) snprintf(fstab, CF_BUFSIZE, "%s:%s - %s %s - yes %s", host, rmountpt, mountpt, fstype, opts); #elif defined(__CYGWIN__) snprintf(fstab, CF_BUFSIZE, "/bin/mount %s:%s %s", host, rmountpt, mountpt); #endif Log(LOG_LEVEL_VERBOSE, "Verifying '%s' in '%s'", mountpt, VFSTAB[VSYSTEMHARDCLASS]); if (!MatchFSInFstab(mountpt)) { AppendItem(&FSTABLIST, fstab, NULL); FSTAB_EDITS++; cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Adding file system '%s:%s' to '%s'", host, rmountpt, VFSTAB[VSYSTEMHARDCLASS]); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } free(opts); return 0; } /*******************************************************************/ int VerifyNotInFstab(EvalContext *ctx, char *name, Attributes a, const Promise *pp, PromiseResult *result) /* Ensure filesystem is NOT in fstab, and return no of changes */ { char regex[CF_BUFSIZE]; char *host, *mountpt, *opts; Item *ip; if (!FSTABLIST) { if (!LoadFileAsItemList(&FSTABLIST, VFSTAB[VSYSTEMHARDCLASS], a.edits)) { Log(LOG_LEVEL_ERR, "Couldn't open '%s'", VFSTAB[VSYSTEMHARDCLASS]); return false; } else { FSTAB_EDITS = 0; } } if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } host = a.mount.mount_server; mountpt = name; if (MatchFSInFstab(mountpt)) { if (a.mount.editfstab) { #if defined(_AIX) FILE *pfp; char aixcomm[CF_BUFSIZE]; snprintf(aixcomm, CF_BUFSIZE, "/usr/sbin/rmnfsmnt -f %s", mountpt); if ((pfp = cf_popen(aixcomm, "r", true)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed to invoke /usr/sbin/rmnfsmnt to edit fstab"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return 0; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = getline(&line, &line_size, pfp); if (res == -1) { if (!feof(pfp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to read output of /bin/rmnfsmnt"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); cf_pclose(pfp); free(line); return 0; } else { break; } } if (line[0] == '#') { continue; } if (strstr(line, "busy")) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under '%s' cannot be removed from '%s'", mountpt, VFSTAB[VSYSTEMHARDCLASS]); *result = PromiseResultUpdate(*result, PROMISE_RESULT_INTERRUPTED); free(line); return 0; } } free(line); cf_pclose(pfp); return 0; /* ignore internal editing for aix , always returns 0 changes */ #else Item* next; snprintf(regex, CF_BUFSIZE, ".*[\\s]+%s[\\s]+.*", mountpt); for (ip = FSTABLIST; ip != NULL; ip = next) { next = ip->next; if (FullTextMatch(ctx, regex, ip->name)) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Deleting file system mounted on '%s'", host); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); // Check host name matches too? DeleteThisItem(&FSTABLIST, ip); FSTAB_EDITS++; } } #endif } } if (a.mount.mount_options) { free(opts); } return 0; } /*******************************************************************/ PromiseResult VerifyMount(EvalContext *ctx, char *name, Attributes a, const Promise *pp) { char comm[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt, *opts=NULL; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; /* Check for options required for this mount - i.e., -o ro,rsize, etc. */ if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } PromiseResult result = PROMISE_RESULT_NOOP; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s -o %s %s:%s %s", CommandArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), opts, host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from '%s'", CommandArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return PROMISE_RESULT_FAIL; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); ssize_t res = CfReadLine(&line, &line_size, pfp); if (res == -1) { if (!feof(pfp)) { Log(LOG_LEVEL_ERR, "Unable to read output of mount command. (fread: %s)", GetErrorStr()); cf_pclose(pfp); free(line); return PROMISE_RESULT_FAIL; } } else if ((strstr(line, "busy")) || (strstr(line, "Busy"))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under '%s' cannot be mounted", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); cf_pclose(pfp); free(line); return 1; } free(line); cf_pclose(pfp); } /* Since opts is either Rlist2String or xstrdup'd, we need to always free it */ free(opts); cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Mounting '%s' to keep promise", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); return result; } /*******************************************************************/ PromiseResult VerifyUnmount(EvalContext *ctx, char *name, Attributes a, const Promise *pp) { char comm[CF_BUFSIZE]; FILE *pfp; char *mountpt; mountpt = name; PromiseResult result = PROMISE_RESULT_NOOP; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS], mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS]); return result; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); ssize_t res = CfReadLine(&line, &line_size, pfp); if (res == -1) { cf_pclose(pfp); free(line); if (!feof(pfp)) { Log(LOG_LEVEL_ERR, "Unable to read output of unmount command. (fread: %s)", GetErrorStr()); return result; } } else if (res > 0 && ((strstr(line, "busy")) || (strstr(line, "Busy")))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under '%s' cannot be unmounted", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); cf_pclose(pfp); free(line); return result; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Unmounting '%s' to keep promise", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); return result; } /*******************************************************************/ static int MatchFSInFstab(char *match) { Item *ip; for (ip = FSTABLIST; ip != NULL; ip = ip->next) { if (strstr(ip->name, match)) { return true; } } return false; } /*******************************************************************/ void MountAll() { FILE *pp; if (DONTDO) { Log(LOG_LEVEL_VERBOSE, "Promised to mount filesystem, but not on this trial run"); return; } else { Log(LOG_LEVEL_VERBOSE, "Attempting to mount all filesystems."); } #if defined(__CYGWIN__) /* This is a shell script. Make sure it hasn't been compromised. */ struct stat sb; if (stat("/etc/fstab", &sb) == -1) { int fd; if ((fd = creat("/etc/fstab", 0755)) > 0) { if (write(fd, "#!/bin/sh\n\n", 10) != 10) { UnexpectedError("Failed to write to file '/etc/fstab'"); } close(fd); } else { if (sb.st_mode & (S_IWOTH | S_IWGRP)) { Log(LOG_LEVEL_ERR, "File /etc/fstab was insecure. Cannot mount filesystems."); return; } } } #endif SetTimeOut(RPCTIMEOUT); if ((pp = cf_popen(VMOUNTCOMM[VSYSTEMHARDCLASS], "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from '%s'. (cf_popen: %s)", VMOUNTCOMM[VSYSTEMHARDCLASS], GetErrorStr()); return; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Error reading list of mounted filesystems. (ferror: %s)", GetErrorStr()); } break; } if ((strstr(line, "already mounted")) || (strstr(line, "exceeded")) || (strstr(line, "determined"))) { continue; } if (strstr(line, "not supported")) { continue; } if ((strstr(line, "denied")) || (strstr(line, "RPC"))) { Log(LOG_LEVEL_ERR, "There was a mount error, trying to mount one of the filesystems on this host."); break; } if ((strstr(line, "trying")) && (!strstr(line, "NFS version 2")) && (!strstr(line, "vers 3"))) { Log(LOG_LEVEL_ERR, "Attempting abort because mount went into a retry loop."); break; } } free(line); alarm(0); signal(SIGALRM, SIG_DFL); cf_pclose(pp); } /*******************************************************************/ /* Addendum */ /*******************************************************************/ static void DeleteThisItem(Item **liststart, Item *entry) { Item *ip, *sp; if (entry != NULL) { if (entry->name != NULL) { free(entry->name); } sp = entry->next; if (entry == *liststart) { *liststart = sp; } else { for (ip = *liststart; ip->next != entry; ip = ip->next) { } ip->next = sp; } free((char *) entry); } } void CleanupNFS(void) { Log(LOG_LEVEL_VERBOSE, "Number of changes observed in '%s' is %d", VFSTAB[VSYSTEMHARDCLASS], FSTAB_EDITS); if (FSTAB_EDITS && FSTABLIST && !DONTDO) { RawSaveItemList(FSTABLIST, VFSTAB[VSYSTEMHARDCLASS], NewLineMode_Unix); DeleteItemList(FSTABLIST); FSTABLIST = NULL; FSTAB_EDITS = 0; } } cfengine-3.6.2/cf-agent/verify_files.h0000644000175100017510000000237012316547775017362 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_FILES_H #define CFENGINE_VERIFY_FILES_H #include PromiseResult FindAndVerifyFilesPromises(EvalContext *ctx, const Promise *pp); PromiseResult ScheduleEditOperation(EvalContext *ctx, char *filename, Attributes attr, const Promise *pp); #endif cfengine-3.6.2/cf-agent/verify_exec.c0000664000175100017510000003373012411001073017151 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef enum { ACTION_RESULT_OK, ACTION_RESULT_TIMEOUT, ACTION_RESULT_FAILED } ActionResult; static bool SyntaxCheckExec(Attributes a, const Promise *pp); static bool PromiseKeptExec(Attributes a, const Promise *pp); static char *GetLockNameExec(Attributes a, const Promise *pp); static ActionResult RepairExec(EvalContext *ctx, Attributes a, const Promise *pp, PromiseResult *result); static void PreviewProtocolLine(char *line, char *comm); PromiseResult VerifyExecPromise(EvalContext *ctx, const Promise *pp) { Attributes a = GetExecAttributes(ctx, pp); if (!SyntaxCheckExec(a, pp)) { return PROMISE_RESULT_FAIL; } if (PromiseKeptExec(a, pp)) { return PROMISE_RESULT_NOOP; } char *lock_name = GetLockNameExec(a, pp); CfLock thislock = AcquireLock(ctx, lock_name, VUQNAME, CFSTARTTIME, a.transaction, pp, false); free(lock_name); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } PromiseBanner(pp); PromiseResult result = PROMISE_RESULT_NOOP; /* See VerifyCommandRetcode for interpretation of return codes. * Unless overridden by attributes in body classes, an exit code 0 means * reparied (PROMISE_RESULT_CHANGE), an exit code != 0 means failure. */ switch (RepairExec(ctx, a, pp, &result)) { case ACTION_RESULT_OK: result = PromiseResultUpdate(result, PROMISE_RESULT_NOOP); break; case ACTION_RESULT_TIMEOUT: result = PromiseResultUpdate(result, PROMISE_RESULT_TIMEOUT); break; case ACTION_RESULT_FAILED: result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); break; default: ProgrammingError("Unexpected ActionResult value"); } YieldCurrentLock(thislock); return result; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static bool SyntaxCheckExec(Attributes a, const Promise *pp) { if ((a.contain.nooutput) && (a.contain.preview)) { Log(LOG_LEVEL_ERR, "no_output and preview are mutually exclusive (broken promise)"); PromiseRef(LOG_LEVEL_ERR, pp); return false; } #ifdef __MINGW32__ if (a.contain.umask != (mode_t)CF_UNDEFINED) { Log(LOG_LEVEL_VERBOSE, "contain.umask is ignored on Windows"); } if (a.contain.owner != CF_UNDEFINED) { Log(LOG_LEVEL_VERBOSE, "contain.exec_owner is ignored on Windows"); } if (a.contain.group != CF_UNDEFINED) { Log(LOG_LEVEL_VERBOSE, "contain.exec_group is ignored on Windows"); } if (a.contain.chroot != NULL) { Log(LOG_LEVEL_VERBOSE, "contain.chroot is ignored on Windows"); } #else /* !__MINGW32__ */ if (a.contain.umask == (mode_t)CF_UNDEFINED) { a.contain.umask = 077; } #endif /* !__MINGW32__ */ return true; } static bool PromiseKeptExec(ARG_UNUSED Attributes a, ARG_UNUSED const Promise *pp) { return false; } static char *GetLockNameExec(Attributes a, const Promise *pp) { Writer *w = StringWriter(); if (a.args) { WriterWriteF(w, "%s %s", pp->promiser, a.args); } else { WriterWrite(w, pp->promiser); } return StringWriterClose(w); } /*****************************************************************************/ static ActionResult RepairExec(EvalContext *ctx, Attributes a, const Promise *pp, PromiseResult *result) { char eventname[CF_BUFSIZE]; char cmdline[CF_BUFSIZE]; char comm[20]; int outsourced, count = 0; #if !defined(__MINGW32__) mode_t maskval = 0; #endif FILE *pfp; char cmdOutBuf[CF_BUFSIZE]; int cmdOutBufPos = 0; int lineOutLen; char module_context[CF_BUFSIZE]; module_context[0] = '\0'; if (IsAbsoluteFileName(CommandArg0(pp->promiser)) || a.contain.shelltype == SHELL_TYPE_NONE) { if (!IsExecutable(CommandArg0(pp->promiser))) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "'%s' promises to be executable but isn't", pp->promiser); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); if (strchr(pp->promiser, ' ')) { Log(LOG_LEVEL_VERBOSE, "Paths with spaces must be inside escaped quoutes (e.g. \\\"%s\\\")", pp->promiser); } return ACTION_RESULT_FAILED; } else { Log(LOG_LEVEL_VERBOSE, "Promiser string contains a valid executable '%s' - ok", CommandArg0(pp->promiser)); } } char timeout_str[CF_BUFSIZE]; if (a.contain.timeout == CF_NOINT) { snprintf(timeout_str, CF_BUFSIZE, "no timeout"); } else { snprintf(timeout_str, CF_BUFSIZE, "timeout=%ds", a.contain.timeout); } char owner_str[CF_BUFSIZE] = ""; if (a.contain.owner != -1) { snprintf(owner_str, CF_BUFSIZE, ",uid=%ju", (uintmax_t)a.contain.owner); } char group_str[CF_BUFSIZE] = ""; if (a.contain.group != -1) { snprintf(group_str, CF_BUFSIZE, ",gid=%ju", (uintmax_t)a.contain.group); } snprintf(cmdline, CF_BUFSIZE, "%s%s%s", pp->promiser, a.args ? " " : "", a.args ? a.args : ""); Log(LOG_LEVEL_INFO, "Executing '%s%s%s' ... '%s'", timeout_str, owner_str, group_str, cmdline); BeginMeasure(); if (DONTDO && (!a.contain.preview)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Would execute script '%s'", cmdline); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return ACTION_RESULT_OK; } if (a.transaction.action != cfa_fix) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, a, "Command '%s' needs to be executed, but only warning was promised", cmdline); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return ACTION_RESULT_OK; } CommandPrefix(cmdline, comm); if (a.transaction.background) { #ifdef __MINGW32__ outsourced = true; #else Log(LOG_LEVEL_VERBOSE, "Backgrounding job '%s'", cmdline); outsourced = fork(); #endif } else { outsourced = false; } if (outsourced || (!a.transaction.background)) // work done here: either by child or non-background parent { if (a.contain.timeout != CF_NOINT) { SetTimeOut(a.contain.timeout); } #ifndef __MINGW32__ Log(LOG_LEVEL_VERBOSE, "(Setting umask to %jo)", (uintmax_t)a.contain.umask); maskval = umask(a.contain.umask); if (a.contain.umask == 0) { Log(LOG_LEVEL_VERBOSE, "Programming '%s' running with umask 0! Use umask= to set", cmdline); } #endif /* !__MINGW32__ */ const char *open_mode = a.module ? "rt" : "r"; if (a.contain.shelltype == SHELL_TYPE_POWERSHELL) { #ifdef __MINGW32__ pfp = cf_popen_powershell_setuid(cmdline, open_mode, a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot, a.transaction.background); #else // !__MINGW32__ Log(LOG_LEVEL_ERR, "Powershell is only supported on Windows"); return ACTION_RESULT_FAILED; #endif // !__MINGW32__ } else if (a.contain.shelltype == SHELL_TYPE_USE) { pfp = cf_popen_shsetuid(cmdline, open_mode, a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot, a.transaction.background); } else { pfp = cf_popensetuid(cmdline, open_mode, a.contain.owner, a.contain.group, a.contain.chdir, a.contain.chroot, a.transaction.background); } if (pfp == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", cmdline, GetErrorStr()); return ACTION_RESULT_FAILED; } StringSet *module_tags = StringSetNew(); size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pfp); if (res == -1) { if (!feof(pfp)) { Log(LOG_LEVEL_ERR, "Unable to read output from command '%s'. (fread: %s)", cmdline, GetErrorStr()); cf_pclose(pfp); free(line); return ACTION_RESULT_FAILED; } else { break; } } if (strstr(line, "cfengine-die")) { break; } if (a.contain.preview) { PreviewProtocolLine(line, cmdline); } if (a.module) { ModuleProtocol(ctx, cmdline, line, !a.contain.nooutput, module_context, module_tags); } else if ((!a.contain.nooutput) && (!EmptyString(line))) { lineOutLen = strlen(comm) + strlen(line) + 12; // if buffer is to small for this line, output it directly if (lineOutLen > sizeof(cmdOutBuf)) { Log(LOG_LEVEL_NOTICE, "Q: '%s': %s", comm, line); } else { if (cmdOutBufPos + lineOutLen > sizeof(cmdOutBuf)) { Log(LOG_LEVEL_NOTICE, "%s", cmdOutBuf); cmdOutBufPos = 0; } snprintf(cmdOutBuf + cmdOutBufPos, sizeof(cmdOutBuf) - cmdOutBufPos, "Q: \"...%s\": %s\n", comm, line); cmdOutBufPos += (lineOutLen - 1); } count++; } } StringSetDestroy(module_tags); free(line); #ifdef __MINGW32__ if (outsourced) // only get return value if we waited for command execution { cf_pclose(pfp); } else #endif /* __MINGW32__ */ { int ret = cf_pclose(pfp); if (ret == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Finished script '%s' - failed (abnormal termination)", pp->promiser); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } else { VerifyCommandRetcode(ctx, ret, a, pp, result); } } } if (count) { if (cmdOutBufPos) { Log(LOG_LEVEL_NOTICE, "%s", cmdOutBuf); } Log(LOG_LEVEL_INFO, "Last %d quoted lines were generated by promiser '%s'", count, cmdline); } if (a.contain.timeout != CF_NOINT) { alarm(0); signal(SIGALRM, SIG_DFL); } Log(LOG_LEVEL_INFO, "Completed execution of '%s'", cmdline); #ifndef __MINGW32__ umask(maskval); #endif snprintf(eventname, CF_BUFSIZE - 1, "Exec(%s)", cmdline); #ifndef __MINGW32__ if ((a.transaction.background) && outsourced) { Log(LOG_LEVEL_VERBOSE, "Backgrounded command '%s' is done - exiting", cmdline); exit(EXIT_SUCCESS); } #endif /* !__MINGW32__ */ return ACTION_RESULT_OK; } /*************************************************************/ /* Level */ /*************************************************************/ void PreviewProtocolLine(char *line, char *comm) { int i; char *message = line; /* * Table matching cfoutputlevel enums to log prefixes. */ char *prefixes[] = { ":silent:", ":inform:", ":verbose:", ":editverbose:", ":error:", ":logonly:", }; int precount = sizeof(prefixes) / sizeof(char *); if (line[0] == ':') { /* * Line begins with colon - see if it matches a log prefix. */ for (i = 0; i < precount; i++) { int prelen = 0; prelen = strlen(prefixes[i]); if (strncmp(line, prefixes[i], prelen) == 0) { /* * Found log prefix - set logging level, and remove the * prefix from the log message. */ message += prelen; break; } } } Log(LOG_LEVEL_VERBOSE, "'%s', preview of '%s'", message, comm); } cfengine-3.6.2/cf-agent/verify_environments.h0000644000175100017510000000231412316547775021005 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_ENVIRONMENTS_H #define CFENGINE_VERIFY_ENVIRONMENTS_H void NewEnvironmentsContext(void); void DeleteEnvironmentsContext(void); PromiseResult VerifyEnvironmentsPromise(EvalContext *ctx, const Promise *pp); #endif cfengine-3.6.2/cf-agent/files_repository.c0000644000175100017510000000742112352022221020240 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include /*********************************************************************/ static Item *VREPOSLIST = NULL; /* GLOBAL_X */ static char REPOSCHAR = '_'; /* GLOBAL_P */ static char *VREPOSITORY = NULL; /* GLOBAL_P */ /*********************************************************************/ void SetRepositoryLocation(const char *path) { VREPOSITORY = xstrdup(path); } /*********************************************************************/ void SetRepositoryChar(char c) { REPOSCHAR = c; } /*********************************************************************/ bool GetRepositoryPath(ARG_UNUSED const char *file, Attributes attr, char *destination) { if ((attr.repository == NULL) && (VREPOSITORY == NULL)) { return false; } size_t repopathlen; if (attr.repository != NULL) { repopathlen = strlcpy(destination, attr.repository, CF_BUFSIZE); } else { repopathlen = strlcpy(destination, VREPOSITORY, CF_BUFSIZE); } if (repopathlen >= CF_BUFSIZE) { Log(LOG_LEVEL_ERR, "Internal limit, buffer ran out of space for long filename"); return false; } return true; } /*********************************************************************/ int ArchiveToRepository(const char *file, Attributes attr) /* Returns true if the file was backup up and false if not */ { char destination[CF_BUFSIZE]; struct stat sb, dsb; if (!GetRepositoryPath(file, attr, destination)) { return false; } if (attr.copy.backup == BACKUP_OPTION_NO_BACKUP) { return true; } if (IsItemIn(VREPOSLIST, file)) { Log(LOG_LEVEL_INFO, "The file '%s' has already been moved to the repository once. Multiple update will cause loss of backup.", file); return true; } ThreadLock(cft_getaddr); PrependItemList(&VREPOSLIST, file); ThreadUnlock(cft_getaddr); JoinPath(destination, CanonifyName(file)); if (!MakeParentDirectory(destination, attr.move_obstructions)) { } if (stat(file, &sb) == -1) { Log(LOG_LEVEL_DEBUG, "File '%s' promised to archive to the repository but it disappeared!", file); return true; } stat(destination, &dsb); if (CopyRegularFileDisk(file, destination)) { Log(LOG_LEVEL_INFO, "Moved '%s' to repository location '%s'", file, destination); return true; } else { Log(LOG_LEVEL_INFO, "Failed to move '%s' to repository location '%s'", file, destination); return false; } } bool FileInRepository(const char *filename) { return IsItemIn(VREPOSLIST, filename); } cfengine-3.6.2/cf-agent/cf-agent-enterprise-stubs.c0000644000175100017510000000537712352566767021703 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, LastSawBundle, ARG_UNUSED const Bundle *, bundle, ARG_UNUSED double, comp) { } ENTERPRISE_FUNC_8ARG_DEFINE_STUB(PromiseResult, LogFileChange, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED const char *, file, ARG_UNUSED int, change, ARG_UNUSED Attributes, a, ARG_UNUSED const Promise *, pp, ARG_UNUSED CopyRegularFileFunction, CopyRegularFilePtr, ARG_UNUSED const char *, destination, ARG_UNUSED DeleteCompressedArrayFunction, DeleteCompressedArrayPtr) { Log(LOG_LEVEL_VERBOSE, "Logging file differences requires version Nova or above"); return PROMISE_RESULT_NOOP; } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, Nova_NoteVarUsageDB, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED const GenericAgentConfig *, config) { } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, Nova_NoteClassUsage, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED const GenericAgentConfig *, config) { } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, Nova_TrackExecution, ARG_UNUSED const char *, input_file) { } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, GenerateDiffReports, ARG_UNUSED const GenericAgentConfig *, config) { } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, Nova_NoteAgentExecutionPerformance, ARG_UNUSED const char *, input_file, ARG_UNUSED struct timespec, start) { } cfengine-3.6.2/cf-agent/verify_files_hashes.h0000644000175100017510000000314212352557236020704 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* AgentConnection */ #ifndef CFENGINE_VERIFY_FILES_HASHES_H #define CFENGINE_VERIFY_FILES_HASHES_H int FileHashChanged(EvalContext *ctx, const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1], HashMethod type, Attributes attr, const Promise *pp, PromiseResult *result); int CompareFileHashes(const char *file1, const char *file2, struct stat *sstat, struct stat *dstat, FileCopy fc, AgentConnection *conn); int CompareBinaryFiles(const char *file1, const char *file2, struct stat *sstat, struct stat *dstat, FileCopy fc, AgentConnection *conn); #endif cfengine-3.6.2/cf-agent/files_editline.h0000644000175100017510000000253212316547775017653 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILES_EDITLINE_H #define CFENGINE_FILES_EDITLINE_H #include #include int ScheduleEditLineOperations(EvalContext *ctx, const Bundle *bp, Attributes a, const Promise *pp, EditContext *edcontext); Bundle *MakeTemporaryBundleFromTemplate(EvalContext *ctx, Policy *policy, Attributes a, const Promise *pp, PromiseResult *result); #endif cfengine-3.6.2/cf-agent/verify_files_utils.c0000664000175100017510000034523412411001073020554 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CF_RECURSION_LIMIT 100 static const Rlist *AUTO_DEFINE_LIST = NULL; /* GLOBAL_P */ Item *VSETUIDLIST = NULL; /* GLOBAL_X */ const Rlist *SINGLE_COPY_LIST = NULL; /* GLOBAL_P */ static Rlist *SINGLE_COPY_CACHE = NULL; /* GLOBAL_X */ static bool TransformFile(EvalContext *ctx, char *file, Attributes attr, const Promise *pp, PromiseResult *result); static PromiseResult VerifyName(EvalContext *ctx, char *path, struct stat *sb, Attributes attr, const Promise *pp); static PromiseResult VerifyDelete(EvalContext *ctx, char *path, struct stat *sb, Attributes attr, const Promise *pp); static PromiseResult VerifyCopy(EvalContext *ctx, const char *source, char *destination, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn); static PromiseResult TouchFile(EvalContext *ctx, char *path, Attributes attr, const Promise *pp); static PromiseResult VerifyFileAttributes(EvalContext *ctx, const char *file, struct stat *dstat, Attributes attr, const Promise *pp); static int PushDirState(EvalContext *ctx, char *name, struct stat *sb); static bool PopDirState(int goback, char *name, struct stat *sb, DirectoryRecursion r); static bool CheckLinkSecurity(struct stat *sb, char *name); static int CompareForFileCopy(char *sourcefile, char *destfile, struct stat *ssb, struct stat *dsb, FileCopy fc, AgentConnection *conn); static void FileAutoDefine(EvalContext *ctx, char *destfile); static void TruncateFile(char *name); static void RegisterAHardLink(int i, char *value, Attributes attr, CompressedArray **inode_cache); static PromiseResult VerifyCopiedFileAttributes(EvalContext *ctx, const char *src, const char *dest, struct stat *sstat, struct stat *dstat, Attributes attr, const Promise *pp); static int cf_stat(const char *file, struct stat *buf, FileCopy fc, AgentConnection *conn); #ifndef __MINGW32__ static int cf_readlink(EvalContext *ctx, char *sourcefile, char *linkbuf, int buffsize, Attributes attr, const Promise *pp, AgentConnection *conn, PromiseResult *result); #endif static int SkipDirLinks(EvalContext *ctx, char *path, const char *lastnode, DirectoryRecursion r); static int DeviceBoundary(struct stat *sb, dev_t rootdevice); static PromiseResult LinkCopy(EvalContext *ctx, char *sourcefile, char *destfile, struct stat *sb, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn); #ifndef __MINGW32__ static PromiseResult VerifySetUidGid(EvalContext *ctx, const char *file, struct stat *dstat, mode_t newperm, const Promise *pp, Attributes attr); #endif #ifdef __APPLE__ static int VerifyFinderType(EvalContext *ctx, const char *file, Attributes a, const Promise *pp, PromiseResult *result); #endif static void VerifyFileChanges(const char *file, struct stat *sb, Attributes attr, const Promise *pp); static PromiseResult VerifyFileIntegrity(EvalContext *ctx, const char *file, Attributes attr, const Promise *pp); extern Attributes GetExpandedAttributes(EvalContext *ctx, const Promise *pp, const Attributes *attr); extern void ClearExpandedAttributes(Attributes *a); void SetFileAutoDefineList(const Rlist *auto_define_list) { AUTO_DEFINE_LIST = auto_define_list; } void VerifyFileLeaf(EvalContext *ctx, char *path, struct stat *sb, Attributes attr, const Promise *pp, PromiseResult *result) { /* Here we can assume that we are in the parent directory of the leaf */ Log(LOG_LEVEL_VERBOSE, "Handling file existence constraints on '%s'", path); /* Update this.promiser again, and overwrite common attributes (classes, action) accordingly */ EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "promiser", path, CF_DATA_TYPE_STRING, "source=promise"); // Parameters may only be scalars Attributes org_attr = GetFilesAttributes(ctx, pp); attr = GetExpandedAttributes(ctx, pp, &org_attr); if (attr.transformer != NULL) { if (!TransformFile(ctx, path, attr, pp, result)) { /* NOP? */ } } else { if (attr.haverename) { *result = PromiseResultUpdate(*result, VerifyName(ctx, path, sb, attr, pp)); } if (attr.havedelete) { *result = PromiseResultUpdate(*result, VerifyDelete(ctx, path, sb, attr, pp)); } if (attr.touch) { *result = PromiseResultUpdate(*result, TouchFile(ctx, path, attr, pp)); // intrinsically non-convergent op } } if (attr.haveperms || attr.havechange || attr.acl.acl_entries) { if (S_ISDIR(sb->st_mode) && attr.recursion.depth && !attr.recursion.include_basedir && (strcmp(path, pp->promiser) == 0)) { Log(LOG_LEVEL_VERBOSE, "Promise to skip base directory '%s'", path); } else { *result = PromiseResultUpdate(*result, VerifyFileAttributes(ctx, path, sb, attr, pp)); } } ClearExpandedAttributes(&attr); } /* Checks whether item matches a list of wildcards */ static int MatchRlistItem(EvalContext *ctx, const Rlist *listofregex, const char *teststring) { for (const Rlist *rp = listofregex; rp != NULL; rp = rp->next) { /* Avoid using regex if possible, due to memory leak */ if (strcmp(teststring, RlistScalarValue(rp)) == 0) { return (true); } /* Make it commutative */ if (FullTextMatch(ctx, RlistScalarValue(rp), teststring)) { return true; } } return false; } static PromiseResult CfCopyFile(EvalContext *ctx, char *sourcefile, char *destfile, struct stat ssb, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn) { char *server; const char *lastnode; struct stat dsb; int found; mode_t srcmode = ssb.st_mode; #ifdef __MINGW32__ if (attr.copy.copy_links != NULL) { Log(LOG_LEVEL_VERBOSE, "copy_from.copylink_patterns is ignored on Windows (source files cannot be symbolic links)"); } #endif /* __MINGW32__ */ attr.link.when_no_file = cfa_force; if (attr.copy.servers) { server = RlistScalarValue(attr.copy.servers); } else { server = NULL; } if ((strcmp(sourcefile, destfile) == 0) && server && (strcmp(server, "localhost") == 0)) { Log(LOG_LEVEL_INFO, "File copy promise loop: file/dir '%s' is its own source", sourcefile); return PROMISE_RESULT_NOOP; } if (attr.haveselect && !SelectLeaf(ctx, sourcefile, &ssb, attr.select)) { Log(LOG_LEVEL_DEBUG, "Skipping non-selected file '%s'", sourcefile); return PROMISE_RESULT_NOOP; } if (RlistIsInListOfRegex(SINGLE_COPY_CACHE, destfile)) { Log(LOG_LEVEL_INFO, "Skipping single-copied file '%s'", destfile); return PROMISE_RESULT_NOOP; } if (attr.copy.link_type != FILE_LINK_TYPE_NONE) { lastnode = ReadLastNode(sourcefile); if (MatchRlistItem(ctx, attr.copy.link_instead, lastnode)) { if (MatchRlistItem(ctx, attr.copy.copy_links, lastnode)) { Log(LOG_LEVEL_INFO, "File %s matches both copylink_patterns and linkcopy_patterns - promise loop (skipping)!", sourcefile); return PROMISE_RESULT_NOOP; } else { Log(LOG_LEVEL_VERBOSE, "Copy item '%s' marked for linking", sourcefile); #ifdef __MINGW32__ Log(LOG_LEVEL_VERBOSE, "Links are not yet supported on Windows - copying '%s' instead", sourcefile); #else return LinkCopy(ctx, sourcefile, destfile, &ssb, attr, pp, inode_cache, conn); #endif } } } found = lstat(destfile, &dsb); if (found != -1) { if (((S_ISLNK(dsb.st_mode)) && (attr.copy.link_type == FILE_LINK_TYPE_NONE)) || ((S_ISLNK(dsb.st_mode)) && (!S_ISLNK(ssb.st_mode)))) { if ((!S_ISLNK(ssb.st_mode)) && ((attr.copy.type_check) && (attr.copy.link_type != FILE_LINK_TYPE_NONE))) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "File image exists but destination type is silly (file/dir/link doesn't match)"); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; } if (DONTDO) { Log(LOG_LEVEL_VERBOSE, "Need to remove old symbolic link '%s' to make way for copy", destfile); } else { if (unlink(destfile) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't remove link '%s'. (unlink: %s)", destfile, GetErrorStr()); return PROMISE_RESULT_FAIL; } Log(LOG_LEVEL_VERBOSE, "Removing old symbolic link '%s' to make way for copy", destfile); found = -1; } } } else { MakeParentDirectory(destfile, true); } if (attr.copy.min_size != CF_NOINT) { if ((ssb.st_size < attr.copy.min_size) || (ssb.st_size > attr.copy.max_size)) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "Source file '%s' size is not in the permitted safety range", sourcefile); return PROMISE_RESULT_NOOP; } } PromiseResult result = PROMISE_RESULT_NOOP; if (found == -1) { if (attr.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Image file '%s' is non-existent and should be a copy of '%s'", destfile, sourcefile); return PromiseResultUpdate(result, PROMISE_RESULT_WARN); } if ((S_ISREG(srcmode)) || ((S_ISLNK(srcmode)) && (attr.copy.link_type == FILE_LINK_TYPE_NONE))) { if (DONTDO) { Log(LOG_LEVEL_VERBOSE, "'%s' wasn't at destination (needs copying)", destfile); return result; } else { Log(LOG_LEVEL_VERBOSE, "'%s' wasn't at destination (copying)", destfile); if (server) { Log(LOG_LEVEL_INFO, "Copying from '%s:%s'", server, sourcefile); } else { Log(LOG_LEVEL_INFO, "Copying from 'localhost:%s'", sourcefile); } } if ((S_ISLNK(srcmode)) && (attr.copy.link_type != FILE_LINK_TYPE_NONE)) { Log(LOG_LEVEL_VERBOSE, "'%s' is a symbolic link", sourcefile); result = PromiseResultUpdate(result, LinkCopy(ctx, sourcefile, destfile, &ssb, attr, pp, inode_cache, conn)); } else if (CopyRegularFile(ctx, sourcefile, destfile, ssb, dsb, attr, pp, inode_cache, conn, &result)) { if (stat(destfile, &dsb) == -1) { Log(LOG_LEVEL_ERR, "Can't stat destination file '%s'. (stat: %s)", destfile, GetErrorStr()); } else { result = PromiseResultUpdate(result, VerifyCopiedFileAttributes(ctx, sourcefile, destfile, &ssb, &dsb, attr, pp)); } if (server) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, attr, "Updated file from '%s:%s'", server, sourcefile); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, attr, "Updated file from 'localhost:%s'", sourcefile); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } if (SINGLE_COPY_LIST) { RlistPrependScalarIdemp(&SINGLE_COPY_CACHE, destfile); } if (MatchRlistItem(ctx, AUTO_DEFINE_LIST, destfile)) { FileAutoDefine(ctx, destfile); } } else { if (server) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Copy from '%s:%s' failed", server, sourcefile); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Copy from 'localhost:%s' failed", sourcefile); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } return result; } if (S_ISFIFO(srcmode)) { #ifdef HAVE_MKFIFO if (DONTDO) { Log(LOG_LEVEL_INFO, "Need to make FIFO '%s'", destfile); } else if (mkfifo(destfile, srcmode)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Cannot create fifo '%s'. (mkfifo: %s)", destfile, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Created fifo '%s'", destfile); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); #endif } else { #ifndef __MINGW32__ // only regular files on windows if (S_ISBLK(srcmode) || S_ISCHR(srcmode) || S_ISSOCK(srcmode)) { if (DONTDO) { Log(LOG_LEVEL_INFO, "Make BLK/CHR/SOCK '%s'", destfile); } else if (mknod(destfile, srcmode, ssb.st_rdev)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Cannot create special file '%s'. (mknod: %s)", destfile, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Created special file/device '%s'.", destfile); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } #endif /* !__MINGW32__ */ } if ((S_ISLNK(srcmode)) && (attr.copy.link_type != FILE_LINK_TYPE_NONE)) { result = PromiseResultUpdate(result, LinkCopy(ctx, sourcefile, destfile, &ssb, attr, pp, inode_cache, conn)); } } else { int ok_to_copy = false; Log(LOG_LEVEL_VERBOSE, "Destination file '%s' already exists", destfile); if (attr.copy.compare == FILE_COMPARATOR_EXISTS) { Log(LOG_LEVEL_VERBOSE, "Existence only is promised, no copying required"); return result; } if (!attr.copy.force_update) { ok_to_copy = CompareForFileCopy(sourcefile, destfile, &ssb, &dsb, attr.copy, conn); } else { ok_to_copy = true; } if ((attr.copy.type_check) && (attr.copy.link_type != FILE_LINK_TYPE_NONE)) { if (((S_ISDIR(dsb.st_mode)) && (!S_ISDIR(ssb.st_mode))) || ((S_ISREG(dsb.st_mode)) && (!S_ISREG(ssb.st_mode))) || ((S_ISBLK(dsb.st_mode)) && (!S_ISBLK(ssb.st_mode))) || ((S_ISCHR(dsb.st_mode)) && (!S_ISCHR(ssb.st_mode))) || ((S_ISSOCK(dsb.st_mode)) && (!S_ISSOCK(ssb.st_mode))) || ((S_ISFIFO(dsb.st_mode)) && (!S_ISFIFO(ssb.st_mode))) || ((S_ISLNK(dsb.st_mode)) && (!S_ISLNK(ssb.st_mode)))) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Promised file copy %s exists but type mismatch with source '%s'", destfile, sourcefile); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } } if (ok_to_copy && (attr.transaction.action == cfa_warn)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Image file '%s' exists but is not up to date wrt '%s' (only a warning has been promised)", destfile, sourcefile); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); return result; } if ((attr.copy.force_update) || ok_to_copy || (S_ISLNK(ssb.st_mode))) /* Always check links */ { if ((S_ISREG(srcmode)) || (attr.copy.link_type == FILE_LINK_TYPE_NONE)) { if (DONTDO) { Log(LOG_LEVEL_ERR, "Should update file '%s' from source '%s' on '%s'", destfile, sourcefile, server); return result; } if (MatchRlistItem(ctx, AUTO_DEFINE_LIST, destfile)) { FileAutoDefine(ctx, destfile); } if (CopyRegularFile(ctx, sourcefile, destfile, ssb, dsb, attr, pp, inode_cache, conn, &result)) { if (stat(destfile, &dsb) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Can't stat destination '%s'. (stat: %s)", destfile, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); } else { char *source_host = server ? server : "localhost"; cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Updated '%s' from source '%s' on '%s'", destfile, sourcefile, source_host); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); result = PromiseResultUpdate(result, VerifyCopiedFileAttributes(ctx, sourcefile, destfile, &ssb, &dsb, attr, pp)); } if (RlistIsInListOfRegex(SINGLE_COPY_LIST, destfile)) { RlistPrependScalarIdemp(&SINGLE_COPY_CACHE, destfile); } } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Was not able to copy '%s' to '%s'", sourcefile, destfile); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } return result; } if (S_ISLNK(ssb.st_mode)) { result = PromiseResultUpdate(result, LinkCopy(ctx, sourcefile, destfile, &ssb, attr, pp, inode_cache, conn)); } } else { result = PromiseResultUpdate(result, VerifyCopiedFileAttributes(ctx, sourcefile, destfile, &ssb, &dsb, attr, pp)); /* Now we have to check for single copy, even though nothing was copied otherwise we can get oscillations between multipe versions if type is based on a checksum */ if (RlistIsInListOfRegex(SINGLE_COPY_LIST, destfile)) { RlistPrependScalarIdemp(&SINGLE_COPY_CACHE, destfile); } cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "File '%s' is an up to date copy of source", destfile); } } return result; } static PromiseResult PurgeLocalFiles(EvalContext *ctx, Item *filelist, const char *localdir, Attributes attr, const Promise *pp, AgentConnection *conn) { Dir *dirh; struct stat sb; const struct dirent *dirp; char filename[CF_BUFSIZE] = { 0 }; if (strlen(localdir) < 2) { Log(LOG_LEVEL_ERR, "Purge of '%s' denied - too dangerous!", localdir); return PROMISE_RESULT_NOOP; } /* If we purge with no authentication we wipe out EVERYTHING ! */ if (conn && (!conn->authenticated)) { Log(LOG_LEVEL_VERBOSE, "Not purge local files '%s' - no authenticated contact with a source", localdir); return PROMISE_RESULT_NOOP; } if (!attr.havedepthsearch) { Log(LOG_LEVEL_VERBOSE, "No depth search when copying '%s' so purging does not apply", localdir); return PROMISE_RESULT_NOOP; } /* chdir to minimize the risk of race exploits during copy (which is inherently dangerous) */ if (safe_chdir(localdir) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't chdir to local directory '%s'. (chdir: %s)", localdir, GetErrorStr()); return PROMISE_RESULT_NOOP; } if ((dirh = DirOpen(".")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Can't open local directory '%s'. (opendir: %s)", localdir, GetErrorStr()); return PROMISE_RESULT_NOOP; } PromiseResult result = PROMISE_RESULT_NOOP; for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!ConsiderLocalFile(dirp->d_name, localdir)) { continue; } if (!IsItemIn(filelist, dirp->d_name)) { strncpy(filename, localdir, CF_BUFSIZE - 2); AddSlash(filename); if (strlcat(filename, dirp->d_name, CF_BUFSIZE) >= CF_BUFSIZE) { Log(LOG_LEVEL_ERR, "Path name is too long in PurgeLocalFiles"); } if (DONTDO || attr.transaction.action == cfa_warn) { Log(LOG_LEVEL_ERR, "Need to purge '%s' from copy dest directory", filename); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else { Log(LOG_LEVEL_INFO, "Purging '%s' in copy dest directory", filename); if (lstat(filename, &sb) == -1) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_INTERRUPTED, pp, attr, "Couldn't stat '%s' while purging. (lstat: %s)", filename, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); } else if (S_ISDIR(sb.st_mode)) { if (!DeleteDirectoryTree(filename)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to purge directory tree '%s'", filename); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else if (rmdir(filename) == -1) { if (errno != ENOENT) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to purge directory '%s'", filename); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } } else if (unlink(filename) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't delete '%s' while purging", filename); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } } } DirClose(dirh); return result; } static PromiseResult SourceSearchAndCopy(EvalContext *ctx, const char *from, char *to, int maxrecurse, Attributes attr, const Promise *pp, dev_t rootdevice, CompressedArray **inode_cache, AgentConnection *conn) { struct stat sb, dsb; /* TODO overflow check all these str*cpy()s in here! */ char newfrom[CF_BUFSIZE], newto[CF_BUFSIZE]; Item *namecache = NULL; const struct dirent *dirp; AbstractDir *dirh; if (maxrecurse == 0) /* reached depth limit */ { Log(LOG_LEVEL_DEBUG, "MAXRECURSE ran out, quitting at level '%s'", from); return PROMISE_RESULT_NOOP; } if (strlen(from) == 0) /* Check for root dir */ { from = "/"; } /* Check that dest dir exists before starting */ strlcpy(newto, to, sizeof(newto) - 10); AddSlash(newto); strcat(newto, "dummy"); if (attr.transaction.action != cfa_warn) { struct stat tostat; if (!MakeParentDirectory(newto, attr.move_obstructions)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to make directory for '%s' in file-copy '%s' to '%s'", newto, attr.copy.source, attr.copy.destination); return PROMISE_RESULT_FAIL; } DeleteSlash(to); /* Set aside symlinks */ if (lstat(to, &tostat) != 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Unable to stat newly created directory '%s'. (lstat: %s)", to, GetErrorStr()); return PROMISE_RESULT_WARN; } if (S_ISLNK(tostat.st_mode)) { char backup[CF_BUFSIZE]; mode_t mask; if (!attr.move_obstructions) { Log(LOG_LEVEL_INFO, "Path '%s' is a symlink. Unable to move it aside without move_obstructions is set", to); return PROMISE_RESULT_NOOP; } strcpy(backup, to); DeleteSlash(to); strcat(backup, ".cf-moved"); if (rename(to, backup) == -1) { Log(LOG_LEVEL_INFO, "Unable to backup old '%s'", to); unlink(to); } mask = umask(0); if (mkdir(to, DEFAULTMODE) == -1) { Log(LOG_LEVEL_ERR, "Unable to make directory '%s'. (mkdir: %s)", to, GetErrorStr()); umask(mask); return PROMISE_RESULT_NOOP; } umask(mask); } } if ((dirh = AbstractDirOpen(from, attr.copy, conn)) == NULL) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, attr, "copy can't open directory '%s'", from); return PROMISE_RESULT_INTERRUPTED; } PromiseResult result = PROMISE_RESULT_NOOP; for (dirp = AbstractDirRead(dirh); dirp != NULL; dirp = AbstractDirRead(dirh)) { if (!ConsiderAbstractFile(dirp->d_name, from, attr.copy, conn)) { continue; } if (attr.copy.purge) /* Purge this file */ { AppendItem(&namecache, dirp->d_name, NULL); } strlcpy(newfrom, from, sizeof(newfrom) - 2); /* Assemble pathname */ strlcpy(newto, to, sizeof(newto) - 2); if (!JoinPath(newfrom, dirp->d_name)) { AbstractDirClose(dirh); return result; } if ((attr.recursion.travlinks) || (attr.copy.link_type == FILE_LINK_TYPE_NONE)) { /* No point in checking if there are untrusted symlinks here, since this is from a trusted source, by defintion */ if (cf_stat(newfrom, &sb, attr.copy, conn) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't stat '%s'. (cf_stat: %s)", newfrom, GetErrorStr()); continue; } } else { if (cf_lstat(newfrom, &sb, attr.copy, conn) == -1) { Log(LOG_LEVEL_VERBOSE, "Can't stat '%s'. (cf_stat: %s)", newfrom, GetErrorStr()); continue; } } /* If we are tracking subdirs in copy, then join else don't add */ if (attr.copy.collapse) { if ((!S_ISDIR(sb.st_mode)) && (!JoinPath(newto, dirp->d_name))) { AbstractDirClose(dirh); return result; } } else { if (!JoinPath(newto, dirp->d_name)) { AbstractDirClose(dirh); return result; } } if ((attr.recursion.xdev) && (DeviceBoundary(&sb, rootdevice))) { Log(LOG_LEVEL_VERBOSE, "Skipping '%s' on different device", newfrom); continue; } if (S_ISDIR(sb.st_mode)) { if (attr.recursion.travlinks) { Log(LOG_LEVEL_VERBOSE, "Traversing directory links during copy is too dangerous, pruned"); continue; } if (SkipDirLinks(ctx, newfrom, dirp->d_name, attr.recursion)) { continue; } memset(&dsb, 0, sizeof(struct stat)); /* Only copy dirs if we are tracking subdirs */ if ((!attr.copy.collapse) && (stat(newto, &dsb) == -1)) { if (mkdir(newto, 0700) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Can't make directory '%s'. (mkdir: %s)", newto, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); continue; } if (stat(newto, &dsb) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Can't stat local copy '%s' - failed to establish directory. (stat: %s)", newto, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); continue; } } Log(LOG_LEVEL_VERBOSE, "Entering '%s'", newto); if (!attr.copy.collapse) { VerifyCopiedFileAttributes(ctx, newfrom, newto, &sb, &dsb, attr, pp); } result = PromiseResultUpdate(result, SourceSearchAndCopy(ctx, newfrom, newto, maxrecurse - 1, attr, pp, rootdevice, inode_cache, conn)); } else { result = PromiseResultUpdate(result, VerifyCopy(ctx, newfrom, newto, attr, pp, inode_cache, conn)); } } if (attr.copy.purge) { PurgeLocalFiles(ctx, namecache, to, attr, pp, conn); DeleteItemList(namecache); } AbstractDirClose(dirh); return result; } static PromiseResult VerifyCopy(EvalContext *ctx, const char *source, char *destination, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn) { AbstractDir *dirh; char sourcefile[CF_BUFSIZE]; char sourcedir[CF_BUFSIZE]; char destdir[CF_BUFSIZE]; char destfile[CF_BUFSIZE]; struct stat ssb, dsb; const struct dirent *dirp; int found; if (attr.copy.link_type == FILE_LINK_TYPE_NONE) { Log(LOG_LEVEL_DEBUG, "Treating links as files for '%s'", source); found = cf_stat(source, &ssb, attr.copy, conn); } else { found = cf_lstat(source, &ssb, attr.copy, conn); } if (found == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't stat '%s' in verify copy", source); return PROMISE_RESULT_FAIL; } if (ssb.st_nlink > 1) /* Preserve hard link structure when copying */ { RegisterAHardLink(ssb.st_ino, destination, attr, inode_cache); } if (S_ISDIR(ssb.st_mode)) { PromiseResult result = PROMISE_RESULT_NOOP; strcpy(sourcedir, source); AddSlash(sourcedir); strcpy(destdir, destination); AddSlash(destdir); if ((dirh = AbstractDirOpen(sourcedir, attr.copy, conn)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't open directory '%s'. (opendir: %s)", sourcedir, GetErrorStr()); return PROMISE_RESULT_FAIL; } /* Now check any overrides */ if (stat(destdir, &dsb) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't stat directory '%s'. (stat: %s)", destdir, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { result = PromiseResultUpdate(result, VerifyCopiedFileAttributes(ctx, sourcedir, destdir, &ssb, &dsb, attr, pp)); } for (dirp = AbstractDirRead(dirh); dirp != NULL; dirp = AbstractDirRead(dirh)) { if (!ConsiderAbstractFile(dirp->d_name, sourcedir, attr.copy, conn)) { continue; } strcpy(sourcefile, sourcedir); if (!JoinPath(sourcefile, dirp->d_name)) { FatalError(ctx, "VerifyCopy"); } strcpy(destfile, destdir); if (!JoinPath(destfile, dirp->d_name)) { FatalError(ctx, "VerifyCopy"); } if (attr.copy.link_type == FILE_LINK_TYPE_NONE) { if (cf_stat(sourcefile, &ssb, attr.copy, conn) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't stat source file (notlinked) '%s'. (stat: %s)", sourcefile, GetErrorStr()); return PROMISE_RESULT_FAIL; } } else { if (cf_lstat(sourcefile, &ssb, attr.copy, conn) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't stat source file '%s'. (lstat: %s)", sourcefile, GetErrorStr()); return PROMISE_RESULT_FAIL; } } result = PromiseResultUpdate(result, CfCopyFile(ctx, sourcefile, destfile, ssb, attr, pp, inode_cache, conn)); } AbstractDirClose(dirh); return result; } else { strcpy(sourcefile, source); strcpy(destfile, destination); return CfCopyFile(ctx, sourcefile, destfile, ssb, attr, pp, inode_cache, conn); } } static PromiseResult LinkCopy(EvalContext *ctx, char *sourcefile, char *destfile, struct stat *sb, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn) /* Link the file to the source, instead of copying */ #ifdef __MINGW32__ { Log(LOG_LEVEL_VERBOSE, "Windows does not support symbolic links"); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Windows can't link '%s' to '%s'", sourcefile, destfile); return PROMISE_RESULT_FAIL; } #else /* !__MINGW32__ */ { char linkbuf[CF_BUFSIZE]; const char *lastnode; struct stat dsb; PromiseResult result = PROMISE_RESULT_NOOP; linkbuf[0] = '\0'; if ((S_ISLNK(sb->st_mode)) && (cf_readlink(ctx, sourcefile, linkbuf, CF_BUFSIZE, attr, pp, conn, &result) == -1)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't readlink '%s'", sourcefile); return PROMISE_RESULT_FAIL; } else if (S_ISLNK(sb->st_mode)) { Log(LOG_LEVEL_VERBOSE, "Checking link from '%s' to '%s'", destfile, linkbuf); if ((attr.copy.link_type == FILE_LINK_TYPE_ABSOLUTE) && (!IsAbsoluteFileName(linkbuf))) /* Not absolute path - must fix */ { char vbuff[CF_BUFSIZE]; strlcpy(vbuff, sourcefile, CF_BUFSIZE); ChopLastNode(vbuff); AddSlash(vbuff); strncat(vbuff, linkbuf, CF_BUFSIZE - 1); strlcpy(linkbuf, vbuff, CF_BUFSIZE); } } else { strlcpy(linkbuf, sourcefile, CF_BUFSIZE); } lastnode = ReadLastNode(sourcefile); if (MatchRlistItem(ctx, attr.copy.copy_links, lastnode)) { struct stat ssb; ExpandLinks(linkbuf, sourcefile, 0); Log(LOG_LEVEL_VERBOSE, "Link item in copy '%s' marked for copying from '%s' instead", sourcefile, linkbuf); stat(linkbuf, &ssb); return CfCopyFile(ctx, linkbuf, destfile, ssb, attr, pp, inode_cache, conn); } int status; switch (attr.copy.link_type) { case FILE_LINK_TYPE_SYMLINK: if (*linkbuf == '.') { status = VerifyRelativeLink(ctx, destfile, linkbuf, attr, pp); } else { status = VerifyLink(ctx, destfile, linkbuf, attr, pp); } break; case FILE_LINK_TYPE_RELATIVE: status = VerifyRelativeLink(ctx, destfile, linkbuf, attr, pp); break; case FILE_LINK_TYPE_ABSOLUTE: status = VerifyAbsoluteLink(ctx, destfile, linkbuf, attr, pp); break; case FILE_LINK_TYPE_HARDLINK: status = VerifyHardLink(ctx, destfile, linkbuf, attr, pp); break; default: ProgrammingError("Unhandled link type in switch: %d", attr.copy.link_type); } if ((status == PROMISE_RESULT_CHANGE) || (status == PROMISE_RESULT_NOOP)) { if (lstat(destfile, &dsb) == -1) { Log(LOG_LEVEL_ERR, "Can't lstat '%s'. (lstat: %s)", destfile, GetErrorStr()); } else { result = PromiseResultUpdate(result, VerifyCopiedFileAttributes(ctx, sourcefile, destfile, sb, &dsb, attr, pp)); } if (status == PROMISE_RESULT_CHANGE) { cfPS(ctx, LOG_LEVEL_INFO, status, pp, attr, "Created link '%s'", destfile); result = PromiseResultUpdate(result, status); } else if (status == PROMISE_RESULT_NOOP) { cfPS(ctx, LOG_LEVEL_VERBOSE, status, pp, attr, "Link '%s' as promised", destfile); result = PromiseResultUpdate(result, status); } else // TODO: is this reachable? { cfPS(ctx, LOG_LEVEL_INFO, status, pp, attr, "Unable to create link '%s'", destfile); result = PromiseResultUpdate(result, status); } } return result; } #endif /* !__MINGW32__ */ bool CopyRegularFile(EvalContext *ctx, const char *source, const char *dest, struct stat sstat, struct stat dstat, Attributes attr, const Promise *pp, CompressedArray **inode_cache, AgentConnection *conn, PromiseResult *result) { char backup[CF_BUFSIZE]; char new[CF_BUFSIZE], *linkable; int remote = false, backupisdir = false, backupok = false, discardbackup; struct stat s; #ifdef HAVE_UTIME_H struct utimbuf timebuf; #endif #ifdef __APPLE__ /* For later copy from new to dest */ char *rsrcbuf; int rsrcbytesr; /* read */ int rsrcbytesw; /* written */ int rsrcbytesl; /* to read */ int rsrcrd; int rsrcwd; /* Keep track of if a resrouce fork */ int rsrcfork = 0; #endif discardbackup = ((attr.copy.backup == BACKUP_OPTION_NO_BACKUP) || (attr.copy.backup == BACKUP_OPTION_REPOSITORY_STORE)); if (DONTDO) { Log(LOG_LEVEL_ERR, "Promise requires copy from '%s' to '%s'", source, dest); return false; } /* Make an assoc array of inodes used to preserve hard links */ linkable = CompressedArrayValue(*inode_cache, sstat.st_ino); if (sstat.st_nlink > 1) /* Preserve hard links, if possible */ { if ((CompressedArrayElementExists(*inode_cache, sstat.st_ino)) && (strcmp(dest, linkable) != 0)) { unlink(dest); MakeHardLink(ctx, dest, linkable, attr, pp, result); return true; } } if (conn != NULL) { assert(attr.copy.servers && strcmp(RlistScalarValue(attr.copy.servers), "localhost")); Log(LOG_LEVEL_DEBUG, "This is a remote copy from server '%s'", RlistScalarValue(attr.copy.servers)); remote = true; } #ifdef __APPLE__ if (strstr(dest, _PATH_RSRCFORKSPEC)) { char *tmpstr = xstrndup(dest, CF_BUFSIZE); rsrcfork = 1; /* Drop _PATH_RSRCFORKSPEC */ char *forkpointer = strstr(tmpstr, _PATH_RSRCFORKSPEC); *forkpointer = '\0'; strlcpy(new, tmpstr, CF_BUFSIZE); free(tmpstr); } else { #endif strlcpy(new, dest, CF_BUFSIZE); if (!JoinSuffix(new, CF_NEW)) { Log(LOG_LEVEL_ERR, "Unable to construct filename for copy"); return false; } #ifdef __APPLE__ } #endif if (remote) { if (conn->error) { return false; } if (!CopyRegularFileNet(source, new, sstat.st_size, attr.copy.encrypt, conn)) { return false; } } else { if (!CopyRegularFileDisk(source, new)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Failed copying file '%s' to '%s'", source, new); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } if (attr.copy.stealth) { #ifdef HAVE_UTIME_H timebuf.actime = sstat.st_atime; timebuf.modtime = sstat.st_mtime; utime(source, &timebuf); #endif } } Log(LOG_LEVEL_VERBOSE, "Copy of regular file succeeded '%s' to '%s'", source, new); backup[0] = '\0'; if (!discardbackup) { char stamp[CF_BUFSIZE]; time_t stampnow; Log(LOG_LEVEL_DEBUG, "Backup file '%s'", source); strlcpy(backup, dest, CF_BUFSIZE); if (attr.copy.backup == BACKUP_OPTION_TIMESTAMP) { stampnow = time((time_t *) NULL); snprintf(stamp, CF_BUFSIZE - 1, "_%lu_%s", CFSTARTTIME, CanonifyName(ctime(&stampnow))); if (!JoinSuffix(backup, stamp)) { return false; } } if (!JoinSuffix(backup, CF_SAVED)) { return false; } /* Now in case of multiple copies of same object, try to avoid overwriting original backup */ if (lstat(backup, &s) != -1) { if (S_ISDIR(s.st_mode)) /* if there is a dir in the way */ { backupisdir = true; PurgeLocalFiles(ctx, NULL, backup, attr, pp, conn); rmdir(backup); } unlink(backup); } if (rename(dest, backup) == -1) { /* ignore */ } backupok = (lstat(backup, &s) != -1); /* Did the rename() succeed? NFS-safe */ } else { /* Mainly important if there is a dir in the way */ if (stat(dest, &s) != -1) { if (S_ISDIR(s.st_mode)) { PurgeLocalFiles(ctx, NULL, dest, attr, pp, conn); rmdir(dest); } } } if (lstat(new, &dstat) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't stat new file '%s' - another agent has picked it up?. (stat: %s)", new, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } if ((S_ISREG(dstat.st_mode)) && (dstat.st_size != sstat.st_size)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "New file '%s' seems to have been corrupted in transit, destination %d and source %d, aborting.", new, (int) dstat.st_size, (int) sstat.st_size); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); if (backupok) { rename(backup, dest); /* ignore failure of this call, as there is nothing more we can do */ } return false; } if (attr.copy.verify) { Log(LOG_LEVEL_VERBOSE, "Final verification of transmission ..."); if (CompareFileHashes(source, new, &sstat, &dstat, attr.copy, conn)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "New file '%s' seems to have been corrupted in transit, aborting.", new); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); if (backupok) { rename(backup, dest); } return false; } else { Log(LOG_LEVEL_VERBOSE, "New file '%s' transmitted correctly - verified", new); } } #ifdef __APPLE__ if (rsrcfork) { /* Can't just "mv" the resource fork, unfortunately */ rsrcrd = safe_open(new, O_RDONLY | O_BINARY); rsrcwd = safe_open(dest, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0600); if (rsrcrd == -1 || rsrcwd == -1) { Log(LOG_LEVEL_INFO, "Open of Darwin resource fork rsrcrd/rsrcwd failed. (open: %s)", GetErrorStr()); close(rsrcrd); close(rsrcwd); return (false); } rsrcbuf = xmalloc(CF_BUFSIZE); rsrcbytesr = 0; while (1) { rsrcbytesr = read(rsrcrd, rsrcbuf, CF_BUFSIZE); if (rsrcbytesr == -1) { /* Ck error */ if (errno == EINTR) { continue; } else { Log(LOG_LEVEL_INFO, "Read of Darwin resource fork rsrcrd failed. (read: %s)", GetErrorStr()); close(rsrcrd); close(rsrcwd); free(rsrcbuf); return (false); } } else if (rsrcbytesr == 0) { /* Reached EOF */ close(rsrcrd); close(rsrcwd); free(rsrcbuf); unlink(new); /* Go ahead and unlink .cfnew */ break; } rsrcbytesl = rsrcbytesr; rsrcbytesw = 0; while (rsrcbytesl > 0) { rsrcbytesw += write(rsrcwd, rsrcbuf, rsrcbytesl); if (rsrcbytesw == -1) { if (errno == EINTR) { continue; } else { Log(LOG_LEVEL_INFO, "Write of Darwin resource fork rsrcwd failed."); close(rsrcrd); close(rsrcwd); free(rsrcbuf); return (false); } } rsrcbytesl = rsrcbytesr - rsrcbytesw; } } } else { #endif if (rename(new, dest) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Could not install copy file as '%s', directory in the way?. (rename: %s)", dest, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); if (backupok) { rename(backup, dest); /* ignore failure */ } return false; } #ifdef __APPLE__ } #endif if ((!discardbackup) && backupisdir) { Log(LOG_LEVEL_INFO, "Cannot move a directory to repository, leaving at '%s'", backup); } else if ((!discardbackup) && (ArchiveToRepository(backup, attr))) { unlink(backup); } if (attr.copy.stealth) { #ifdef HAVE_UTIME_H timebuf.actime = sstat.st_atime; timebuf.modtime = sstat.st_mtime; utime(dest, &timebuf); #endif } return true; } static bool TransformFile(EvalContext *ctx, char *file, Attributes attr, const Promise *pp, PromiseResult *result) { FILE *pop = NULL; int transRetcode = 0; if (attr.transformer == NULL || file == NULL) { return false; } Buffer *command = BufferNew(); ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, attr.transformer, command); Log(LOG_LEVEL_INFO, "Transforming '%s' ", BufferData(command)); if (!IsExecutable(CommandArg0(BufferData(command)))) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Transformer '%s' for file '%s' failed", attr.transformer, file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(command); return false; } if (!DONTDO) { CfLock thislock = AcquireLock(ctx, BufferData(command), VUQNAME, CFSTARTTIME, attr.transaction, pp, false); if (thislock.lock == NULL) { BufferDestroy(command); return false; } if ((pop = cf_popen(BufferData(command), "r", true)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Transformer '%s' for file '%s' failed", attr.transformer, file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); YieldCurrentLock(thislock); BufferDestroy(command); return false; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pop); if (res == -1) { if (!feof(pop)) { cf_pclose(pop); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Transformer '%s' for file '%s' failed", attr.transformer, file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); YieldCurrentLock(thislock); free(line); BufferDestroy(command); return false; } else { break; } } Log(LOG_LEVEL_INFO, "%s", line); } free(line); transRetcode = cf_pclose(pop); if (VerifyCommandRetcode(ctx, transRetcode, attr, pp, result)) { Log(LOG_LEVEL_INFO, "Transformer '%s' => '%s' seemed to work ok", file, BufferData(command)); } else { Log(LOG_LEVEL_ERR, "Transformer '%s' => '%s' returned error", file, BufferData(command)); } YieldCurrentLock(thislock); } else { Log(LOG_LEVEL_ERR, "Need to transform file '%s' with '%s'", file, BufferData(command)); } BufferDestroy(command); return true; } static PromiseResult VerifyName(EvalContext *ctx, char *path, struct stat *sb, Attributes attr, const Promise *pp) { mode_t newperm; struct stat dsb; if (lstat(path, &dsb) == -1) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, attr, "File object named '%s' is not there (promise kept)", path); return PROMISE_RESULT_NOOP; } else { if (attr.rename.disable) { Log(LOG_LEVEL_WARNING, "File object '%s' exists, contrary to promise", path); } } PromiseResult result = PROMISE_RESULT_NOOP; if (attr.rename.newname) { if (DONTDO) { Log(LOG_LEVEL_INFO, "File '%s' should be renamed to '%s' to keep promise", path, attr.rename.newname); return PROMISE_RESULT_NOOP; } else { if (!FileInRepository(attr.rename.newname)) { if (rename(path, attr.rename.newname) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Error occurred while renaming '%s'. (rename: %s)", path, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Renaming file '%s' to '%s'", path, attr.rename.newname); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Rename to same destination twice? Would overwrite saved copy - aborting"); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } } return result; } if (S_ISLNK(dsb.st_mode)) { if (attr.rename.disable) { if (!DONTDO) { if (unlink(path) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to unlink '%s'. (unlink: %s)", path, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Disabling symbolic link '%s' by deleting it", path); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } } else { Log(LOG_LEVEL_INFO, "Need to disable link '%s' to keep promise", path); } return result; } } /* Normal disable - has priority */ if (attr.rename.disable) { char newname[CF_BUFSIZE]; if (attr.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "'%s' '%s' should be renamed", S_ISDIR(sb->st_mode) ? "Directory" : "File", path); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); return result; } if (attr.rename.newname && strlen(attr.rename.newname) > 0) { if (IsAbsPath(attr.rename.newname)) { strlcpy(path, attr.rename.newname, CF_BUFSIZE); } else { strcpy(newname, path); ChopLastNode(newname); if (!JoinPath(newname, attr.rename.newname)) { return result; } } } else { strcpy(newname, path); if (attr.rename.disable_suffix) { if (!JoinSuffix(newname, attr.rename.disable_suffix)) { return result; } } else { if (!JoinSuffix(newname, ".cfdisabled")) { return result; } } } if ((attr.rename.plus != CF_SAMEMODE) && (attr.rename.minus != CF_SAMEMODE)) { newperm = (sb->st_mode & 07777); newperm |= attr.rename.plus; newperm &= ~(attr.rename.minus); } else { newperm = (mode_t) 0600; } if (DONTDO) { Log(LOG_LEVEL_INFO, "File '%s' should be renamed to '%s' to keep promise", path, newname); return result; } else { safe_chmod(path, newperm); if (!FileInRepository(newname)) { if (rename(path, newname) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Error occurred while renaming '%s'. (rename: %s)", path, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Disabling/renaming file '%s' to '%s' with mode %04jo", path, newname, (uintmax_t)newperm); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } if (ArchiveToRepository(newname, attr)) { unlink(newname); } } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Disable required twice? Would overwrite saved copy - changing permissions only"); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } } return result; } if (attr.rename.rotate == 0) { if (attr.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "File '%s' should be truncated", path); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else if (!DONTDO) { TruncateFile(path); cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Truncating (emptying) '%s'", path); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { Log(LOG_LEVEL_ERR, " * File '%s' needs emptying", path); } return result; } if (attr.rename.rotate > 0) { if (attr.transaction.action == cfa_warn) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "File '%s' should be rotated", path); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } else if (!DONTDO) { RotateFiles(path, attr.rename.rotate); cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Rotating files '%s' in %d fifo", path, attr.rename.rotate); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { Log(LOG_LEVEL_ERR, "File '%s' needs rotating", path); } return result; } return result; } static PromiseResult VerifyDelete(EvalContext *ctx, char *path, struct stat *sb, Attributes attr, const Promise *pp) { const char *lastnode = ReadLastNode(path); char buf[CF_MAXVARSIZE]; Log(LOG_LEVEL_VERBOSE, "Verifying file deletions for '%s'", path); PromiseResult result = PROMISE_RESULT_NOOP; if (DONTDO) { Log(LOG_LEVEL_INFO, "Promise requires deletion of file object '%s'", path); } else { switch (attr.transaction.action) { case cfa_warn: cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "'%s' '%s' should be deleted", S_ISDIR(sb->st_mode) ? "Directory" : "File", path); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); break; case cfa_fix: if (!S_ISDIR(sb->st_mode)) { if (unlink(lastnode) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't unlink '%s' tidying. (unlink: %s)", path, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Deleted file '%s'", path); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } } else // directory { if (!attr.delete.rmdirs) { Log(LOG_LEVEL_INFO, "Keeping directory '%s'. (unlink: %s)", path, GetErrorStr()); return result; } if (attr.havedepthsearch && strcmp(path, pp->promiser) == 0) { /* This is the parent and we cannot delete it from here - must delete separately */ return result; } // use the full path if we are to delete the current dir if ((strcmp(lastnode, ".") == 0) && strlen(path) > 2) { snprintf(buf, sizeof(buf), "%s", path); buf[strlen(path) - 1] = '\0'; buf[strlen(path) - 2] = '\0'; } else { snprintf(buf, sizeof(buf), "%s", lastnode); } if (rmdir(buf) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Delete directory '%s' failed (cannot delete node called '%s'). (rmdir: %s)", path, buf, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Deleted directory '%s'", path); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } } break; default: ProgrammingError("Unhandled file action in switch: %d", attr.transaction.action); } } return result; } static PromiseResult TouchFile(EvalContext *ctx, char *path, Attributes attr, const Promise *pp) { PromiseResult result = PROMISE_RESULT_NOOP; if (!DONTDO) { if (utime(path, NULL) != -1) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Touched (updated time stamps) for path '%s'", path); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Touch '%s' failed to update timestamps. (utime: %s)", path, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } else { Log(LOG_LEVEL_ERR, "Need to touch (update timestamps) path '%s'", path); } return result; } PromiseResult VerifyFileAttributes(EvalContext *ctx, const char *file, struct stat *dstat, Attributes attr, const Promise *pp) { PromiseResult result = PROMISE_RESULT_NOOP; #ifndef __MINGW32__ mode_t newperm = dstat->st_mode, maskvalue; # if defined HAVE_CHFLAGS u_long newflags; # endif maskvalue = umask(0); /* This makes the DEFAULT modes absolute */ newperm = (dstat->st_mode & 07777); if ((attr.perms.plus != CF_SAMEMODE) && (attr.perms.minus != CF_SAMEMODE)) { newperm |= attr.perms.plus; newperm &= ~(attr.perms.minus); /* directories must have x set if r set, regardless */ if (S_ISDIR(dstat->st_mode)) { if (attr.perms.rxdirs) { Log(LOG_LEVEL_DEBUG, "Directory...fixing x bits"); if (newperm & S_IRUSR) { newperm |= S_IXUSR; } if (newperm & S_IRGRP) { newperm |= S_IXGRP; } if (newperm & S_IROTH) { newperm |= S_IXOTH; } } else { Log(LOG_LEVEL_VERBOSE, "NB: rxdirs is set to false - x for r bits not checked"); } } } result = PromiseResultUpdate(result, VerifySetUidGid(ctx, file, dstat, newperm, pp, attr)); # ifdef __APPLE__ if (VerifyFinderType(ctx, file, attr, pp, &result)) { /* nop */ } # endif #endif if (VerifyOwner(ctx, file, pp, attr, dstat, &result)) { /* nop */ } #ifdef __MINGW32__ if (NovaWin_FileExists(file) && !NovaWin_IsDir(file)) #else if (attr.havechange && S_ISREG(dstat->st_mode)) #endif { result = PromiseResultUpdate(result, VerifyFileIntegrity(ctx, file, attr, pp)); } if (attr.havechange) { VerifyFileChanges(file, dstat, attr, pp); } #ifndef __MINGW32__ if (S_ISLNK(dstat->st_mode)) /* No point in checking permission on a link */ { KillGhostLink(ctx, file, attr, pp, &result); umask(maskvalue); return result; } #endif if (attr.acl.acl_entries) { result = PromiseResultUpdate(result, VerifyACL(ctx, file, attr, pp)); } #ifndef __MINGW32__ result = PromiseResultUpdate(result, VerifySetUidGid(ctx, file, dstat, dstat->st_mode, pp, attr)); if ((newperm & 07777) == (dstat->st_mode & 07777)) /* file okay */ { Log(LOG_LEVEL_DEBUG, "File okay, newperm '%jo', stat '%jo'", (uintmax_t) (newperm & 07777), (uintmax_t) (dstat->st_mode & 07777)); cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, attr, "File permissions on '%s' as promised", file); result = PromiseResultUpdate(result, PROMISE_RESULT_NOOP); } else { Log(LOG_LEVEL_DEBUG, "Trying to fix mode...newperm '%jo', stat '%jo'", (uintmax_t) (newperm & 07777), (uintmax_t) (dstat->st_mode & 07777)); switch (attr.transaction.action) { case cfa_warn: cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "'%s' has permission %04jo - [should be %04jo]", file, (uintmax_t)dstat->st_mode & 07777, (uintmax_t)newperm & 07777); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); break; case cfa_fix: if (!DONTDO) { if (safe_chmod(file, newperm & 07777) == -1) { Log(LOG_LEVEL_ERR, "chmod failed on '%s'. (chmod: %s)", file, GetErrorStr()); break; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Object '%s' had permission %04jo, changed it to %04jo", file, (uintmax_t)dstat->st_mode & 07777, (uintmax_t)newperm & 07777); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; default: ProgrammingError("Unhandled file action in switch: %d", attr.transaction.action); } } # if defined HAVE_CHFLAGS /* BSD special flags */ newflags = (dstat->st_flags & CHFLAGS_MASK); newflags |= attr.perms.plus_flags; newflags &= ~(attr.perms.minus_flags); if ((newflags & CHFLAGS_MASK) == (dstat->st_flags & CHFLAGS_MASK)) /* file okay */ { Log(LOG_LEVEL_DEBUG, "BSD File okay, flags '%jx', current '%jx'", (uintmax_t) (newflags & CHFLAGS_MASK), (uintmax_t) (dstat->st_flags & CHFLAGS_MASK)); } else { Log(LOG_LEVEL_DEBUG, "BSD Fixing '%s', newflags '%jx', flags '%jx'", file, (uintmax_t) (newflags & CHFLAGS_MASK), (uintmax_t) (dstat->st_flags & CHFLAGS_MASK)); switch (attr.transaction.action) { case cfa_warn: cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "'%s' has flags %jo - [should be %jo]", file, (uintmax_t) (dstat->st_mode & CHFLAGS_MASK), (uintmax_t) (newflags & CHFLAGS_MASK)); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); break; case cfa_fix: if (!DONTDO) { if (chflags(file, newflags & CHFLAGS_MASK) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_DENIED, pp, attr, "Failed setting BSD flags '%jx' on '%s'. (chflags: %s)", (uintmax_t) newflags, file, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_DENIED); break; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "'%s' had flags %jo, changed it to %jo", file, (uintmax_t) (dstat->st_flags & CHFLAGS_MASK), (uintmax_t) (newflags & CHFLAGS_MASK)); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } } break; default: ProgrammingError("Unhandled file action in switch: %d", attr.transaction.action); } } # endif #endif if (attr.touch) { if (utime(file, NULL) == -1) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_DENIED, pp, attr, "Touching file '%s' failed. (utime: %s)", file, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_DENIED); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Touching file '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } } #ifndef __MINGW32__ umask(maskvalue); #endif return result; } int DepthSearch(EvalContext *ctx, char *name, struct stat *sb, int rlevel, Attributes attr, const Promise *pp, dev_t rootdevice, PromiseResult *result) { Dir *dirh; int goback; const struct dirent *dirp; char path[CF_BUFSIZE]; struct stat lsb; Seq *db_file_set = NULL; Seq *selected_files = NULL; if (!attr.havedepthsearch) /* if the search is trivial, make sure that we are in the parent dir of the leaf */ { char basedir[CF_BUFSIZE]; Log(LOG_LEVEL_DEBUG, "Direct file reference '%s', no search implied", name); snprintf(basedir, sizeof(basedir), "%s", name); ChopLastNode(basedir); if (safe_chdir(basedir)) { Log(LOG_LEVEL_ERR, "Failed to chdir into '%s'. (chdir: '%s')", basedir, GetErrorStr()); return false; } if (!attr.haveselect || SelectLeaf(ctx, path, sb, attr.select)) { VerifyFileLeaf(ctx, name, sb, attr, pp, result); return true; } else { return false; } } if (rlevel > CF_RECURSION_LIMIT) { Log(LOG_LEVEL_WARNING, "Very deep nesting of directories (>%d deep) for '%s' (Aborting files)", rlevel, name); return false; } memset(path, 0, CF_BUFSIZE); if (!PushDirState(ctx, name, sb)) { return false; } if ((dirh = DirOpen(".")) == NULL) { Log(LOG_LEVEL_INFO, "Could not open existing directory '%s'. (opendir: %s)", name, GetErrorStr()); return false; } if (attr.havechange) { db_file_set = SeqNew(1, &free); if (!FileChangesGetDirectoryList(name, db_file_set)) { SeqDestroy(db_file_set); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } selected_files = SeqNew(1, &free); } for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!ConsiderLocalFile(dirp->d_name, name)) { continue; } strcpy(path, name); AddSlash(path); if (!JoinPath(path, dirp->d_name)) { goto end; } if (lstat(dirp->d_name, &lsb) == -1) { Log(LOG_LEVEL_VERBOSE, "Recurse was looking at '%s' when an error occurred. (lstat: %s)", path, GetErrorStr()); continue; } if (S_ISLNK(lsb.st_mode)) /* should we ignore links? */ { if (KillGhostLink(ctx, path, attr, pp, result)) { continue; } } /* See if we are supposed to treat links to dirs as dirs and descend */ if ((attr.recursion.travlinks) && (S_ISLNK(lsb.st_mode))) { if ((lsb.st_uid != 0) && (lsb.st_uid != getuid())) { Log(LOG_LEVEL_INFO, "File '%s' is an untrusted link: cfengine will not follow it with a destructive operation", path); continue; } /* if so, hide the difference by replacing with actual object */ if (stat(dirp->d_name, &lsb) == -1) { Log(LOG_LEVEL_ERR, "Recurse was working on '%s' when this failed. (stat: %s)", path, GetErrorStr()); continue; } } if ((attr.recursion.xdev) && (DeviceBoundary(&lsb, rootdevice))) { Log(LOG_LEVEL_VERBOSE, "Skipping '%s' on different device - use xdev option to change this. (stat: %s)", path, GetErrorStr()); continue; } if (S_ISDIR(lsb.st_mode)) { if (SkipDirLinks(ctx, path, dirp->d_name, attr.recursion)) { continue; } if ((attr.recursion.depth > 1) && (rlevel <= attr.recursion.depth)) { Log(LOG_LEVEL_VERBOSE, "Entering '%s', level %d", path, rlevel); goback = DepthSearch(ctx, path, &lsb, rlevel + 1, attr, pp, rootdevice, result); if (!PopDirState(goback, name, sb, attr.recursion)) { FatalError(ctx, "Not safe to continue"); } } } if (!attr.haveselect || SelectLeaf(ctx, path, &lsb, attr.select)) { if (attr.havechange) { if (!SeqBinaryLookup(db_file_set, dirp->d_name, (SeqItemComparator)strcmp)) { // See comments in FileChangesCheckAndUpdateDirectory(), // regarding this function call. FileChangesLogNewFile(path, pp); } SeqAppend(selected_files, xstrdup(dirp->d_name)); } VerifyFileLeaf(ctx, path, &lsb, attr, pp, result); } else { Log(LOG_LEVEL_DEBUG, "Skipping non-selected file '%s'", path); } } if (attr.havechange) { FileChangesCheckAndUpdateDirectory(name, selected_files, db_file_set, attr.change.update, pp, result); } end: SeqDestroy(selected_files); SeqDestroy(db_file_set); DirClose(dirh); return true; } static int PushDirState(EvalContext *ctx, char *name, struct stat *sb) { if (safe_chdir(name) == -1) { Log(LOG_LEVEL_INFO, "Could not change to directory '%s', mode '%04jo' in tidy. (chdir: %s)", name, (uintmax_t)(sb->st_mode & 07777), GetErrorStr()); return false; } if (!CheckLinkSecurity(sb, name)) { FatalError(ctx, "Not safe to continue"); } return true; } /** * @return true if safe for agent to continue */ static bool PopDirState(int goback, char *name, struct stat *sb, DirectoryRecursion r) { if (goback && (r.travlinks)) { if (safe_chdir(name) == -1) { Log(LOG_LEVEL_ERR, "Error in backing out of recursive travlink descent securely to '%s'. (chdir: %s)", name, GetErrorStr()); return false; } if (!CheckLinkSecurity(sb, name)) { return false; } } else if (goback) { if (safe_chdir("..") == -1) { Log(LOG_LEVEL_ERR, "Error in backing out of recursive descent securely to '%s'. (chdir: %s)", name, GetErrorStr()); return false; } } return true; } /** * @return true if it is safe for the agent to continue execution */ static bool CheckLinkSecurity(struct stat *sb, char *name) { struct stat security; Log(LOG_LEVEL_DEBUG, "Checking the inode and device to make sure we are where we think we are..."); if (stat(".", &security) == -1) { Log(LOG_LEVEL_ERR, "Could not stat directory '%s' after entering. (stat: %s)", name, GetErrorStr()); return true; // continue anyway } if ((sb->st_dev != security.st_dev) || (sb->st_ino != security.st_ino)) { Log(LOG_LEVEL_ERR, "SERIOUS SECURITY ALERT: path race exploited in recursion to/from '%s'. Not safe for agent to continue - aborting", name); return false; // too dangerous } return true; } static PromiseResult VerifyCopiedFileAttributes(EvalContext *ctx, const char *src, const char *dest, struct stat *sstat, struct stat *dstat, Attributes attr, const Promise *pp) { #ifndef __MINGW32__ mode_t newplus, newminus; uid_t save_uid; gid_t save_gid; // If we get here, there is both a src and dest file save_uid = (attr.perms.owners)->uid; save_gid = (attr.perms.groups)->gid; if (attr.copy.preserve) { Log(LOG_LEVEL_VERBOSE, "Attempting to preserve file permissions from the source: %04jo", (uintmax_t)(sstat->st_mode & 07777)); if ((attr.perms.owners)->uid == CF_SAME_OWNER) /* Preserve uid and gid */ { (attr.perms.owners)->uid = sstat->st_uid; } if ((attr.perms.groups)->gid == CF_SAME_GROUP) { (attr.perms.groups)->gid = sstat->st_gid; } // Will this preserve if no mode set? newplus = (sstat->st_mode & 07777); newminus = ~newplus & 07777; attr.perms.plus = newplus; attr.perms.minus = newminus; } else { if ((attr.perms.owners)->uid == CF_SAME_OWNER) /* Preserve uid and gid */ { (attr.perms.owners)->uid = dstat->st_uid; } if ((attr.perms.groups)->gid == CF_SAME_GROUP) { (attr.perms.groups)->gid = dstat->st_gid; } if (attr.haveperms) { newplus = (dstat->st_mode & 07777) | attr.perms.plus; newminus = ~(newplus & ~(attr.perms.minus)) & 07777; attr.perms.plus = newplus; attr.perms.minus = newminus; } } #endif PromiseResult result = VerifyFileAttributes(ctx, dest, dstat, attr, pp); #ifndef __MINGW32__ (attr.perms.owners)->uid = save_uid; (attr.perms.groups)->gid = save_gid; #endif if (attr.copy.preserve && (attr.copy.servers == NULL || strcmp(RlistScalarValue(attr.copy.servers), "localhost") == 0)) { if (!CopyFileExtendedAttributesDisk(src, dest)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Could not preserve extended attributes (ACLs and security contexts) on file '%s'", dest); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } } return result; } static PromiseResult CopyFileSources(EvalContext *ctx, char *destination, Attributes attr, const Promise *pp, AgentConnection *conn) { Buffer *source = BufferNew(); // Expand this.promiser ExpandScalar(ctx, PromiseGetBundle(pp)->ns, PromiseGetBundle(pp)->name, attr.copy.source, source); char vbuff[CF_BUFSIZE]; struct stat ssb, dsb; struct timespec start; char eventname[CF_BUFSIZE]; if (conn != NULL && (!conn->authenticated)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "No authenticated source '%s' in files.copy_from promise", BufferData(source)); BufferDestroy(source); return PROMISE_RESULT_FAIL; } if (cf_stat(BufferData(source), &ssb, attr.copy, conn) == -1) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, attr, "Can't stat file '%s' on '%s' in files.copy_from promise", BufferData(source), conn ? conn->remoteip : "localhost"); BufferDestroy(source); return PROMISE_RESULT_FAIL; } start = BeginMeasure(); strlcpy(vbuff, destination, CF_BUFSIZE - 3); if (S_ISDIR(ssb.st_mode)) /* could be depth_search */ { AddSlash(vbuff); strcat(vbuff, "."); } if (!MakeParentDirectory(vbuff, attr.move_obstructions)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't make directories for '%s' in files.copy_from promise", vbuff); BufferDestroy(source); return PROMISE_RESULT_FAIL; } CompressedArray *inode_cache = NULL; PromiseResult result = PROMISE_RESULT_NOOP; if (S_ISDIR(ssb.st_mode)) /* could be depth_search */ { if (attr.copy.purge) { Log(LOG_LEVEL_VERBOSE, "Destination purging enabled"); } Log(LOG_LEVEL_VERBOSE, "Entering directory '%s'", BufferData(source)); result = PromiseResultUpdate(result, SourceSearchAndCopy(ctx, BufferData(source), destination, attr.recursion.depth, attr, pp, ssb.st_dev, &inode_cache, conn)); if (stat(destination, &dsb) != -1) { if (attr.copy.check_root) { result = PromiseResultUpdate(result, VerifyCopiedFileAttributes(ctx, BufferData(source), destination, &ssb, &dsb, attr, pp)); } } } else { result = PromiseResultUpdate(result, VerifyCopy(ctx, BufferData(source), destination, attr, pp, &inode_cache, conn)); } DeleteCompressedArray(inode_cache); snprintf(eventname, CF_BUFSIZE - 1, "Copy(%s:%s > %s)", conn ? conn->this_server : "localhost", BufferData(source), destination); EndMeasure(eventname, start); BufferDestroy(source); return result; } /* Decide the protocol version the agent will use to connect: If the user has * specified a copy_from attribute then follow that one, else use the body * common control setting. */ static ProtocolVersion DecideProtocol(const EvalContext *ctx, ProtocolVersion copyfrom_setting) { if (copyfrom_setting == CF_PROTOCOL_UNDEFINED) { /* TODO we would like to get the common control setting from * GenericAgentConfig. Given that we have only access to EvalContext here, * we get the raw string and reparse it every time. */ const char *s = EvalContextVariableControlCommonGet( ctx, COMMON_CONTROL_PROTOCOL_VERSION); ProtocolVersion common_setting = ProtocolVersionParse(s); return common_setting; } else { return copyfrom_setting; } } static AgentConnection *FileCopyConnectionOpen(const EvalContext *ctx, const char *servername, FileCopy fc, bool background) { ConnectionFlags flags = { .protocol_version = DecideProtocol(ctx, fc.protocol_version), .cache_connection = !background, .force_ipv4 = fc.force_ipv4, .trust_server = fc.trustkey }; unsigned int conntimeout = fc.timeout; if (fc.timeout == CF_NOINT || fc.timeout < 0) { conntimeout = CONNTIMEOUT; } const char *port = (fc.port != NULL) ? fc.port : CFENGINE_PORT_STR; AgentConnection *conn = NULL; if (flags.cache_connection) { /* Get a connection from the cache. TODO fix our connection cache to account for ports. */ conn = GetIdleConnectionToServer(servername); if (conn == NULL) { int err = 0; conn = ServerConnection(servername, port, conntimeout, flags, &err); if (conn != NULL) { /* Success! Put it in the cache and leave. */ CacheServerConnection(conn, servername); } } } else { int err = 0; conn = ServerConnection(servername, port, conntimeout, flags, &err); } if (conn == NULL) { Log(LOG_LEVEL_INFO, "Unable to establish connection with %s", servername); if (flags.cache_connection) { MarkServerOffline(servername); } } return conn; } void FileCopyConnectionClose(AgentConnection *conn) { if (conn->flags.cache_connection) { /* Mark the connection as available in the cache. */ ServerNotBusy(conn); } else { DisconnectServer(conn); } } PromiseResult ScheduleCopyOperation(EvalContext *ctx, char *destination, Attributes attr, const Promise *pp) { /* TODO currently parser allows body copy_from to have no source! See tests/acceptance/10_files/02_maintain/017.cf and https://cfengine.com/bugtracker/view.php?id=687 */ /* assert(attr.copy.source != NULL); */ if (attr.copy.source == NULL) { Log(LOG_LEVEL_INFO, "Body copy_from has no source! Maybe a typo in the policy?"); return PROMISE_RESULT_FAIL; } Log(LOG_LEVEL_VERBOSE, "File '%s' copy_from '%s'", destination, attr.copy.source); /* Empty attr.copy.servers means copy from localhost. */ bool copyfrom_localhost = (attr.copy.servers == NULL); AgentConnection *conn = NULL; Rlist *rp = attr.copy.servers; /* Iterate over all copy_from servers until connection succeeds. */ while (rp != NULL && conn == NULL) { const char *servername = RlistScalarValue(rp); if (strcmp(servername, "localhost") == 0) { copyfrom_localhost = true; break; } conn = FileCopyConnectionOpen(ctx, servername, attr.copy, attr.transaction.background); rp = rp->next; } if (!copyfrom_localhost && conn == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "No suitable server responded to hail"); PromiseRef(LOG_LEVEL_INFO, pp); return PROMISE_RESULT_FAIL; } /* (conn == NULL) means local copy. */ PromiseResult result = CopyFileSources(ctx, destination, attr, pp, conn); if (conn != NULL) { FileCopyConnectionClose(conn); } return result; } PromiseResult ScheduleLinkOperation(EvalContext *ctx, char *destination, char *source, Attributes attr, const Promise *pp) { const char *lastnode; lastnode = ReadLastNode(destination); PromiseResult result = PROMISE_RESULT_NOOP; if (MatchRlistItem(ctx, attr.link.copy_patterns, lastnode)) { Log(LOG_LEVEL_VERBOSE, "Link '%s' matches copy_patterns", destination); CompressedArray *inode_cache = NULL; result = PromiseResultUpdate(result, VerifyCopy(ctx, attr.link.source, destination, attr, pp, &inode_cache, NULL)); DeleteCompressedArray(inode_cache); return result; } switch (attr.link.link_type) { case FILE_LINK_TYPE_SYMLINK: VerifyLink(ctx, destination, source, attr, pp); break; case FILE_LINK_TYPE_HARDLINK: VerifyHardLink(ctx, destination, source, attr, pp); break; case FILE_LINK_TYPE_RELATIVE: VerifyRelativeLink(ctx, destination, source, attr, pp); break; case FILE_LINK_TYPE_ABSOLUTE: VerifyAbsoluteLink(ctx, destination, source, attr, pp); break; default: Log(LOG_LEVEL_ERR, "Unknown link type - should not happen."); break; } return result; } PromiseResult ScheduleLinkChildrenOperation(EvalContext *ctx, char *destination, char *source, int recurse, Attributes attr, const Promise *pp) { Dir *dirh; const struct dirent *dirp; char promiserpath[CF_BUFSIZE], sourcepath[CF_BUFSIZE]; struct stat lsb; int ret; if ((ret = lstat(destination, &lsb)) != -1) { if (attr.move_obstructions && S_ISLNK(lsb.st_mode)) { unlink(destination); } else if (!S_ISDIR(lsb.st_mode)) { Log(LOG_LEVEL_ERR, "Cannot promise to link multiple files to children of '%s' as it is not a directory!", destination); return PROMISE_RESULT_NOOP; } } snprintf(promiserpath, CF_BUFSIZE, "%s/.", destination); PromiseResult result = PROMISE_RESULT_NOOP; if ((ret == -1 || !S_ISDIR(lsb.st_mode)) && !CfCreateFile(ctx, promiserpath, pp, attr, &result)) { Log(LOG_LEVEL_ERR, "Cannot promise to link multiple files to children of '%s' as it is not a directory!", destination); return result; } if ((dirh = DirOpen(source)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Can't open source of children to link '%s'. (opendir: %s)", attr.link.source, GetErrorStr()); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); return result; } for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!ConsiderLocalFile(dirp->d_name, source)) { continue; } /* Assemble pathnames */ strlcpy(promiserpath, destination, CF_BUFSIZE); AddSlash(promiserpath); if (!JoinPath(promiserpath, dirp->d_name)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Can't construct filename which verifying child links"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); DirClose(dirh); return result; } strlcpy(sourcepath, source, CF_BUFSIZE); AddSlash(sourcepath); if (!JoinPath(sourcepath, dirp->d_name)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, attr, "Can't construct filename while verifying child links"); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); DirClose(dirh); return result; } if ((lstat(promiserpath, &lsb) != -1) && !S_ISLNK(lsb.st_mode) && !S_ISDIR(lsb.st_mode)) { if (attr.link.when_linking_children == cfa_override) { attr.move_obstructions = true; } else { Log(LOG_LEVEL_VERBOSE, "Have promised not to disturb existing content belonging to '%s'", promiserpath); continue; } } if ((attr.recursion.depth > recurse) && (lstat(sourcepath, &lsb) != -1) && S_ISDIR(lsb.st_mode)) { result = PromiseResultUpdate(result, ScheduleLinkChildrenOperation(ctx, promiserpath, sourcepath, recurse + 1, attr, pp)); } else { result = PromiseResultUpdate(result, ScheduleLinkOperation(ctx, promiserpath, sourcepath, attr, pp)); } } DirClose(dirh); return result; } static PromiseResult VerifyFileIntegrity(EvalContext *ctx, const char *file, Attributes attr, const Promise *pp) { unsigned char digest1[EVP_MAX_MD_SIZE + 1]; unsigned char digest2[EVP_MAX_MD_SIZE + 1]; int changed = false, one, two; if ((attr.change.report_changes != FILE_CHANGE_REPORT_CONTENT_CHANGE) && (attr.change.report_changes != FILE_CHANGE_REPORT_ALL)) { return PROMISE_RESULT_NOOP; } memset(digest1, 0, EVP_MAX_MD_SIZE + 1); memset(digest2, 0, EVP_MAX_MD_SIZE + 1); PromiseResult result = PROMISE_RESULT_NOOP; if (attr.change.hash == HASH_METHOD_BEST) { if (!DONTDO) { HashFile(file, digest1, HASH_METHOD_MD5); HashFile(file, digest2, HASH_METHOD_SHA1); one = FileChangesCheckAndUpdateHash(ctx, file, digest1, HASH_METHOD_MD5, attr, pp, &result); two = FileChangesCheckAndUpdateHash(ctx, file, digest2, HASH_METHOD_SHA1, attr, pp, &result); if (one || two) { changed = true; } } } else { if (!DONTDO) { HashFile(file, digest1, attr.change.hash); if (FileChangesCheckAndUpdateHash(ctx, file, digest1, attr.change.hash, attr, pp, &result)) { changed = true; } } } if (changed) { EvalContextHeapPersistentSave(ctx, "checksum_alerts", CF_PERSISTENCE, CONTEXT_STATE_POLICY_PRESERVE, ""); EvalContextClassPutSoft(ctx, "checksum_alerts", CONTEXT_SCOPE_NAMESPACE, ""); FileChangesLogChange(file, FILE_STATE_CONTENT_CHANGED, "Content changed", pp); } if (attr.change.report_diffs) { char destination[CF_BUFSIZE]; if (!GetRepositoryPath(file, attr, destination)) { destination[0] = '\0'; } LogFileChange(ctx, file, changed, attr, pp, &CopyRegularFile, destination, &DeleteCompressedArray); } return result; } static int CompareForFileCopy(char *sourcefile, char *destfile, struct stat *ssb, struct stat *dsb, FileCopy fc, AgentConnection *conn) { int ok_to_copy; switch (fc.compare) { case FILE_COMPARATOR_CHECKSUM: case FILE_COMPARATOR_HASH: if (S_ISREG(dsb->st_mode) && S_ISREG(ssb->st_mode)) { ok_to_copy = CompareFileHashes(sourcefile, destfile, ssb, dsb, fc, conn); } else { Log(LOG_LEVEL_VERBOSE, "Checksum comparison replaced by ctime: files not regular"); ok_to_copy = (dsb->st_ctime < ssb->st_ctime) || (dsb->st_mtime < ssb->st_mtime); } if (ok_to_copy) { Log(LOG_LEVEL_VERBOSE, "Image file '%s' has a wrong digest/checksum, should be copy of '%s'", destfile, sourcefile); return ok_to_copy; } break; case FILE_COMPARATOR_BINARY: if (S_ISREG(dsb->st_mode) && S_ISREG(ssb->st_mode)) { ok_to_copy = CompareBinaryFiles(sourcefile, destfile, ssb, dsb, fc, conn); } else { Log(LOG_LEVEL_VERBOSE, "Byte comparison replaced by ctime: files not regular"); ok_to_copy = (dsb->st_ctime < ssb->st_ctime) || (dsb->st_mtime < ssb->st_mtime); } if (ok_to_copy) { Log(LOG_LEVEL_VERBOSE, "Image file %s has a wrong binary checksum, should be copy of '%s'", destfile, sourcefile); return ok_to_copy; } break; case FILE_COMPARATOR_MTIME: ok_to_copy = (dsb->st_mtime < ssb->st_mtime); if (ok_to_copy) { Log(LOG_LEVEL_VERBOSE, "Image file '%s' out of date, should be copy of '%s'", destfile, sourcefile); return ok_to_copy; } break; case FILE_COMPARATOR_ATIME: ok_to_copy = (dsb->st_ctime < ssb->st_ctime) || (dsb->st_mtime < ssb->st_mtime) || (CompareBinaryFiles(sourcefile, destfile, ssb, dsb, fc, conn)); if (ok_to_copy) { Log(LOG_LEVEL_VERBOSE, "Image file '%s' seems out of date, should be copy of '%s'", destfile, sourcefile); return ok_to_copy; } break; default: ok_to_copy = (dsb->st_ctime < ssb->st_ctime) || (dsb->st_mtime < ssb->st_mtime); if (ok_to_copy) { Log(LOG_LEVEL_VERBOSE, "Image file '%s' out of date, should be copy of '%s'", destfile, sourcefile); return ok_to_copy; } break; } return false; } static void FileAutoDefine(EvalContext *ctx, char *destfile) { char context[CF_MAXVARSIZE]; snprintf(context, CF_MAXVARSIZE, "auto_%s", CanonifyName(destfile)); EvalContextClassPutSoft(ctx, context, CONTEXT_SCOPE_NAMESPACE, "source=promise"); Log(LOG_LEVEL_INFO, "Auto defining class '%s'", context); } #ifndef __MINGW32__ static PromiseResult VerifySetUidGid(EvalContext *ctx, const char *file, struct stat *dstat, mode_t newperm, const Promise *pp, Attributes attr) { int amroot = true; PromiseResult result = PROMISE_RESULT_NOOP; if (!IsPrivileged()) { amroot = false; } if ((dstat->st_uid == 0) && (dstat->st_mode & S_ISUID)) { if (newperm & S_ISUID) { if (!IsItemIn(VSETUIDLIST, file)) { if (amroot) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "NEW SETUID root PROGRAM '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } PrependItem(&VSETUIDLIST, file, NULL); } } else { switch (attr.transaction.action) { case cfa_fix: cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Removing setuid (root) flag from '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; case cfa_warn: if (amroot) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "WARNING setuid (root) flag on '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } break; } } } if (dstat->st_uid == 0 && (dstat->st_mode & S_ISGID)) { if (newperm & S_ISGID) { if (!IsItemIn(VSETUIDLIST, file)) { if (S_ISDIR(dstat->st_mode)) { /* setgid directory */ } else { if (amroot) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "NEW SETGID root PROGRAM '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); } PrependItem(&VSETUIDLIST, file, NULL); } } } else { switch (attr.transaction.action) { case cfa_fix: cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Removing setgid (root) flag from '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); break; case cfa_warn: cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_WARN, pp, attr, "WARNING setgid (root) flag on '%s'", file); result = PromiseResultUpdate(result, PROMISE_RESULT_WARN); break; default: break; } } } return result; } #endif #ifdef __APPLE__ static int VerifyFinderType(EvalContext *ctx, const char *file, Attributes a, const Promise *pp, PromiseResult *result) { /* Code modeled after hfstar's extract.c */ typedef struct { long fdType; long fdCreator; short fdFlags; short fdLocationV; short fdLocationH; short fdFldr; short fdIconID; short fdUnused[3]; char fdScript; char fdXFlags; short fdComment; long fdPutAway; } FInfo; struct attrlist attrs; struct { long ssize; struct timespec created; struct timespec modified; struct timespec changed; struct timespec backup; FInfo fi; } fndrInfo; int retval; if (a.perms.findertype == NULL) { return 0; } Log(LOG_LEVEL_DEBUG, "VerifyFinderType of '%s' for '%s'", file, a.perms.findertype); if (strncmp(a.perms.findertype, "*", CF_BUFSIZE) == 0 || strncmp(a.perms.findertype, "", CF_BUFSIZE) == 0) { return 0; } attrs.bitmapcount = ATTR_BIT_MAP_COUNT; attrs.reserved = 0; attrs.commonattr = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO; attrs.volattr = 0; attrs.dirattr = 0; attrs.fileattr = 0; attrs.forkattr = 0; memset(&fndrInfo, 0, sizeof(fndrInfo)); getattrlist(file, &attrs, &fndrInfo, sizeof(fndrInfo), 0); if (fndrInfo.fi.fdType != *(long *) a.perms.findertype) { fndrInfo.fi.fdType = *(long *) a.perms.findertype; switch (a.transaction.action) { case cfa_fix: if (DONTDO) { Log(LOG_LEVEL_INFO, "Promised to set Finder Type code of '%s' to '%s'", file, a.perms.findertype); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return 0; } /* setattrlist does not take back in the long ssize */ retval = setattrlist(file, &attrs, &fndrInfo.created, 4 * sizeof(struct timespec) + sizeof(FInfo), 0); Log(LOG_LEVEL_DEBUG, "CheckFinderType setattrlist returned '%d'", retval); if (retval >= 0) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Setting Finder Type code of '%s' to '%s'", file, a.perms.findertype); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Setting Finder Type code of '%s' to '%s' failed", file, a.perms.findertype); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } return retval; case cfa_warn: Log(LOG_LEVEL_ERR, "Darwin FinderType does not match -- not fixing."); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return 0; default: return 0; } } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Finder Type code of '%s' to '%s' is as promised", file, a.perms.findertype); *result = PromiseResultUpdate(*result, PROMISE_RESULT_NOOP); return 0; } } #endif static void TruncateFile(char *name) { struct stat statbuf; int fd; if (stat(name, &statbuf) == -1) { Log(LOG_LEVEL_DEBUG, "Didn't find '%s' to truncate", name); } else { if ((fd = safe_creat(name, 000)) == -1) /* dummy mode ignored */ { Log(LOG_LEVEL_ERR, "Failed to create or truncate file '%s'. (creat: %s)", name, GetErrorStr()); } else { close(fd); } } } static void RegisterAHardLink(int i, char *value, Attributes attr, CompressedArray **inode_cache) { if (!FixCompressedArrayValue(i, value, inode_cache)) { /* Not root hard link, remove to preserve consistency */ if (DONTDO) { Log(LOG_LEVEL_VERBOSE, "Need to remove old hard link '%s' to preserve structure", value); } else { if (attr.transaction.action == cfa_warn) { Log(LOG_LEVEL_VERBOSE, "Need to remove old hard link '%s' to preserve structure", value); } else { Log(LOG_LEVEL_VERBOSE, "Removing old hard link '%s' to preserve structure", value); unlink(value); } } } } static int cf_stat(const char *file, struct stat *buf, FileCopy fc, AgentConnection *conn) { if (!file) { return -1; } if (conn == NULL) { return stat(file, buf); } else { assert(fc.servers && strcmp(RlistScalarValue(fc.servers), "localhost")); return cf_remote_stat(file, buf, "file", fc.encrypt, conn); } } #ifndef __MINGW32__ static int cf_readlink(EvalContext *ctx, char *sourcefile, char *linkbuf, int buffsize, Attributes attr, const Promise *pp, AgentConnection *conn, PromiseResult *result) /* wrapper for network access */ { memset(linkbuf, 0, buffsize); if (conn == NULL) { return readlink(sourcefile, linkbuf, buffsize - 1); } assert(attr.copy.servers && strcmp(RlistScalarValue(attr.copy.servers), "localhost")); const Stat *sp = ClientCacheLookup(conn, RlistScalarValue(attr.copy.servers), sourcefile); if (sp) { if (sp->cf_readlink != NULL) { if (strlen(sp->cf_readlink) + 1 > buffsize) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "readlink value is too large in cfreadlink"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); Log(LOG_LEVEL_ERR, "Contained '%s'", sp->cf_readlink); return -1; } else { memset(linkbuf, 0, buffsize); strcpy(linkbuf, sp->cf_readlink); return 0; } } } return -1; } #endif /* !__MINGW32__ */ static int SkipDirLinks(EvalContext *ctx, char *path, const char *lastnode, DirectoryRecursion r) { if (r.exclude_dirs) { if ((MatchRlistItem(ctx, r.exclude_dirs, path)) || (MatchRlistItem(ctx, r.exclude_dirs, lastnode))) { Log(LOG_LEVEL_VERBOSE, "Skipping matched excluded directory '%s'", path); return true; } } if (r.include_dirs) { if (!((MatchRlistItem(ctx, r.include_dirs, path)) || (MatchRlistItem(ctx, r.include_dirs, lastnode)))) { Log(LOG_LEVEL_VERBOSE, "Skipping matched non-included directory '%s'", path); return true; } } return false; } #ifndef __MINGW32__ bool VerifyOwner(EvalContext *ctx, const char *file, const Promise *pp, Attributes attr, struct stat *sb, PromiseResult *result) { struct passwd *pw; struct group *gp; UidList *ulp; GidList *glp; short uidmatch = false, gidmatch = false; uid_t uid = CF_SAME_OWNER; gid_t gid = CF_SAME_GROUP; for (ulp = attr.perms.owners; ulp != NULL; ulp = ulp->next) { if (ulp->uid == CF_SAME_OWNER || sb->st_uid == ulp->uid) /* "same" matches anything */ { uid = ulp->uid; uidmatch = true; break; } } if (attr.perms.groups->next == NULL && attr.perms.groups->gid == CF_UNKNOWN_GROUP) // Only one non.existent item { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to make file belong to an unknown group"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } if (attr.perms.owners->next == NULL && attr.perms.owners->uid == CF_UNKNOWN_OWNER) // Only one non.existent item { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Unable to make file belong to an unknown user"); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } for (glp = attr.perms.groups; glp != NULL; glp = glp->next) { if (glp->gid == CF_SAME_GROUP || sb->st_gid == glp->gid) /* "same" matches anything */ { gid = glp->gid; gidmatch = true; break; } } if (uidmatch && gidmatch) { return false; } else { if (!uidmatch) { for (ulp = attr.perms.owners; ulp != NULL; ulp = ulp->next) { if (attr.perms.owners->uid != CF_UNKNOWN_OWNER) { uid = attr.perms.owners->uid; /* default is first (not unknown) item in list */ break; } } } if (!gidmatch) { for (glp = attr.perms.groups; glp != NULL; glp = glp->next) { if (attr.perms.groups->gid != CF_UNKNOWN_GROUP) { gid = attr.perms.groups->gid; /* default is first (not unknown) item in list */ break; } } } switch (attr.transaction.action) { case cfa_fix: if (uid == CF_SAME_OWNER && gid == CF_SAME_GROUP) { Log(LOG_LEVEL_VERBOSE, "Touching '%s'", file); } else { if (uid != CF_SAME_OWNER) { Log(LOG_LEVEL_DEBUG, "Change owner to uid '%ju' if possible", (uintmax_t) uid); } if (gid != CF_SAME_GROUP) { Log(LOG_LEVEL_DEBUG, "Change group to gid '%ju' if possible", (uintmax_t) gid); } } if (!DONTDO && S_ISLNK(sb->st_mode)) { # ifdef HAVE_LCHOWN Log(LOG_LEVEL_DEBUG, "Using lchown function"); if (safe_lchown(file, uid, gid) == -1) { Log(LOG_LEVEL_INFO, "Cannot set ownership on link '%s'. (lchown: %s)", file, GetErrorStr()); } else { return true; } # endif } else if (!DONTDO) { if (!uidmatch) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Owner of '%s' was %ju, setting to %ju", file, (uintmax_t) sb->st_uid, (uintmax_t) uid); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } if (!gidmatch) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Group of '%s' was %ju, setting to %ju", file, (uintmax_t)sb->st_gid, (uintmax_t)gid); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } if (!S_ISLNK(sb->st_mode)) { if (safe_chown(file, uid, gid) == -1) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_DENIED, pp, attr, "Cannot set ownership on file '%s'. (chown: %s)", file, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_DENIED); } else { return true; } } } break; case cfa_warn: if ((pw = getpwuid(sb->st_uid)) == NULL) { Log(LOG_LEVEL_ERR, "File '%s' is not owned by anybody in the passwd database", file); Log(LOG_LEVEL_ERR, "(uid = %ju,gid = %ju)", (uintmax_t)sb->st_uid, (uintmax_t)sb->st_gid); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); break; } if ((gp = getgrgid(sb->st_gid)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "File '%s' is not owned by any group in group database", file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); break; } cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "File '%s' is owned by '%s', group '%s'", file, pw->pw_name, gp->gr_name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); break; } } return false; } #endif /* !__MINGW32__ */ static void VerifyFileChanges(const char *file, struct stat *sb, Attributes attr, const Promise *pp) { if ((attr.change.report_changes != FILE_CHANGE_REPORT_STATS_CHANGE) && (attr.change.report_changes != FILE_CHANGE_REPORT_ALL)) { return; } FileChangesCheckAndUpdateStats(file, sb, attr.change.update, pp); } bool CfCreateFile(EvalContext *ctx, char *file, const Promise *pp, Attributes attr, PromiseResult *result) { int fd; /* If name ends in /. then this is a directory */ // attr.move_obstructions for MakeParentDirectory if (!IsAbsoluteFileName(file)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Cannot create a relative filename '%s' - has no invariant meaning. (creat: %s)", file, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } if (strcmp(".", ReadLastNode(file)) == 0) { Log(LOG_LEVEL_DEBUG, "File object '%s' seems to be a directory", file); if (!DONTDO && attr.transaction.action != cfa_warn) { if (!MakeParentDirectory(file, attr.move_obstructions)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Error creating directories for '%s'. (creat: %s)", file, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Created directory '%s'", file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Warning promised, need to create directory '%s'", file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return false; } } else { if (!DONTDO && attr.transaction.action != cfa_warn) { mode_t saveumask = umask(0); mode_t filemode = 0600; /* Decide the mode for filecreation */ if (PromiseGetConstraintAsRval(pp, "mode", RVAL_TYPE_SCALAR) == NULL) { /* Relying on umask is risky */ filemode = 0600; Log(LOG_LEVEL_VERBOSE, "No mode was set, choose plain file default %04jo", (uintmax_t)filemode); } else { filemode = attr.perms.plus & ~(attr.perms.minus); } MakeParentDirectory(file, attr.move_obstructions); if ((fd = safe_creat(file, filemode)) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Error creating file '%s', mode '%04jo'. (creat: %s)", file, (uintmax_t)filemode, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); umask(saveumask); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Created file '%s', mode %04jo", file, (uintmax_t)filemode); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); close(fd); umask(saveumask); return true; } } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_WARN, pp, attr, "Warning promised, need to create file '%s'", file); *result = PromiseResultUpdate(*result, PROMISE_RESULT_WARN); return false; } } return true; } static int DeviceBoundary(struct stat *sb, dev_t rootdevice) { if (sb->st_dev == rootdevice) { return false; } else { Log(LOG_LEVEL_VERBOSE, "Device change from %jd to %jd", (intmax_t) rootdevice, (intmax_t) sb->st_dev); return true; } } cfengine-3.6.2/cf-agent/agent-diagnostics.h0000664000175100017510000000473212243421446020266 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_AGENT_DIAGNOSTICS_H #define CFENGINE_AGENT_DIAGNOSTICS_H #include #include typedef struct { bool success; char *message; } AgentDiagnosticsResult; typedef AgentDiagnosticsResult AgentDiagnosticCheckFn(const char *workdir); typedef struct { const char *description; AgentDiagnosticCheckFn *check; } AgentDiagnosticCheck; typedef void (*AgentDiagnosticsRunFunction)(const char *workdir, const AgentDiagnosticCheck checks[], Writer *output); void AgentDiagnosticsRun(const char *workdir, const AgentDiagnosticCheck checks[], Writer *output); // Checks AgentDiagnosticsResult AgentDiagnosticsCheckHavePrivateKey(const char *workdir); AgentDiagnosticsResult AgentDiagnosticsCheckHavePublicKey(const char *workdir); AgentDiagnosticsResult AgentDiagnosticsCheckIsBootstrapped(const char *workdir); AgentDiagnosticsResult AgentDiagnosticsCheckAmPolicyServer(const char *workdir); typedef AgentDiagnosticsResult (*AgentDiagnosticsResultNewFunction)(bool success, char *message); AgentDiagnosticsResult AgentDiagnosticsResultNew(bool success, char *message); const AgentDiagnosticCheck *AgentDiagnosticsAllChecks(void); ENTERPRISE_VOID_FUNC_4ARG_DECLARE(void, AgentDiagnosticsRunAllChecksNova, const char *, workdir, Writer *, output, AgentDiagnosticsRunFunction, AgentDiagnosticsRunPtr, AgentDiagnosticsResultNewFunction, AgentDiagnosticsResultNewPtr); #endif cfengine-3.6.2/cf-agent/verify_files_hashes.c0000664000175100017510000000672512411001073020666 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include int CompareFileHashes(const char *file1, const char *file2, struct stat *sstat, struct stat *dstat, FileCopy fc, AgentConnection *conn) { unsigned char digest1[EVP_MAX_MD_SIZE + 1] = { 0 }, digest2[EVP_MAX_MD_SIZE + 1] = { 0 }; int i; if (sstat->st_size != dstat->st_size) { Log(LOG_LEVEL_DEBUG, "File sizes differ, no need to compute checksum"); return true; } if (conn == NULL) { HashFile(file1, digest1, CF_DEFAULT_DIGEST); HashFile(file2, digest2, CF_DEFAULT_DIGEST); for (i = 0; i < EVP_MAX_MD_SIZE; i++) { if (digest1[i] != digest2[i]) { return true; } } Log(LOG_LEVEL_DEBUG, "Files were identical"); return false; /* only if files are identical */ } else { assert(fc.servers && strcmp(RlistScalarValue(fc.servers), "localhost")); return CompareHashNet(file1, file2, fc.encrypt, conn); /* client.c */ } } int CompareBinaryFiles(const char *file1, const char *file2, struct stat *sstat, struct stat *dstat, FileCopy fc, AgentConnection *conn) { int fd1, fd2, bytes1, bytes2; char buff1[BUFSIZ], buff2[BUFSIZ]; if (sstat->st_size != dstat->st_size) { Log(LOG_LEVEL_DEBUG, "File sizes differ, no need to compute checksum"); return true; } if (conn == NULL) { fd1 = safe_open(file1, O_RDONLY | O_BINARY, 0400); fd2 = safe_open(file2, O_RDONLY | O_BINARY, 0400); do { bytes1 = read(fd1, buff1, BUFSIZ); bytes2 = read(fd2, buff2, BUFSIZ); if ((bytes1 != bytes2) || (memcmp(buff1, buff2, bytes1) != 0)) { Log(LOG_LEVEL_VERBOSE, "Binary Comparison mismatch..."); close(fd2); close(fd1); return true; } } while (bytes1 > 0); close(fd2); close(fd1); return false; /* only if files are identical */ } else { assert(fc.servers && strcmp(RlistScalarValue(fc.servers), "localhost")); Log(LOG_LEVEL_DEBUG, "Using network checksum instead"); return CompareHashNet(file1, file2, fc.encrypt, conn); /* client.c */ } } cfengine-3.6.2/cf-agent/tokyo_check.c0000664000175100017510000002757212411001073017152 0ustar00a10038a1003800000000000000#include #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #ifdef TCDB /* * The idea behind the following code comes from : copiousfreetime@github */ /* * Fields we will need from a TC record */ typedef struct TokyoCabinetRecord { uint64_t offset; uint64_t length; uint64_t left; uint64_t right; uint32_t key_size; uint32_t rec_size; uint16_t pad_size; uint8_t magic; uint8_t hash; } TokyoCabinetRecord; /* meta information from the Hash Database * used to coordinate the other operations */ typedef struct DBMeta { uint64_t bucket_count; /* Number of hash buckets */ uint64_t bucket_offset; /* Start of the bucket list */ uint64_t record_count; /* Number of records */ uint64_t record_offset; /* First record offset in file */ short alignment_pow; /* power of 2 for calculating offsets */ short bytes_per; /* 4 or 8 */ char dbpath[PATH_MAX + 1]; /* full pathname to the database file */ int fd; StringMap *offset_map; StringMap *record_map; } DBMeta; static DBMeta *DBMetaNewDirect(const char *dbfilename) { char hbuf[256]; DBMeta *dbmeta; dbmeta = (DBMeta *) xcalloc(1, sizeof(DBMeta)); realpath(dbfilename, dbmeta->dbpath); if (-1 == (dbmeta->fd = open(dbmeta->dbpath, O_RDONLY))) { Log(LOG_LEVEL_ERR, "Failure opening file '%s'. (open: %s)", dbmeta->dbpath, GetErrorStr()); if (dbmeta) { free(dbmeta); } return NULL; } if (256 != read(dbmeta->fd, hbuf, 256)) { Log(LOG_LEVEL_ERR, "Failure reading from database '%s'. (read: %s)", dbmeta->dbpath, GetErrorStr()); close(dbmeta->fd); if (dbmeta) { free(dbmeta); } return NULL; } memcpy(&(dbmeta->bucket_count), hbuf + 40, sizeof(uint64_t)); dbmeta->bucket_offset = 256; uint8_t opts; memcpy(&opts, hbuf + 36, sizeof(uint8_t)); dbmeta->bytes_per = (opts & (1 << 0)) ? sizeof(uint64_t) : sizeof(uint32_t); memcpy(&(dbmeta->record_count), hbuf + 48, sizeof(uint64_t)); memcpy(&(dbmeta->record_offset), hbuf + 64, sizeof(uint64_t)); memcpy(&(dbmeta->alignment_pow), hbuf + 34, sizeof(uint8_t)); dbmeta->offset_map = StringMapNew(); dbmeta->record_map = StringMapNew(); Log(LOG_LEVEL_VERBOSE, "Database : %s", dbmeta->dbpath); Log(LOG_LEVEL_VERBOSE, " number of buckets : %" PRIu64, dbmeta->bucket_count); Log(LOG_LEVEL_VERBOSE, " offset of buckets : %" PRIu64, dbmeta->bucket_offset); Log(LOG_LEVEL_VERBOSE, " bytes per pointer : %hd", dbmeta->bytes_per); Log(LOG_LEVEL_VERBOSE, " alignment power : %hd", dbmeta->alignment_pow); Log(LOG_LEVEL_VERBOSE, " number of records : %" PRIu64, dbmeta->record_count); Log(LOG_LEVEL_VERBOSE, " offset of records : %" PRIu64, dbmeta->record_offset); return dbmeta; } static void DBMetaFree(DBMeta * dbmeta) { StringMapDestroy(dbmeta->offset_map); StringMapDestroy(dbmeta->record_map); close(dbmeta->fd); if (dbmeta) { free(dbmeta); } } static int AddOffsetToMapUnlessExists(StringMap ** tree, uint64_t offset, int64_t bucket_index) { char *tmp; xasprintf(&tmp, "%" PRIu64, offset); char *val; if (StringMapHasKey(*tree, tmp) == false) { xasprintf(&val, "%" PRIu64, bucket_index); StringMapInsert(*tree, tmp, val); } else { Log(LOG_LEVEL_ERR, "Duplicate offset for value %" PRIu64 " at index %" PRId64 ", other value %" PRIu64 ", other index '%s'", offset, bucket_index, offset, (char *) StringMapGet(*tree, tmp)); free(tmp); } return 0; } static int DBMetaPopulateOffsetMap(DBMeta * dbmeta) { uint64_t i; if (lseek(dbmeta->fd, dbmeta->bucket_offset, SEEK_SET) == -1) { Log(LOG_LEVEL_ERR, "Error traversing bucket section to find record offsets '%s'", strerror(errno)); return 1; } for (i = 0; i < dbmeta->bucket_count; i++) { uint64_t offset = 0LL; int b = read(dbmeta->fd, &offset, dbmeta->bytes_per); if (b != dbmeta->bytes_per) { Log(LOG_LEVEL_ERR, "Read the wrong number of bytes (%d)", b); return 2; } /* if the value is > 0 then we have a number so do something with it */ if (offset > 0) { offset = offset << dbmeta->alignment_pow; if (AddOffsetToMapUnlessExists(&(dbmeta->offset_map), offset, i)) { return 3; } } } Log(LOG_LEVEL_VERBOSE, "Found %zu buckets with offsets", StringMapSize(dbmeta->offset_map)); return 0; } typedef enum { // enumeration for magic data MAGIC_DATA_BLOCK = 0xc8, // for data block MAGIC_FREE_BLOCK = 0xb0 // for free block } TypeOfBlock; static int TCReadVaryInt(int fd, uint32_t * result) { uint64_t num = 0; unsigned int base = 1; unsigned int i = 0; int read_bytes = 0; char c; while (true) { read_bytes += read(fd, &c, 1); if (c >= 0) { num += (c * base); break; } num += (base * (c + 1) * -1); base <<= 7; i += 1; } *result = num; return read_bytes; } static bool DBMetaReadOneRecord(DBMeta * dbmeta, TokyoCabinetRecord * rec) { if (lseek(dbmeta->fd, rec->offset, SEEK_SET) == -1) { Log(LOG_LEVEL_ERR, "Error traversing record section to find records : "); } while (true) { // get the location of the current read rec->offset = lseek(dbmeta->fd, 0, SEEK_CUR); if (rec->offset == (off_t) - 1) { Log(LOG_LEVEL_ERR, "Error traversing record section to find records"); } if (1 != read(dbmeta->fd, &(rec->magic), 1)) { Log(LOG_LEVEL_ERR, "Failure reading 1 byte, (read: %s)", GetErrorStr()); return false; } if (MAGIC_DATA_BLOCK == rec->magic) { Log(LOG_LEVEL_VERBOSE, "off=%" PRIu64 "[c8]", rec->offset); int length = 1; length += read(dbmeta->fd, &(rec->hash), 1); length += read(dbmeta->fd, &(rec->left), dbmeta->bytes_per); rec->left = rec->left << dbmeta->alignment_pow; length += read(dbmeta->fd, &(rec->right), dbmeta->bytes_per); rec->right = rec->right << dbmeta->alignment_pow; length += read(dbmeta->fd, &(rec->pad_size), 2); length += rec->pad_size; length += TCReadVaryInt(dbmeta->fd, &(rec->key_size)); length += TCReadVaryInt(dbmeta->fd, &(rec->rec_size)); rec->length = length + rec->key_size + rec->rec_size; return true; } else if (MAGIC_FREE_BLOCK == rec->magic) { Log(LOG_LEVEL_VERBOSE, "off=%" PRIu64 "[b0]", rec->offset); uint32_t length; rec->length = 1; rec->length += read(dbmeta->fd, &length, sizeof(length)); rec->length += length; return true; } else { Log(LOG_LEVEL_VERBOSE, "Read a non-magic byte (skip it)"); } } Log(LOG_LEVEL_ERR, "Read loop reached here"); return false; } static int DBMetaPopulateRecordMap(DBMeta * dbmeta) { off_t offset; uint64_t data_blocks = 0; uint64_t free_blocks = 0; struct stat st; offset = dbmeta->record_offset; if (fstat(dbmeta->fd, &st) == -1) { Log(LOG_LEVEL_ERR, "Error getting file stats. (fstat: %s)", GetErrorStr()); return 1; } while (offset < st.st_size) { TokyoCabinetRecord new_rec; memset(&new_rec, 0, sizeof(TokyoCabinetRecord)); new_rec.offset = offset; // read a variable-length record if (!DBMetaReadOneRecord(dbmeta, &new_rec)) { Log(LOG_LEVEL_ERR, "Unable to fetch a new record from DB file"); return 2; } else { offset = new_rec.offset + new_rec.length; } // if it is a data record then: // for the record, its left and right do: // look up that record in the offset tree // 1) remove it if it exists // 2) add it to the record_tree if it doesn't if (MAGIC_DATA_BLOCK == new_rec.magic) { if (new_rec.offset > 0) { char *key; xasprintf(&key, "%" PRIu64, new_rec.offset); if (StringMapHasKey(dbmeta->offset_map, key) == true) { if (key) { free(key); } } else { StringMapInsert(dbmeta->record_map, key, xstrdup("0")); } } else { Log(LOG_LEVEL_ERR, "new_rec.offset cannot be <= 0 ???"); } if (new_rec.left > 0) { Log(LOG_LEVEL_VERBOSE, "handle left %" PRIu64, new_rec.left); if (AddOffsetToMapUnlessExists (&(dbmeta->offset_map), new_rec.left, -1)) { return 4; } } if (new_rec.right > 0) { Log(LOG_LEVEL_VERBOSE, "handle right %" PRIu64, new_rec.right); if (AddOffsetToMapUnlessExists (&(dbmeta->offset_map), new_rec.right, -1)) { return 4; } } data_blocks++; } else if (MAGIC_FREE_BLOCK == new_rec.magic) { // if it is a fragment record, then skip it free_blocks++; } else { Log(LOG_LEVEL_ERR, "NO record found at offset %" PRIu64, new_rec.offset); } } // if we are not at the end of the file, output the current file offset // with an appropriate message and return Log(LOG_LEVEL_VERBOSE, "Found %" PRIu64 " data records and " "%" PRIu64 " free block records", data_blocks, free_blocks); return 0; } static int DBMetaGetResults(DBMeta * dbmeta) { uint64_t buckets_no_record = StringMapSize(dbmeta->offset_map); uint64_t records_no_bucket = StringMapSize(dbmeta->record_map); int ret = 0; Log(LOG_LEVEL_VERBOSE, "Found %" PRIu64 " offsets listed in buckets that do not have records", buckets_no_record); Log(LOG_LEVEL_VERBOSE, "Found %" PRIu64 " records in data that do not have an offset pointing to them", records_no_bucket); if (buckets_no_record > 0) { ret += 1; } if (records_no_bucket > 0) { ret += 2; } return ret; } int CheckTokyoDBCoherence(const char *path) { int ret = 0; DBMeta *dbmeta; dbmeta = DBMetaNewDirect(path); if (dbmeta == NULL) { return 1; } Log(LOG_LEVEL_VERBOSE, "Populating with bucket section offsets"); ret = DBMetaPopulateOffsetMap(dbmeta); if (ret) { goto clean; } Log(LOG_LEVEL_VERBOSE, "Populating with record section offsets"); ret = DBMetaPopulateRecordMap(dbmeta); if (ret) { goto clean; } ret = DBMetaGetResults(dbmeta); clean: if (dbmeta) { DBMetaFree(dbmeta); } return ret; } #else int CheckTokyoDBCoherence(ARG_UNUSED const char *path) { return 0; } #endif cfengine-3.6.2/cf-agent/verify_storage.c0000664000175100017510000003566512411001073017702 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include bool CF_MOUNTALL = false; /* GLOBAL_X */ static PromiseResult FindStoragePromiserObjects(EvalContext *ctx, const Promise *pp); static PromiseResult VerifyFileSystem(EvalContext *ctx, char *name, Attributes a, const Promise *pp); static PromiseResult VerifyFreeSpace(EvalContext *ctx, char *file, Attributes a, const Promise *pp); static PromiseResult VolumeScanArrivals(char *file, Attributes a, const Promise *pp); #if !defined(__MINGW32__) static int FileSystemMountedCorrectly(Seq *list, char *name, Attributes a); static int IsForeignFileSystem(struct stat *childstat, char *dir); #endif #ifndef __MINGW32__ static PromiseResult VerifyMountPromise(EvalContext *ctx, char *file, Attributes a, const Promise *pp); #endif /* !__MINGW32__ */ Seq *GetGlobalMountedFSList(void) { static Seq *mounted_fs_list = NULL; /* GLOBAL_X */ if (!mounted_fs_list) { mounted_fs_list = SeqNew(100, free); } return mounted_fs_list; } PromiseResult FindAndVerifyStoragePromises(EvalContext *ctx, const Promise *pp) { PromiseBanner(pp); return FindStoragePromiserObjects(ctx, pp); } /*****************************************************************************/ static PromiseResult FindStoragePromiserObjects(EvalContext *ctx, const Promise *pp) { /* Check if we are searching over a regular expression */ return LocateFilePromiserGroup(ctx, pp->promiser, pp, VerifyStoragePromise); } /*****************************************************************************/ PromiseResult VerifyStoragePromise(EvalContext *ctx, char *path, const Promise *pp) { CfLock thislock; Attributes a = GetStorageAttributes(ctx, pp); #ifdef __MINGW32__ if (!a.havemount) { Log(LOG_LEVEL_VERBOSE, "storage.mount is not supported on Windows"); } #endif /* No parameter conflicts here */ if (a.mount.unmount) { if ((a.mount.mount_source)) { Log(LOG_LEVEL_VERBOSE, "An unmount promise indicates a mount-source information - probably an error"); } if ((a.mount.mount_server)) { Log(LOG_LEVEL_VERBOSE, "An unmount promise indicates a mount-server information - probably an error"); } } else if (a.havemount) { if ((a.mount.mount_source == NULL) || (a.mount.mount_server == NULL)) { Log(LOG_LEVEL_ERR, "Insufficient specification in mount promise - need source and server"); return PROMISE_RESULT_NOOP; } } thislock = AcquireLock(ctx, path, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } /* Do mounts first */ PromiseResult result = PROMISE_RESULT_NOOP; #ifndef __MINGW32__ if ((SeqLength(GetGlobalMountedFSList())) && (!LoadMountInfo(GetGlobalMountedFSList()))) { Log(LOG_LEVEL_ERR, "Couldn't obtain a list of mounted filesystems - aborting"); YieldCurrentLock(thislock); return PROMISE_RESULT_NOOP; } if (a.havemount) { result = PromiseResultUpdate(result, VerifyMountPromise(ctx, path, a, pp)); } #endif /* !__MINGW32__ */ /* Then check file system */ if (a.havevolume) { result = PromiseResultUpdate(result, VerifyFileSystem(ctx, path, a, pp)); if (a.volume.freespace != CF_NOINT) { result = PromiseResultUpdate(result, VerifyFreeSpace(ctx, path, a, pp)); } if (a.volume.scan_arrivals) { result = PromiseResultUpdate(result, VolumeScanArrivals(path, a, pp)); } } YieldCurrentLock(thislock); return result; } /*******************************************************************/ /** Level */ /*******************************************************************/ static PromiseResult VerifyFileSystem(EvalContext *ctx, char *name, Attributes a, const Promise *pp) { struct stat statbuf, localstat; Dir *dirh; const struct dirent *dirp; off_t sizeinbytes = 0; long filecount = 0; char buff[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "Checking required filesystem %s", name); if (stat(name, &statbuf) == -1) { return PROMISE_RESULT_NOOP; } if (S_ISLNK(statbuf.st_mode)) { PromiseResult result = PROMISE_RESULT_NOOP; KillGhostLink(ctx, name, a, pp, &result); return result; } PromiseResult result = PROMISE_RESULT_NOOP; if (S_ISDIR(statbuf.st_mode)) { if ((dirh = DirOpen(name)) == NULL) { Log(LOG_LEVEL_ERR, "Can't open directory '%s' which checking required/disk. (opendir: %s)", name, GetErrorStr()); return PROMISE_RESULT_NOOP; } for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!ConsiderLocalFile(dirp->d_name, name)) { continue; } filecount++; strcpy(buff, name); if (buff[strlen(buff)] != FILE_SEPARATOR) { strcat(buff, FILE_SEPARATOR_STR); } strcat(buff, dirp->d_name); if (lstat(buff, &localstat) == -1) { if (S_ISLNK(localstat.st_mode)) { KillGhostLink(ctx, buff, a, pp, &result); continue; } Log(LOG_LEVEL_ERR, "Can't stat volume '%s'. (lstat: %s)", buff, GetErrorStr()); continue; } sizeinbytes += localstat.st_size; } DirClose(dirh); if (sizeinbytes < 0) { Log(LOG_LEVEL_ERR, "Internal error: count of byte size was less than zero!"); return result; } if (sizeinbytes < a.volume.sensible_size) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "File system '%s' is suspiciously small! (%jd bytes)", name, (intmax_t) sizeinbytes); return PROMISE_RESULT_INTERRUPTED; } if (filecount < a.volume.sensible_count) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Filesystem '%s' has only %ld files/directories.", name, filecount); return PROMISE_RESULT_INTERRUPTED; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Filesystem '%s' content seems to be sensible as promised", name); return result; } /*******************************************************************/ static PromiseResult VerifyFreeSpace(EvalContext *ctx, char *file, Attributes a, const Promise *pp) { struct stat statbuf; #ifdef __MINGW32__ if (!a.volume.check_foreign) { Log(LOG_LEVEL_VERBOSE, "storage.volume.check_foreign is not supported on Windows (checking every mount)"); } #endif /* __MINGW32__ */ if (stat(file, &statbuf) == -1) { Log(LOG_LEVEL_ERR, "Couldn't stat '%s' while checking diskspace. (stat: %s)", file, GetErrorStr()); return PROMISE_RESULT_NOOP; } #ifndef __MINGW32__ if (!a.volume.check_foreign) { if (IsForeignFileSystem(&statbuf, file)) { Log(LOG_LEVEL_INFO, "Filesystem '%s' is mounted from a foreign system, so skipping it", file); return PROMISE_RESULT_NOOP; } } #endif /* !__MINGW32__ */ if (a.volume.freespace < 0) { int threshold_percentage = -a.volume.freespace; int free_percentage = GetDiskUsage(file, CF_SIZE_PERCENT); if (free_percentage < threshold_percentage) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Free disk space is under %d%% for volume containing '%s', %d%% free", threshold_percentage, file, free_percentage); return PROMISE_RESULT_FAIL; } } else { off_t threshold = a.volume.freespace; off_t free_bytes = GetDiskUsage(file, CF_SIZE_ABS); if (free_bytes < threshold) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Disk space under %jd kB for volume containing '%s' (%jd kB free)", (intmax_t) (threshold / 1024), file, (intmax_t) (free_bytes / 1024)); return PROMISE_RESULT_FAIL; } } return PROMISE_RESULT_NOOP; } /*******************************************************************/ static PromiseResult VolumeScanArrivals(ARG_UNUSED char *file, ARG_UNUSED Attributes a, ARG_UNUSED const Promise *pp) { Log(LOG_LEVEL_VERBOSE, "Scan arrival sequence . not yet implemented"); return PROMISE_RESULT_NOOP; } /*******************************************************************/ /*********************************************************************/ /* Unix-specific implementations */ /*********************************************************************/ #if !defined(__MINGW32__) static int FileSystemMountedCorrectly(Seq *list, char *name, Attributes a) { int found = false; for (size_t i = 0; i < SeqLength(list); i++) { Mount *mp = SeqAt(list, i); if (mp == NULL) { continue; } /* Give primacy to the promised / affected object */ if (strcmp(name, mp->mounton) == 0) { /* We have found something mounted on the promiser dir */ found = true; if ((a.mount.mount_source) && (strcmp(mp->source, a.mount.mount_source) != 0)) { Log(LOG_LEVEL_INFO, "A different file system '%s:%s' is mounted on '%s' than what is promised", mp->host, mp->source, name); return false; } else { Log(LOG_LEVEL_VERBOSE, "File system '%s' seems to be mounted correctly", mp->source); break; } } } if (!found) { if (!a.mount.unmount) { Log(LOG_LEVEL_VERBOSE, "File system '%s' seems not to be mounted correctly", name); CF_MOUNTALL = true; } } return found; } /*********************************************************************/ /* Mounting */ /*********************************************************************/ static int IsForeignFileSystem(struct stat *childstat, char *dir) /* Is FS NFS mounted ? */ { struct stat parentstat; char vbuff[CF_BUFSIZE]; strlcpy(vbuff, dir, CF_BUFSIZE); if (vbuff[strlen(vbuff) - 1] == FILE_SEPARATOR) { strcat(vbuff, ".."); } else { strcat(vbuff, FILE_SEPARATOR_STR); strcat(vbuff, ".."); } if (stat(vbuff, &parentstat) == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to stat '%s'. (stat: %s)", vbuff, GetErrorStr()); return false; } if (childstat->st_dev != parentstat.st_dev) { Log(LOG_LEVEL_DEBUG, "'%s' is on a different file system, not descending", dir); for (size_t i = 0; i < SeqLength(GetGlobalMountedFSList()); i++) { Mount *entry = SeqAt(GetGlobalMountedFSList(), i); if (!strcmp(entry->mounton, dir)) { if ((entry->options) && (strstr(entry->options, "nfs"))) { return true; } } } } return false; } static PromiseResult VerifyMountPromise(EvalContext *ctx, char *name, Attributes a, const Promise *pp) { char *options; char dir[CF_BUFSIZE]; int changes = 0; Log(LOG_LEVEL_VERBOSE, "Verifying mounted file systems on '%s'", name); snprintf(dir, CF_BUFSIZE, "%s/.", name); if (!IsPrivileged()) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Only root can mount filesystems"); return PROMISE_RESULT_INTERRUPTED; } options = Rlist2String(a.mount.mount_options, ","); PromiseResult result = PROMISE_RESULT_NOOP; if (!FileSystemMountedCorrectly(GetGlobalMountedFSList(), name, a)) { if (!a.mount.unmount) { if (!MakeParentDirectory(dir, a.move_obstructions)) { } if (a.mount.editfstab) { changes += VerifyInFstab(ctx, name, a, pp, &result); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Filesystem '%s' was not mounted as promised, and no edits were promised in '%s'", name, VFSTAB[VSYSTEMHARDCLASS]); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); // Mount explicitly result = PromiseResultUpdate(result, VerifyMount(ctx, name, a, pp)); } } else { if (a.mount.editfstab) { changes += VerifyNotInFstab(ctx, name, a, pp, &result); } } if (changes) { CF_MOUNTALL = true; } } else { if (a.mount.unmount) { VerifyUnmount(ctx, name, a, pp); if (a.mount.editfstab) { VerifyNotInFstab(ctx, name, a, pp, &result); } } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "Filesystem '%s' seems to be mounted as promised", name); } } free(options); return result; } #endif /* !__MINGW32__ */ void DeleteStorageContext(void) { #ifndef __MINGW32__ CleanupNFS(); if (!DONTDO && CF_MOUNTALL) { Log(LOG_LEVEL_VERBOSE, "Mounting all filesystems"); MountAll(); } #endif /* !__MINGW32__ */ } cfengine-3.6.2/cf-execd/0000775000175100017510000000000012413020723014466 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-execd/cf-execd.c0000664000175100017510000004137012411001073016310 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CF_EXEC_IFELAPSED 0 #define CF_EXEC_EXPIREAFTER 1 static int NO_FORK = false; /* GLOBAL_A */ static int ONCE = false; /* GLOBAL_A */ static int WINSERVICE = true; /* GLOBAL_A */ static pthread_attr_t threads_attrs; /* GLOBAL_T, initialized by pthread_attr_init */ /*******************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv); void ThisAgentInit(void); static bool ScheduleRun(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, ExecdConfig **execd_config, ExecConfig **exec_config); #ifndef __MINGW32__ static void Apoptosis(void); #endif static bool LocalExecInThread(const ExecConfig *config); /*******************************************************************/ /* Command line options */ /*******************************************************************/ static const char *const CF_EXECD_SHORT_DESCRIPTION = "scheduling daemon for cf-agent"; static const char *const CF_EXECD_MANPAGE_LONG_DESCRIPTION = "cf-execd is the scheduling daemon for cf-agent. It runs cf-agent locally according to a schedule specified in " "policy code (executor control body). After a cf-agent run is completed, cf-execd gathers output from cf-agent, " "and may be configured to email the output to a specified address. It may also be configured to splay (randomize) the " "execution schedule to prevent synchronized cf-agent runs across a network."; static const struct option OPTIONS[] = { {"help", no_argument, 0, 'h'}, {"debug", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"dry-run", no_argument, 0, 'n'}, {"version", no_argument, 0, 'V'}, {"file", required_argument, 0, 'f'}, {"define", required_argument, 0, 'D'}, {"negate", required_argument, 0, 'N'}, {"no-lock", no_argument, 0, 'K'}, {"inform", no_argument, 0, 'I'}, {"diagnostic", no_argument, 0, 'x'}, {"no-fork", no_argument, 0, 'F'}, {"once", no_argument, 0, 'O'}, {"no-winsrv", no_argument, 0, 'W'}, {"ld-library-path", required_argument, 0, 'L'}, {"legacy-output", no_argument, 0, 'l'}, {"color", optional_argument, 0, 'C'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { "Print the help message", "Enable debugging output", "Output verbose information about the behaviour of the agent", "All talk and no action mode - make no changes, only inform of promises not kept", "Output the version of the software", "Specify an alternative input file than the default", "Define a list of comma separated classes to be defined at the start of execution", "Define a list of comma separated classes to be undefined at the start of execution", "Ignore locking constraints during execution (ifelapsed/expireafter) if \"too soon\" to run", "Print basic information about changes made to the system, i.e. promises repaired", "Activate internal diagnostics (developers only)", "Run as a foreground processes (do not fork)", "Run once and then exit (implies no-fork)", "Do not run as a service on windows - use this when running from a command shell (CFEngine Nova only)", "Set the internal value of LD_LIBRARY_PATH for child processes", "Use legacy output format", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", NULL }; /*****************************************************************************/ int main(int argc, char *argv[]) { GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); Policy *policy = NULL; if (GenericAgentCheckPolicy(config, false, false)) { policy = LoadPolicy(ctx, config); } else if (config->tty_interactive) { exit(EXIT_FAILURE); } else { Log(LOG_LEVEL_ERR, "CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe"); EvalContextClassPutHard(ctx, "failsafe_fallback", "attribute_name=Errors,source=agent"); GenericAgentConfigSetInputFile(config, GetInputDir(), "failsafe.cf"); policy = LoadPolicy(ctx, config); } ThisAgentInit(); ExecConfig *exec_config = ExecConfigNew(!ONCE, ctx, policy); ExecdConfig *execd_config = ExecdConfigNew(ctx, policy); SetFacility(execd_config->log_facility); #ifdef __MINGW32__ if (WINSERVICE) { NovaWin_StartExecService(); } else #endif /* __MINGW32__ */ { StartServer(ctx, policy, config, &execd_config, &exec_config); } GenericAgentFinalize(ctx, config); ExecConfigDestroy(exec_config); ExecdConfigDestroy(execd_config); return 0; } /*****************************************************************************/ /* Level 1 */ /*****************************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; char ld_library_path[CF_BUFSIZE]; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_EXECUTOR); while ((c = getopt_long(argc, argv, "dvnKIf:D:N:VxL:hFOV1gMWlC::", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'l': LEGACY_OUTPUT = true; break; case 'f': GenericAgentConfigSetInputFile(config, GetInputDir(), optarg); MINUSF = true; break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case 'K': config->ignore_locks = true; break; case 'D': config->heap_soft = StringSetFromString(optarg, ','); break; case 'N': config->heap_negated = StringSetFromString(optarg, ','); break; case 'I': LogSetGlobalLevel(LOG_LEVEL_INFO); break; case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); NO_FORK = true; // TODO: really? break; case 'n': DONTDO = true; config->ignore_locks = true; break; case 'L': snprintf(ld_library_path, CF_BUFSIZE - 1, "LD_LIBRARY_PATH=%s", optarg); putenv(xstrdup(ld_library_path)); break; case 'W': WINSERVICE = false; break; case 'F': NO_FORK = true; break; case 'O': ONCE = true; NO_FORK = true; break; case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-execd", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-execd", time(NULL), CF_EXECD_SHORT_DESCRIPTION, CF_EXECD_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, true); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'x': Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired."); exit(EXIT_SUCCESS); case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-execd", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_FAILURE); } } if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind)) { Log(LOG_LEVEL_ERR, "Too many arguments"); exit(EXIT_FAILURE); } return config; } /*****************************************************************************/ void ThisAgentInit(void) { umask(077); } /*****************************************************************************/ /* Might be called back from NovaWin_StartExecService */ void StartServer(EvalContext *ctx, Policy *policy, GenericAgentConfig *config, ExecdConfig **execd_config, ExecConfig **exec_config) { pthread_attr_init(&threads_attrs); pthread_attr_setdetachstate(&threads_attrs, PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&threads_attrs, (size_t)2048*1024); Banner("Starting executor"); #ifndef __MINGW32__ if (!ONCE) { /* Kill previous instances of cf-execd if those are still running */ Apoptosis(); } time_t now = time(NULL); if ((!NO_FORK) && (fork() != 0)) { Log(LOG_LEVEL_INFO, "cf-execd starting %.24s", ctime(&now)); _exit(EXIT_SUCCESS); } if (!NO_FORK) { ActAsDaemon(); } #else /* __MINGW32__ */ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #endif WritePID("cf-execd.pid"); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); umask(077); if (ONCE) { LocalExec(*exec_config); CloseLog(); } else { while (!IsPendingTermination()) { if (ScheduleRun(ctx, &policy, config, execd_config, exec_config)) { Log(LOG_LEVEL_VERBOSE, "Sleeping for splaytime %d seconds", (*execd_config)->splay_time); sleep((*execd_config)->splay_time); if (!LocalExecInThread(*exec_config)) { Log(LOG_LEVEL_INFO, "Unable to run agent in thread, falling back to blocking execution"); LocalExec(*exec_config); } } } } PolicyDestroy(policy); } /*****************************************************************************/ static void *LocalExecThread(void *param) { ExecConfig *config = (ExecConfig *)param; LocalExec(config); ExecConfigDestroy(config); return NULL; } static bool LocalExecInThread(const ExecConfig *config) { ExecConfig *thread_config = ExecConfigCopy(config); pthread_t tid; if (pthread_create(&tid, &threads_attrs, LocalExecThread, thread_config) == 0) { return true; } else { ExecConfigDestroy(thread_config); Log(LOG_LEVEL_INFO, "Can't create thread. (pthread_create: %s)", GetErrorStr()); return false; } } #ifndef __MINGW32__ static void Apoptosis(void) { char promiser_buf[CF_SMALLBUF]; snprintf(promiser_buf, sizeof(promiser_buf), "%s/bin/cf-execd", CFWORKDIR); if (LoadProcessTable(&PROCESSTABLE)) { char myuid[PRINTSIZE(unsigned)]; xsnprintf(myuid, sizeof(myuid), "%u", (unsigned) getuid()); Rlist *owners = NULL; RlistPrepend(&owners, myuid, RVAL_TYPE_SCALAR); ProcessSelect process_select = { .owner = owners, .process_result = "process_owner", }; Item *killlist = SelectProcesses(PROCESSTABLE, promiser_buf, process_select, true); RlistDestroy(owners); for (Item *ip = killlist; ip != NULL; ip = ip->next) { pid_t pid = ip->counter; if (pid != getpid() && kill(pid, SIGTERM) < 0) { if (errno == ESRCH) { /* That's ok, process exited voluntarily */ } else { Log(LOG_LEVEL_ERR, "Unable to kill stale cf-execd process pid=%d. (kill: %s)", (int)pid, GetErrorStr()); } } } } DeleteItemList(PROCESSTABLE); Log(LOG_LEVEL_VERBOSE, "Pruning complete"); } #endif typedef enum { RELOAD_ENVIRONMENT, RELOAD_FULL } Reload; static Reload CheckNewPromises(GenericAgentConfig *config) { Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); if (config->agent_specific.daemon.last_validated_at < validated_at) { /* Rereading policies now, so update timestamp. */ config->agent_specific.daemon.last_validated_at = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { return RELOAD_FULL; } else { Log(LOG_LEVEL_INFO, "New promises file contains syntax errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } return RELOAD_ENVIRONMENT; } static bool ScheduleRun(EvalContext *ctx, Policy **policy, GenericAgentConfig *config, ExecdConfig **execd_config, ExecConfig **exec_config) { Log(LOG_LEVEL_VERBOSE, "Sleeping for pulse time %d seconds...", CFPULSETIME); sleep(CFPULSETIME); /* 1 Minute resolution is enough */ /* * FIXME: this logic duplicates the one from cf-serverd.c. Unify ASAP. */ if (CheckNewPromises(config) == RELOAD_FULL) { /* Full reload */ Log(LOG_LEVEL_INFO, "Re-reading promise file '%s'", config->input_file); EvalContextClear(ctx); strcpy(VDOMAIN, "undefined.domain"); PolicyDestroy(*policy); *policy = NULL; { char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); } UpdateLastPolicyUpdateTime(ctx); DetectEnvironment(ctx); EvalContextClassPutHard(ctx, CF_AGENTTYPES[AGENT_TYPE_EXECUTOR], "cfe_internal,source=agent"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); GenericAgentConfigSetBundleSequence(config, NULL); *policy = LoadPolicy(ctx, config); ExecConfigDestroy(*exec_config); ExecdConfigDestroy(*execd_config); *exec_config = ExecConfigNew(!ONCE, ctx, *policy); *execd_config = ExecdConfigNew(ctx, *policy); SetFacility((*execd_config)->log_facility); } else { /* Environment reload */ EvalContextClear(ctx); DetectEnvironment(ctx); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); } { StringSetIterator it = StringSetIteratorInit((*execd_config)->schedule); const char *time_context = NULL; while ((time_context = StringSetIteratorNext(&it))) { if (IsDefinedClass(ctx, time_context)) { Log(LOG_LEVEL_VERBOSE, "Waking up the agent at %s ~ %s", ctime(&CFSTARTTIME), time_context); return true; } } } Log(LOG_LEVEL_VERBOSE, "Nothing to do at %s", ctime(&CFSTARTTIME)); return false; } cfengine-3.6.2/cf-execd/exec-config.c0000644000175100017510000001506712316547775017057 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include // TODO: fix #include static const int THREE_HOURS = 3 * 60 * 60; static char *GetIpAddresses(const EvalContext *ctx) { /* FIXME: correctly handle cases with a lot of IPs assigned to a host */ char ipbuf[CF_MAXVARSIZE] = ""; for (Item *iptr = EvalContextGetIpAddresses(ctx); iptr != NULL; iptr = iptr->next) { if ((SafeStringLength(ipbuf) + SafeStringLength(iptr->name)) < sizeof(ipbuf)) { strcat(ipbuf, iptr->name); strcat(ipbuf, " "); } else { break; } } Chop(ipbuf, sizeof(ipbuf)); return xstrdup(ipbuf); } ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Policy *policy) { ExecConfig *exec_config = xcalloc(1, sizeof(ExecConfig)); exec_config->scheduled_run = scheduled_run; exec_config->exec_command = xstrdup(""); exec_config->agent_expireafter = THREE_HOURS; exec_config->mail_server = xstrdup(""); exec_config->mail_from_address = xstrdup(""); exec_config->mail_to_address = xstrdup(""); exec_config->mail_subject = xstrdup(""); exec_config->mail_max_lines = 30; exec_config->fq_name = xstrdup(VFQNAME); exec_config->ip_address = xstrdup(VIPADDRESS); exec_config->ip_addresses = GetIpAddresses(ctx); Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_executor"); const void *value = EvalContextVariableGet(ctx, ref, NULL); if (!value) { /* FIXME: figure out whether this is reachable */ // TODO: should've been checked before this point. change to programming error Log(LOG_LEVEL_ERR, "Unknown lval '%s' in exec control body", cp->lval); VarRefDestroy(ref); continue; } VarRefDestroy(ref); if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILFROM].lval) == 0) { free(exec_config->mail_from_address); exec_config->mail_from_address = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailfrom '%s'", exec_config->mail_from_address); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILTO].lval) == 0) { free(exec_config->mail_to_address); exec_config->mail_to_address = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailto '%s'", exec_config->mail_to_address); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILSUBJECT].lval) == 0) { free(exec_config->mail_subject); exec_config->mail_subject = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailsubject '%s'", exec_config->mail_subject); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SMTPSERVER].lval) == 0) { free(exec_config->mail_server); exec_config->mail_server = xstrdup(value); Log(LOG_LEVEL_DEBUG, "smtpserver '%s'", exec_config->mail_server); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECCOMMAND].lval) == 0) { free(exec_config->exec_command); exec_config->exec_command = xstrdup(value); Log(LOG_LEVEL_DEBUG, "exec_command '%s'", exec_config->exec_command); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_AGENT_EXPIREAFTER].lval) == 0) { exec_config->agent_expireafter = IntFromString(value); Log(LOG_LEVEL_DEBUG, "agent_expireafter %d", exec_config->agent_expireafter); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILMAXLINES].lval) == 0) { exec_config->mail_max_lines = IntFromString(value); Log(LOG_LEVEL_DEBUG, "maxlines %d", exec_config->mail_max_lines); } } } return exec_config; } ExecConfig *ExecConfigCopy(const ExecConfig *config) { ExecConfig *copy = xcalloc(1, sizeof(ExecConfig)); copy->scheduled_run = config->scheduled_run; copy->exec_command = xstrdup(config->exec_command); copy->agent_expireafter = config->agent_expireafter; copy->mail_server = xstrdup(config->mail_server); copy->mail_from_address = xstrdup(config->mail_from_address); copy->mail_to_address = xstrdup(config->mail_to_address); copy->mail_subject = xstrdup(config->mail_subject); copy->mail_max_lines = config->mail_max_lines; copy->fq_name = xstrdup(config->fq_name); copy->ip_address = xstrdup(config->ip_address); copy->ip_addresses = xstrdup(config->ip_addresses); return copy; } void ExecConfigDestroy(ExecConfig *exec_config) { if (exec_config) { free(exec_config->exec_command); free(exec_config->mail_server); free(exec_config->mail_from_address); free(exec_config->mail_to_address); free(exec_config->mail_subject); free(exec_config->fq_name); free(exec_config->ip_address); free(exec_config->ip_addresses); free(exec_config); } } cfengine-3.6.2/cf-execd/exec-config.h0000644000175100017510000000341012316547775017051 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_EXEC_CONFIG_H #define CFENGINE_EXEC_CONFIG_H #include /* This struct is supposed to be immutable: don't update it, just destroy and create anew */ typedef struct { bool scheduled_run; char *exec_command; int agent_expireafter; char *mail_server; char *mail_from_address; char *mail_to_address; char *mail_subject; int mail_max_lines; /* * Host information. * Might change during policy reload, so copy is retained in each worker. */ char *fq_name; char *ip_address; char *ip_addresses; } ExecConfig; ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Policy *policy); ExecConfig *ExecConfigCopy(const ExecConfig *exec_config); void ExecConfigDestroy(ExecConfig *exec_config); #endif cfengine-3.6.2/cf-execd/execd-config.c0000644000175100017510000001063612316547775017220 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include static double GetSplay(void) { char splay[CF_BUFSIZE]; snprintf(splay, CF_BUFSIZE, "%s+%s+%ju", VFQNAME, VIPADDRESS, (uintmax_t)getuid()); return ((double) StringHash(splay, 0, CF_HASHTABLESIZE)) / CF_HASHTABLESIZE; } ExecdConfig *ExecdConfigNew(const EvalContext *ctx, const Policy *policy) { ExecdConfig *execd_config = xcalloc(1, sizeof(ExecdConfig)); execd_config->schedule = StringSetNew(); StringSetAdd(execd_config->schedule, xstrdup("Min00")); StringSetAdd(execd_config->schedule, xstrdup("Min05")); StringSetAdd(execd_config->schedule, xstrdup("Min10")); StringSetAdd(execd_config->schedule, xstrdup("Min15")); StringSetAdd(execd_config->schedule, xstrdup("Min20")); StringSetAdd(execd_config->schedule, xstrdup("Min25")); StringSetAdd(execd_config->schedule, xstrdup("Min30")); StringSetAdd(execd_config->schedule, xstrdup("Min35")); StringSetAdd(execd_config->schedule, xstrdup("Min40")); StringSetAdd(execd_config->schedule, xstrdup("Min45")); StringSetAdd(execd_config->schedule, xstrdup("Min50")); StringSetAdd(execd_config->schedule, xstrdup("Min55")); execd_config->splay_time = 0; execd_config->log_facility = xstrdup("LOG_USER"); Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_executor"); const void *value = EvalContextVariableGet(ctx, ref, NULL); if (!value) { // TODO: should've been checked before this point. change to programming error Log(LOG_LEVEL_ERR, "Unknown lval '%s' in exec control body", cp->lval); VarRefDestroy(ref); continue; } VarRefDestroy(ref); if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECUTORFACILITY].lval) == 0) { free(execd_config->log_facility); execd_config->log_facility = xstrdup(value); Log(LOG_LEVEL_DEBUG, "executorfacility '%s'", execd_config->log_facility); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SPLAYTIME].lval) == 0) { int time = IntFromString(value); execd_config->splay_time = (int) (time * SECONDS_PER_MINUTE * GetSplay()); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SCHEDULE].lval) == 0) { Log(LOG_LEVEL_DEBUG, "Loading user-defined schedule..."); StringSetClear(execd_config->schedule); for (const Rlist *rp = value; rp; rp = rp->next) { StringSetAdd(execd_config->schedule, xstrdup(RlistScalarValue(rp))); Log(LOG_LEVEL_DEBUG, "Adding '%s'", RlistScalarValue(rp)); } } } } return execd_config; } void ExecdConfigDestroy(ExecdConfig *execd_config) { if (execd_config) { free(execd_config->log_facility); StringSetDestroy(execd_config->schedule); } free(execd_config); } cfengine-3.6.2/cf-execd/cf-execd-runner.c0000664000175100017510000005061612411001073017622 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*******************************************************************/ static const int INF_LINES = -2; /*******************************************************************/ static int CompareResult(const char *filename, const char *prev_file); static void MailResult(const ExecConfig *config, const char *file); static int Dialogue(int sd, const char *s); /******************************************************************************/ # if defined(__MINGW32__) static void *ThreadUniqueName(void) { return pthread_self().p; } # else /* __MINGW32__ */ static void *ThreadUniqueName(void) { return (void *)pthread_self(); } # endif /* __MINGW32__ */ static const char *TwinFilename(void) { #if defined(_WIN32) return "bin-twin/cf-agent.exe"; #else return "bin/cf-twin"; #endif } static const char *AgentFilename(void) { #if defined(_WIN32) return "bin/cf-agent.exe"; #else return "bin/cf-agent"; #endif } static bool TwinExists(void) { char twinfilename[CF_BUFSIZE]; struct stat sb; snprintf(twinfilename, CF_BUFSIZE, "%s/%s", CFWORKDIR, TwinFilename()); MapName(twinfilename); return (stat(twinfilename, &sb) == 0) && (IsExecutable(twinfilename)); } /* Buffer has to be at least CF_BUFSIZE bytes long */ static void ConstructFailsafeCommand(bool scheduled_run, char *buffer) { bool twin_exists = TwinExists(); snprintf(buffer, CF_BUFSIZE, "\"%s/%s\" -f failsafe.cf " "&& \"%s/%s\" -Dfrom_cfexecd%s", CFWORKDIR, twin_exists ? TwinFilename() : AgentFilename(), CFWORKDIR, AgentFilename(), scheduled_run ? ",scheduled_run" : ""); } #ifndef __MINGW32__ #if defined(__hpux) && defined(__GNUC__) #pragma GCC diagnostic ignored "-Wstrict-aliasing" // Avoid spurious HP-UX GCC type-pun warning on FD_SET() macro #endif static bool IsReadReady(int fd, int timeout_sec) { fd_set rset; FD_ZERO(&rset); FD_SET(fd, &rset); struct timeval tv = { .tv_sec = timeout_sec, .tv_usec = 0, }; int ret = select(fd + 1, &rset, NULL, NULL, &tv); if(ret < 0) { Log(LOG_LEVEL_ERR, "IsReadReady: Failed checking for data. (select: %s)", GetErrorStr()); return false; } if(FD_ISSET(fd, &rset)) { return true; } if(ret == 0) // timeout { return false; } // can we get here? Log(LOG_LEVEL_ERR, "IsReadReady: Unknown outcome (ret > 0 but our only fd is not set). (select: %s)", GetErrorStr()); return false; } #if defined(__hpux) && defined(__GNUC__) #pragma GCC diagnostic warning "-Wstrict-aliasing" #endif #endif /* __MINGW32__ */ void LocalExec(const ExecConfig *config) { time_t starttime = time(NULL); void *thread_name = ThreadUniqueName(); { char starttime_str[64]; cf_strtimestamp_local(starttime, starttime_str); if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------"); Log(LOG_LEVEL_VERBOSE, " LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str); Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------"); } else { Log(LOG_LEVEL_VERBOSE, "LocalExec(%sscheduled) at %s", config->scheduled_run ? "" : "not ", starttime_str); } } /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ char cmd[CF_BUFSIZE]; if (strlen(config->exec_command) > 0) { strlcpy(cmd, config->exec_command, CF_BUFSIZE); if (!strstr(cmd, "-Dfrom_cfexecd")) { strcat(cmd, " -Dfrom_cfexecd"); } } else { ConstructFailsafeCommand(config->scheduled_run, cmd); } char esc_command[CF_BUFSIZE]; strlcpy(esc_command, MapName(cmd), CF_BUFSIZE); char filename[CF_BUFSIZE]; { char line[CF_BUFSIZE]; snprintf(line, CF_BUFSIZE, "_%jd_%s", (intmax_t) starttime, CanonifyName(ctime(&starttime))); { char canonified_fq_name[CF_BUFSIZE]; strlcpy(canonified_fq_name, config->fq_name, CF_BUFSIZE); CanonifyNameInPlace(canonified_fq_name); snprintf(filename, CF_BUFSIZE, "%s/outputs/cf_%s_%s_%p", CFWORKDIR, canonified_fq_name, line, thread_name); MapName(filename); } } /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ FILE *fp = fopen(filename, "w"); if (!fp) { Log(LOG_LEVEL_ERR, "Couldn't open '%s' - aborting exec. (fopen: %s)", filename, GetErrorStr()); return; } #if !defined(__MINGW32__) /* * Don't inherit this file descriptor on fork/exec */ if (fileno(fp) != -1) { fcntl(fileno(fp), F_SETFD, FD_CLOEXEC); } #endif Log(LOG_LEVEL_VERBOSE, "Command => %s", cmd); FILE *pp = cf_popen_sh(esc_command, "r"); if (!pp) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", cmd, GetErrorStr()); fclose(fp); return; } Log(LOG_LEVEL_VERBOSE, "Command is executing...%s", esc_command); int count = 0; int complete = false; size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); while (!IsPendingTermination()) { if (!IsReadReady(fileno(pp), (config->agent_expireafter * SECONDS_PER_MINUTE))) { char errmsg[CF_MAXVARSIZE]; snprintf(errmsg, sizeof(errmsg), "cf-execd: !! Timeout waiting for output from agent (agent_expireafter=%d) - terminating it", config->agent_expireafter); Log(LOG_LEVEL_ERR, "%s", errmsg); fprintf(fp, "%s\n", errmsg); count++; pid_t pid_agent; if (PipeToPid(&pid_agent, pp)) { ProcessSignalTerminate(pid_agent); } else { Log(LOG_LEVEL_ERR, "Could not get PID of agent"); } break; } ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (feof(pp)) { complete = true; } else { Log(LOG_LEVEL_ERR, "Unable to read output from command '%s'. (cfread: %s)", cmd, GetErrorStr()); } break; } const char *sp = line; while (*sp != '\0' && isspace(*sp)) { sp++; } if (*sp != '\0') /* line isn't entirely blank */ { char *line_escaped = xmalloc(2 * line_size); ReplaceStr(line, line_escaped, 2 * line_size, "%", "%%"); fprintf(fp, "%s\n", line_escaped); count++; /* If we can't send mail, log to syslog */ if (strlen(config->mail_to_address) == 0) { strncat(line_escaped, "\n", sizeof(line_escaped) - 1 - strlen(line_escaped)); if ((strchr(line_escaped, '\n')) == NULL) { line_escaped[sizeof(line_escaped) - 2] = '\n'; } Log(LOG_LEVEL_INFO, "%s", line_escaped); } line[0] = '\0'; free(line_escaped); } } free(line); cf_pclose(pp); Log(LOG_LEVEL_DEBUG, "Closing fp"); fclose(fp); Log(LOG_LEVEL_VERBOSE, complete ? "Command is complete" : "Terminated command"); if (count) { Log(LOG_LEVEL_VERBOSE, "Mailing result"); MailResult(config, filename); } else { Log(LOG_LEVEL_VERBOSE, "No output"); unlink(filename); } } static int CompareResult(const char *filename, const char *prev_file) { Log(LOG_LEVEL_VERBOSE, "Comparing files %s with %s", prev_file, filename); int rtn = 0; FILE *old_fp = safe_fopen(prev_file, "r"); FILE *new_fp = safe_fopen(filename, "r"); if (old_fp && new_fp) { const char *errptr; int erroffset; pcre_extra *regex_extra = NULL; // Match timestamps and remove them. Not Y21K safe! :-) pcre *regex = pcre_compile(LOGGING_TIMESTAMP_REGEX, PCRE_MULTILINE, &errptr, &erroffset, NULL); if (!regex) { UnexpectedError("Compiling regular expression failed"); rtn = 1; } else { regex_extra = pcre_study(regex, 0, &errptr); } while (regex) { size_t old_line_size = CF_BUFSIZE; char *old_line = xmalloc(old_line_size); char *old_msg = NULL; if (CfReadLine(&old_line, &old_line_size, old_fp) >= 0) { old_msg = old_line; } size_t new_line_size = CF_BUFSIZE; char *new_line = xmalloc(new_line_size); char *new_msg = NULL; if (CfReadLine(&new_line, &new_line_size, new_fp) >= 0) { new_msg = new_line; } if (!old_msg || !new_msg) { if (old_msg != new_msg) { rtn = 1; } free(old_line); free(new_line); break; } char *index; if (pcre_exec(regex, regex_extra, old_msg, strlen(old_msg), 0, 0, NULL, 0) >= 0) { index = strstr(old_msg, ": "); if (index != NULL) { old_msg = index + 2; } } if (pcre_exec(regex, regex_extra, new_msg, strlen(new_msg), 0, 0, NULL, 0) >= 0) { index = strstr(new_msg, ": "); if (index != NULL) { new_msg = index + 2; } } if (strcmp(old_msg, new_msg) != 0) { rtn = 1; free(old_line); free(new_line); break; } free(old_line); free(new_line); } if (regex_extra) { free(regex_extra); } pcre_free(regex); } else { /* no previous file */ rtn = 1; } if (old_fp) { fclose(old_fp); } if (new_fp) { fclose(new_fp); } if (!ThreadLock(cft_count)) { Log(LOG_LEVEL_ERR, "Severe lock error when mailing in exec"); return 1; } /* replace old file with new*/ unlink(prev_file); if (!LinkOrCopy(filename, prev_file, true)) { Log(LOG_LEVEL_INFO, "Could not symlink or copy '%s' to '%s'", filename, prev_file); rtn = 1; } ThreadUnlock(cft_count); return rtn; } static void MailResult(const ExecConfig *config, const char *file) { #if defined __linux__ || defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__ time_t now = time(NULL); #endif Log(LOG_LEVEL_VERBOSE, "Mail result..."); { struct stat statbuf; if (stat(file, &statbuf) == -1) { return; } if (statbuf.st_size == 0) { unlink(file); Log(LOG_LEVEL_DEBUG, "Nothing to report in file '%s'", file); return; } } { char prev_file[CF_BUFSIZE]; snprintf(prev_file, CF_BUFSIZE - 1, "%s/outputs/previous", CFWORKDIR); MapName(prev_file); if (CompareResult(file, prev_file) == 0) { Log(LOG_LEVEL_VERBOSE, "Previous output is the same as current so do not mail it"); return; } } if ((strlen(config->mail_server) == 0) || (strlen(config->mail_to_address) == 0)) { /* Syslog should have done this */ Log(LOG_LEVEL_VERBOSE, "Empty mail server or address - skipping"); return; } if (config->mail_max_lines == 0) { Log(LOG_LEVEL_DEBUG, "Not mailing: EmailMaxLines was zero"); return; } Log(LOG_LEVEL_DEBUG, "Mailing results of '%s' to '%s'", file, config->mail_to_address); /* Check first for anomalies - for subject header */ FILE *fp = fopen(file, "r"); if (!fp) { Log(LOG_LEVEL_INFO, "Couldn't open file '%s'. (fopen: %s)", file, GetErrorStr()); return; } bool anomaly = false; char vbuff[CF_BUFSIZE]; while (!feof(fp)) { vbuff[0] = '\0'; if (fgets(vbuff, sizeof(vbuff), fp) == NULL) { break; } if (strstr(vbuff, "entropy")) { anomaly = true; break; } } fclose(fp); if ((fp = fopen(file, "r")) == NULL) { Log(LOG_LEVEL_INFO, "Couldn't open file '%s'. (fopen: %s)", file, GetErrorStr()); return; } struct hostent *hp = gethostbyname(config->mail_server); if (!hp) { Log(LOG_LEVEL_ERR, "While mailing agent output, unknown host '%s'. Make sure that fully qualified names can be looked up at your site.", config->mail_server); fclose(fp); return; } struct servent *server = getservbyname("smtp", "tcp"); if (!server) { Log(LOG_LEVEL_INFO, "Unable to lookup smtp service. (getservbyname: %s)", GetErrorStr()); fclose(fp); return; } struct sockaddr_in raddr; memset(&raddr, 0, sizeof(raddr)); raddr.sin_port = (unsigned int) server->s_port; raddr.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; raddr.sin_family = AF_INET; Log(LOG_LEVEL_DEBUG, "Connecting..."); int sd = socket(AF_INET, SOCK_STREAM, 0); if (sd == -1) { Log(LOG_LEVEL_INFO, "Couldn't open a socket. (socket: %s)", GetErrorStr()); fclose(fp); return; } if (connect(sd, (void *) &raddr, sizeof(raddr)) == -1) { Log(LOG_LEVEL_INFO, "Couldn't connect to host '%s'. (connect: %s)", config->mail_server, GetErrorStr()); fclose(fp); cf_closesocket(sd); return; } /* read greeting */ if (!Dialogue(sd, NULL)) { goto mail_err; } snprintf(vbuff, sizeof(vbuff), "HELO %s\r\n", config->fq_name); Log(LOG_LEVEL_DEBUG, "%s", vbuff); if (!Dialogue(sd, vbuff)) { goto mail_err; } if (strlen(config->mail_from_address) == 0) { snprintf(vbuff, sizeof(vbuff), "MAIL FROM: \r\n", config->fq_name); Log(LOG_LEVEL_DEBUG, "%s", vbuff); } else { snprintf(vbuff, sizeof(vbuff), "MAIL FROM: <%s>\r\n", config->mail_from_address); Log(LOG_LEVEL_DEBUG, "%s", vbuff); } if (!Dialogue(sd, vbuff)) { goto mail_err; } snprintf(vbuff, sizeof(vbuff), "RCPT TO: <%s>\r\n", config->mail_to_address); Log(LOG_LEVEL_DEBUG, "%s", vbuff); if (!Dialogue(sd, vbuff)) { goto mail_err; } if (!Dialogue(sd, "DATA\r\n")) { goto mail_err; } char mailsubject_anomaly_prefix[8]; if (anomaly) { strcpy(mailsubject_anomaly_prefix, "**!! "); } else { mailsubject_anomaly_prefix[0] = '\0'; } if (SafeStringLength(config->mail_subject) == 0) { snprintf(vbuff, sizeof(vbuff), "Subject: %s[%s/%s]\r\n", mailsubject_anomaly_prefix, config->fq_name, config->ip_address); Log(LOG_LEVEL_DEBUG, "%s", vbuff); } else { snprintf(vbuff, sizeof(vbuff), "Subject: %s%s\r\n", mailsubject_anomaly_prefix, config->mail_subject); Log(LOG_LEVEL_DEBUG, "%s", vbuff); } send(sd, vbuff, strlen(vbuff), 0); /* send X-CFEngine SMTP header if mailsubject set */ if (SafeStringLength(config->mail_subject) > 0) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; char buffer[CF_HOSTKEY_STRING_SIZE]; char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); snprintf(vbuff, sizeof(vbuff), "X-CFEngine: vfqhost=\"%s\";ip-addresses=\"%s\";policyhub=\"%s\";pkhash=\"%s\"\r\n", VFQNAME, config->ip_addresses, existing_policy_server, HashPrintSafe(buffer, sizeof(buffer), digest, CF_DEFAULT_DIGEST, true)); send(sd, vbuff, strlen(vbuff), 0); free(existing_policy_server); } #if defined __linux__ || defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__ strftime(vbuff, CF_BUFSIZE, "Date: %a, %d %b %Y %H:%M:%S %z\r\n", localtime(&now)); send(sd, vbuff, strlen(vbuff), 0); #endif if (strlen(config->mail_from_address) == 0) { snprintf(vbuff, sizeof(vbuff), "From: cfengine@%s\r\n", config->fq_name); Log(LOG_LEVEL_DEBUG, "%s", vbuff); } else { snprintf(vbuff, sizeof(vbuff), "From: %s\r\n", config->mail_from_address); Log(LOG_LEVEL_DEBUG, "%s", vbuff); } send(sd, vbuff, strlen(vbuff), 0); snprintf(vbuff, sizeof(vbuff), "To: %s\r\n\r\n", config->mail_to_address); Log(LOG_LEVEL_DEBUG, "%s", vbuff); send(sd, vbuff, strlen(vbuff), 0); int count = 0; while (!feof(fp)) { vbuff[0] = '\0'; if (fgets(vbuff, sizeof(vbuff), fp) == NULL) { break; } Log(LOG_LEVEL_DEBUG, "%s", vbuff); if (strlen(vbuff) > 0) { vbuff[strlen(vbuff) - 1] = '\r'; strcat(vbuff, "\n"); count++; send(sd, vbuff, strlen(vbuff), 0); } if ((config->mail_max_lines != INF_LINES) && (count > config->mail_max_lines)) { snprintf(vbuff, sizeof(vbuff), "\r\n[Mail truncated by cfengine. File is at %s on %s]\r\n", file, config->fq_name); send(sd, vbuff, strlen(vbuff), 0); break; } } if (!Dialogue(sd, ".\r\n")) { Log(LOG_LEVEL_DEBUG, "mail_err\n"); goto mail_err; } Dialogue(sd, "QUIT\r\n"); Log(LOG_LEVEL_DEBUG, "Done sending mail"); fclose(fp); cf_closesocket(sd); return; mail_err: fclose(fp); cf_closesocket(sd); Log(LOG_LEVEL_INFO, "Cannot mail to %s.", config->mail_to_address); } static int Dialogue(int sd, const char *s) { if ((s != NULL) && (*s != '\0')) { int sent = send(sd, s, strlen(s), 0); Log(LOG_LEVEL_DEBUG, "SENT(%d) -> '%s'", sent, s); } else { Log(LOG_LEVEL_DEBUG, "Nothing to send .. waiting for opening"); } int charpos = 0; int rfclinetype = ' '; char ch, f = '\0'; while (recv(sd, &ch, 1, 0)) { charpos++; if (f == '\0') { f = ch; } if (charpos == 4) /* Multiline RFC in form 222-Message with hyphen at pos 4 */ { rfclinetype = ch; } if ((ch == '\n') || (ch == '\0')) { charpos = 0; if (rfclinetype == ' ') { break; } } } return ((f == '2') || (f == '3')); /* return code 200 or 300 from smtp */ } cfengine-3.6.2/cf-execd/Makefile.in0000664000175100017510000006346212412324463016555 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-execd$(EXEEXT) subdir = cf-execd DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcf_execd_la_DEPENDENCIES = ../libpromises/libpromises.la am_libcf_execd_la_OBJECTS = cf-execd.lo cf-execd-runner.lo \ exec-config.lo execd-config.lo libcf_execd_la_OBJECTS = $(am_libcf_execd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) cf_execd_SOURCES = cf-execd.c cf_execd_OBJECTS = cf_execd-cf-execd.$(OBJEXT) @BUILTIN_EXTENSIONS_FALSE@cf_execd_DEPENDENCIES = libcf-execd.la cf_execd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(cf_execd_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_execd_la_SOURCES) cf-execd.c DIST_SOURCES = $(libcf_execd_la_SOURCES) cf-execd.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-execd.la AM_CPPFLAGS = \ $(OPENSSL_CPPFLAGS) \ -I$(srcdir)/../libpromises \ -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_execd_la_LIBADD = ../libpromises/libpromises.la libcf_execd_la_SOURCES = \ cf-execd.c cf-execd.h \ cf-execd-runner.c cf-execd-runner.h \ exec-config.c exec-config.h \ execd-config.c execd-config.h @BUILTIN_EXTENSIONS_FALSE@cf_execd_CFLAGS = $(AM_CFLAGS) @BUILTIN_EXTENSIONS_FALSE@cf_execd_LDADD = libcf-execd.la CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-execd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-execd/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-execd.la: $(libcf_execd_la_OBJECTS) $(libcf_execd_la_DEPENDENCIES) $(EXTRA_libcf_execd_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_execd_la_OBJECTS) $(libcf_execd_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-execd$(EXEEXT): $(cf_execd_OBJECTS) $(cf_execd_DEPENDENCIES) $(EXTRA_cf_execd_DEPENDENCIES) @rm -f cf-execd$(EXEEXT) $(AM_V_CCLD)$(cf_execd_LINK) $(cf_execd_OBJECTS) $(cf_execd_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-execd-runner.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-execd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_execd-cf-execd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec-config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execd-config.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< cf_execd-cf-execd.o: cf-execd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_execd_CFLAGS) $(CFLAGS) -MT cf_execd-cf-execd.o -MD -MP -MF $(DEPDIR)/cf_execd-cf-execd.Tpo -c -o cf_execd-cf-execd.o `test -f 'cf-execd.c' || echo '$(srcdir)/'`cf-execd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_execd-cf-execd.Tpo $(DEPDIR)/cf_execd-cf-execd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-execd.c' object='cf_execd-cf-execd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_execd_CFLAGS) $(CFLAGS) -c -o cf_execd-cf-execd.o `test -f 'cf-execd.c' || echo '$(srcdir)/'`cf-execd.c cf_execd-cf-execd.obj: cf-execd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_execd_CFLAGS) $(CFLAGS) -MT cf_execd-cf-execd.obj -MD -MP -MF $(DEPDIR)/cf_execd-cf-execd.Tpo -c -o cf_execd-cf-execd.obj `if test -f 'cf-execd.c'; then $(CYGPATH_W) 'cf-execd.c'; else $(CYGPATH_W) '$(srcdir)/cf-execd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_execd-cf-execd.Tpo $(DEPDIR)/cf_execd-cf-execd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-execd.c' object='cf_execd-cf-execd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_execd_CFLAGS) $(CFLAGS) -c -o cf_execd-cf-execd.obj `if test -f 'cf-execd.c'; then $(CYGPATH_W) 'cf-execd.c'; else $(CYGPATH_W) '$(srcdir)/cf-execd.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS @BUILTIN_EXTENSIONS_FALSE@ # Workaround for automake madness (try removing it if you want to know why). # 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: cfengine-3.6.2/cf-execd/Makefile.am0000664000175100017510000000145612411001073016523 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-execd.la AM_CPPFLAGS = \ $(OPENSSL_CPPFLAGS) \ -I$(srcdir)/../libpromises \ -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_execd_la_LIBADD = ../libpromises/libpromises.la libcf_execd_la_SOURCES = \ cf-execd.c cf-execd.h \ cf-execd-runner.c cf-execd-runner.h \ exec-config.c exec-config.h \ execd-config.c execd-config.h if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-execd # Workaround for automake madness (try removing it if you want to know why). cf_execd_CFLAGS = $(AM_CFLAGS) cf_execd_LDADD = libcf-execd.la endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/cf-execd/execd-config.h0000644000175100017510000000263712316547775017227 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_EXECD_CONFIG_H #define CFENGINE_EXECD_CONFIG_H #include #include /* This struct is supposed to be immutable: don't update it, just destroy and create anew */ typedef struct ExecdConfig { StringSet *schedule; int splay_time; char *log_facility; } ExecdConfig; ExecdConfig *ExecdConfigNew(const EvalContext *ctx, const Policy *policy); void ExecdConfigDestroy(ExecdConfig *exec_config); #endif cfengine-3.6.2/cf-execd/cf-execd.h0000644000175100017510000000242012316547775016340 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CF_EXECD_H #define CF_EXECD_H #include #include #include #include #include void StartServer(EvalContext *ctx, Policy *policy, GenericAgentConfig *config, ExecdConfig **execd_config, ExecConfig **exec_config); #endif cfengine-3.6.2/cf-execd/cf-execd-runner.h0000664000175100017510000000216212243421446017635 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF_EXECD_RUNNER_H #define CFENGINE_CF_EXECD_RUNNER_H #include void LocalExec(const ExecConfig *config); #endif cfengine-3.6.2/config.guess0000755000175100017510000013036112403654565015352 0ustar00a10038a1003800000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-06-10' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfengine-3.6.2/README.md0000664000175100017510000000255212411001073014266 0ustar00a10038a1003800000000000000# CFEngine 3 CFEngine 3 is a popular open source configuration management system. Its primary function is to provide automated configuration and maintenance of large-scale computer systems. ## Installation Please see the [INSTALL](https://github.com/cfengine/core/blob/master/INSTALL) file for prerequisites and build instructions. ## License As per the [LICENSE](https://github.com/cfengine/core/blob/master/LICENSE) file, CFEngine Community is licensed under the Gnu General Public License GPL, version 3. ## Example Usage ### Hello World The following code demonstrates simple CFEngine output through a reports promise. body common control { bundlesequence => { "run" }; } bundle agent run { reports: cfengine:: "Hello, world"; } The following policy code may be executed with cf-agent (the main CFEngine binary) as follows. $ cf-agent/cf-agent hello.cf R: Hello, world ## Contributing Please see the [HACKING.md](https://github.com/cfengine/core/blob/master/HACKING.md) file. ## Relationship to CFEngine 2 CFEngine 3 is *not* a drop-in upgrade for CFEngine 2 installations. It is a significantly more powerful version, but it is incompatible with the CFEngine 2 policy language. The server part of CFEngine 3 supports the network protocol of CFEngine 2, so you may upgrade your installation gradually. cfengine-3.6.2/cf-key/0000775000175100017510000000000012413020723014166 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-key/cf-key-functions.h0000664000175100017510000000350412400110676017530 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CFKEYFUNCTIONS_H #define CFENGINE_CFKEYFUNCTIONS_H #include #include #include #include #include #include #include #include #include #include #include RSA* LoadPublicKey(const char* filename); char* GetPubkeyDigest(const char* pubkey); int PrintDigest(const char* pubkey); int TrustKey(const char* pubkey); bool ShowHost(const char *hostkey, const char *address, bool incoming, const KeyHostSeen *quality, void *ctx); void ShowLastSeenHosts(); int RemoveKeys(const char *input, bool must_be_coherent); void KeepKeyPromises(const char *public_key_file, const char *private_key_file); int ForceKeyRemoval(const char *key); int ForceIpAddressRemoval(const char *ip); #endif // CFKEYFUNCTIONS_H cfengine-3.6.2/cf-key/Makefile.in0000664000175100017510000005642212412324463016253 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-key$(EXEEXT) subdir = cf-key DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcf_key_la_DEPENDENCIES = ../libpromises/libpromises.la am_libcf_key_la_OBJECTS = cf-key.lo cf-key-functions.lo libcf_key_la_OBJECTS = $(am_libcf_key_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_cf_key_OBJECTS = cf_key_OBJECTS = $(am_cf_key_OBJECTS) @BUILTIN_EXTENSIONS_FALSE@cf_key_DEPENDENCIES = libcf-key.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_key_la_SOURCES) $(cf_key_SOURCES) DIST_SOURCES = $(libcf_key_la_SOURCES) $(cf_key_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-key.la AM_CPPFLAGS = \ $(OPENSSL_CPPFLAGS) \ -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libpromises \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_key_la_SOURCES = \ cf-key.c \ cf-key-functions.c cf-key-functions.h libcf_key_la_LIBADD = ../libpromises/libpromises.la @BUILTIN_EXTENSIONS_FALSE@cf_key_LDADD = libcf-key.la @BUILTIN_EXTENSIONS_FALSE@cf_key_SOURCES = CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-key/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-key/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-key.la: $(libcf_key_la_OBJECTS) $(libcf_key_la_DEPENDENCIES) $(EXTRA_libcf_key_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_key_la_OBJECTS) $(libcf_key_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-key$(EXEEXT): $(cf_key_OBJECTS) $(cf_key_DEPENDENCIES) $(EXTRA_cf_key_DEPENDENCIES) @rm -f cf-key$(EXEEXT) $(AM_V_CCLD)$(LINK) $(cf_key_OBJECTS) $(cf_key_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-key-functions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-key.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/cf-key/Makefile.am0000664000175100017510000000107212411001073016215 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-key.la AM_CPPFLAGS = \ $(OPENSSL_CPPFLAGS) \ -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libpromises \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_key_la_SOURCES = \ cf-key.c \ cf-key-functions.c cf-key-functions.h libcf_key_la_LIBADD = ../libpromises/libpromises.la if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-key cf_key_LDADD = libcf-key.la cf_key_SOURCES = endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/cf-key/cf-key.c0000664000175100017510000002115112400110676015513 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int SHOWHOSTS = false; /* GLOBAL_A */ bool FORCEREMOVAL = false; /* GLOBAL_A */ bool REMOVEKEYS = false; /* GLOBAL_A */ bool LICENSE_INSTALL = false; /* GLOBAL_A */ char LICENSE_SOURCE[MAX_FILENAME] = ""; /* GLOBAL_A */ const char *remove_keys_host = NULL; /* GLOBAL_A */ static char *print_digest_arg = NULL; /* GLOBAL_A */ static char *trust_key_arg = NULL; /* GLOBAL_A */ static char *KEY_PATH = NULL; /* GLOBAL_A */ static GenericAgentConfig *CheckOpts(int argc, char **argv); /*******************************************************************/ /* Command line options */ /*******************************************************************/ static const char *const CF_KEY_SHORT_DESCRIPTION = "make private/public key-pairs for CFEngine authentication"; static const char *const CF_KEY_MANPAGE_LONG_DESCRIPTION = "The CFEngine key generator makes key pairs for remote authentication.\n"; static const struct option OPTIONS[] = { {"help", no_argument, 0, 'h'}, {"debug", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"output-file", required_argument, 0, 'f'}, {"show-hosts", no_argument, 0, 's'}, {"remove-keys", required_argument, 0, 'r'}, {"force-removal", no_argument, 0, 'x'}, {"install-license", required_argument, 0, 'l'}, {"print-digest", required_argument, 0, 'p'}, {"trust-key", required_argument, 0, 't'}, {"color", optional_argument, 0, 'C'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { "Print the help message", "Enable debugging output", "Output verbose information about the behaviour of the agent", "Output the version of the software", "Specify an alternative output file than the default (localhost)", "Show lastseen hostnames and IP addresses", "Remove keys for specified hostname/IP", "Force removal of keys (USE AT YOUR OWN RISK)", "Install license file on Enterprise server (CFEngine Enterprise Only)", "Print digest of the specified public key", "Make cf-serverd/cf-agent trust the specified public key", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", NULL }; /*****************************************************************************/ typedef void (*CfKeySigHandler)(int signum); bool cf_key_interrupted = false; static void handleShowKeysSignal(int signum) { cf_key_interrupted = true; signal(signum, handleShowKeysSignal); } static void ThisAgentInit(CfKeySigHandler sighandler) { signal(SIGINT, sighandler); signal(SIGTERM, sighandler); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForAgent); signal(SIGUSR2, HandleSignalsForAgent); } int main(int argc, char *argv[]) { GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); if (SHOWHOSTS) { ThisAgentInit(handleShowKeysSignal); ShowLastSeenHosts(); return 0; } if (print_digest_arg) { return PrintDigest(print_digest_arg); } ThisAgentInit(HandleSignalsForAgent); if (REMOVEKEYS) { int status; if (FORCEREMOVAL) { if (!strncmp(remove_keys_host, "SHA=", 3) || !strncmp(remove_keys_host, "MD5=", 3)) { status = ForceKeyRemoval(remove_keys_host); } else { status = ForceIpAddressRemoval(remove_keys_host); } } else { status = RemoveKeys(remove_keys_host, true); if (status == 0 || status == 1) { Log (LOG_LEVEL_VERBOSE, "Forced removal of entry '%s' was successful", remove_keys_host); return 0; } } return status; } if(LICENSE_INSTALL) { bool success = LicenseInstall(LICENSE_SOURCE); return success ? 0 : 1; } if (trust_key_arg) { return TrustKey(trust_key_arg); } char *public_key_file, *private_key_file; if (KEY_PATH) { xasprintf(&public_key_file, "%s.pub", KEY_PATH); xasprintf(&private_key_file, "%s.priv", KEY_PATH); } else { public_key_file = PublicKeyFile(GetWorkDir()); private_key_file = PrivateKeyFile(GetWorkDir()); } KeepKeyPromises(public_key_file, private_key_file); free(public_key_file); free(private_key_file); GenericAgentFinalize(ctx, config); return 0; } /*****************************************************************************/ /* Level */ /*****************************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_KEYGEN); while ((c = getopt_long(argc, argv, "dvf:VMp:sr:xt:hl:C::", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'f': KEY_PATH = optarg; break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); break; case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); break; case 'p': /* print digest */ print_digest_arg = optarg; break; case 's': SHOWHOSTS = true; break; case 'x': FORCEREMOVAL = true; break; case 'r': REMOVEKEYS = true; remove_keys_host = optarg; break; case 'l': LICENSE_INSTALL = true; strlcpy(LICENSE_SOURCE, optarg, sizeof(LICENSE_SOURCE)); break; case 't': trust_key_arg = optarg; break; case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-key", OPTIONS, HINTS, false); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-key", time(NULL), CF_KEY_SHORT_DESCRIPTION, CF_KEY_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, false); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-key", OPTIONS, HINTS, false); FileWriterDetach(w); } exit(EXIT_FAILURE); } } return config; } cfengine-3.6.2/cf-key/cf-key-functions.c0000664000175100017510000003170112400110676017523 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* BN_*, BIGNUM */ #include /* RAND_* */ #include #include #include #include #include #include #include #include #include #include #include static const char *const passphrase = "Cfengine passphrase"; RSA* LoadPublicKey(const char* filename) { FILE* fp; RSA* key; fp = safe_fopen(filename, "r"); if (fp == NULL) { Log(LOG_LEVEL_ERR, "Cannot open file '%s'. (fopen: %s)", filename, GetErrorStr()); return NULL; }; if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL, (void *)passphrase)) == NULL) { Log(LOG_LEVEL_ERR, "Error reading public key. (PEM_read_RSAPublicKey: %s)", CryptoLastErrorString()); fclose(fp); return NULL; }; fclose(fp); if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) { Log(LOG_LEVEL_ERR, "RSA Exponent in key '%s' too small or not odd. (BN_num_bits: %s)", filename, GetErrorStr()); return NULL; }; return key; } /** Return a string with the printed digest of the given key file, or NULL if an error occurred. */ char* GetPubkeyDigest(const char* pubkey) { unsigned char digest[EVP_MAX_MD_SIZE + 1]; RSA* key = NULL; char* buffer = xmalloc(CF_HOSTKEY_STRING_SIZE); key = LoadPublicKey(pubkey); if (NULL == key) { return NULL; } HashPubKey(key, digest, CF_DEFAULT_DIGEST); HashPrintSafe(buffer, CF_HOSTKEY_STRING_SIZE, digest, CF_DEFAULT_DIGEST, true); return buffer; } /*****************************************************************************/ /** Print digest of the specified public key file. Return 0 on success and 1 on error. */ int PrintDigest(const char* pubkey) { char *digeststr = GetPubkeyDigest(pubkey); if (NULL == digeststr) { return 1; /* ERROR exitcode */ } fprintf(stdout, "%s\n", digeststr); free(digeststr); return 0; /* OK exitcode */ } int TrustKey(const char* pubkey) { char *digeststr = GetPubkeyDigest(pubkey); char outfilename[CF_BUFSIZE]; bool ok; if (NULL == digeststr) return 1; /* ERROR exitcode */ snprintf(outfilename, CF_BUFSIZE, "%s/ppkeys/root-%s.pub", CFWORKDIR, digeststr); free(digeststr); ok = CopyRegularFileDisk(pubkey, outfilename); return (ok? 0 : 1); } extern bool cf_key_interrupted; bool ShowHost(const char *hostkey, const char *address, bool incoming, const KeyHostSeen *quality, void *ctx) { int *count = ctx; char timebuf[26]; char hostname[MAXHOSTNAMELEN]; int ret = IPString2Hostname(hostname, address, sizeof(hostname)); (*count)++; printf("%-10.10s %-40.40s %-25.25s %-26.26s %-s\n", incoming ? "Incoming" : "Outgoing", address, (ret != -1) ? hostname : "-", cf_strtimestamp_local(quality->lastseen, timebuf), hostkey); return !cf_key_interrupted; } void ShowLastSeenHosts() { int count = 0; printf("%-10.10s %-40.40s %-25.25s %-26.26s %-s\n", "Direction", "IP", "Name", "Last connection", "Key"); if (!ScanLastSeenQuality(ShowHost, &count)) { Log(LOG_LEVEL_ERR, "Unable to show lastseen database"); return; } printf("Total Entries: %d\n", count); } /** * @brief removes all traces of entry 'input' from lastseen and filesystem * * @param[in] key digest (SHA/MD5 format) or free host name string * @param[in] must_be_coherent. false : delete if lastseen is incoherent, * true : don't if lastseen is incoherent * @retval 0 if entry was deleted, >0 otherwise */ int RemoveKeys(const char *input, bool must_be_coherent) { int res = 0; char equivalent[CF_BUFSIZE]; equivalent[0] = '\0'; res = RemoveKeysFromLastSeen(input, must_be_coherent, equivalent); if (res!=0) { return res; } Log(LOG_LEVEL_INFO, "Removed corresponding entries from lastseen database."); int removed_input = RemovePublicKey(input); int removed_equivalent = RemovePublicKey(equivalent); if ((removed_input == -1) || (removed_equivalent == -1)) { Log(LOG_LEVEL_ERR, "Unable to remove keys for the entry %s", input); return 255; } else if (removed_input + removed_equivalent == 0) { Log(LOG_LEVEL_ERR, "No key file(s) for entry %s were found on the filesytem", input); return 1; } else { Log(LOG_LEVEL_INFO, "Removed %d corresponding key file(s) from filesystem.", removed_input + removed_equivalent); return 0; } return -1; } void KeepKeyPromises(const char *public_key_file, const char *private_key_file) { #ifdef OPENSSL_NO_DEPRECATED RSA *pair = RSA_new(); BIGNUM *rsa_bignum = BN_new(); #else RSA *pair; #endif FILE *fp; struct stat statbuf; int fd; const EVP_CIPHER *cipher; char vbuff[CF_BUFSIZE]; cipher = EVP_des_ede3_cbc(); if (stat(public_key_file, &statbuf) != -1) { printf("A key file already exists at %s\n", public_key_file); return; } if (stat(private_key_file, &statbuf) != -1) { printf("A key file already exists at %s\n", private_key_file); return; } printf("Making a key pair for cfengine, please wait, this could take a minute...\n"); #ifdef OPENSSL_NO_DEPRECATED BN_set_word(rsa_bignum, 35); if (!RSA_generate_key_ex(pair, 2048, rsa_bignum, NULL)) #else pair = RSA_generate_key(2048, 35, NULL, NULL); if (pair == NULL) #endif { Log(LOG_LEVEL_ERR, "Unable to generate key (RSA_generate_key: %s)", CryptoLastErrorString()); return; } fd = safe_open(private_key_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { Log(LOG_LEVEL_ERR, "Open '%s' failed. (open: %s)", private_key_file, GetErrorStr()); return; } if ((fp = fdopen(fd, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open private key '%s'. (fdopen: %s)", private_key_file, GetErrorStr()); close(fd); return; } Log(LOG_LEVEL_VERBOSE, "Writing private key to '%s'", private_key_file); if (!PEM_write_RSAPrivateKey(fp, pair, cipher, (void *)passphrase, strlen(passphrase), NULL, NULL)) { Log(LOG_LEVEL_ERR, "Couldn't write private key. (PEM_write_RSAPrivateKey: %s)", CryptoLastErrorString()); return; } fclose(fp); fd = safe_open(public_key_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { Log(LOG_LEVEL_ERR, "Unable to open public key '%s'. (open: %s)", public_key_file, GetErrorStr()); return; } if ((fp = fdopen(fd, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Open '%s' failed. (fdopen: %s)", public_key_file, GetErrorStr()); close(fd); return; } Log(LOG_LEVEL_VERBOSE, "Writing public key to file '%s'", public_key_file); if (!PEM_write_RSAPublicKey(fp, pair)) { Log(LOG_LEVEL_ERR, "Unable to write public key. (PEM_write_RSAPublicKey: %s)", CryptoLastErrorString()); return; } fclose(fp); snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR); RAND_write_file(vbuff); chmod(vbuff, 0644); } ENTERPRISE_FUNC_1ARG_DEFINE_STUB(bool, LicenseInstall, ARG_UNUSED char *, path_source) { Log(LOG_LEVEL_ERR, "License installation only applies to CFEngine Enterprise"); return false; } int ForceKeyRemoval(const char *hash) { /** Removal of a key hash is made of two passes : Pass #1 (read-only) -> fetches the IP addresses directly linked to the hash key Pass #2 (made of deletes) -> remove all the IP addresses in the previous list -> remove the physical key.pub from the filesystem WARNING: Please backup your lastseen database before calling this function in the case where a 1-to-1 relatioship between the IP and a single keyhash does not exist **/ CF_DB *dbp; CF_DBC *dbcp; char *key; void *value; int ksize, vsize; Seq *hostips = SeqNew(100, free); if (OpenDB(&dbp, dbid_lastseen)) { if (NewDBCursor(dbp, &dbcp)) { while (NextDB(dbcp, &key, &ksize, &value, &vsize)) { if ((key[0] != 'a') || (value == NULL)) { continue; } if (!strncmp(hash, value, strlen(hash))) { SeqAppend(hostips, xstrdup(key + 1)); } } DeleteDBCursor(dbcp); } CloseDB(dbp); } if (OpenDB(&dbp, dbid_lastseen)) { char tmp[CF_BUFSIZE]; snprintf(tmp, CF_BUFSIZE, "k%s", hash); char vtmp[CF_BUFSIZE]; if (!ReadDB(dbp, tmp, &vtmp, sizeof(vtmp))) { Log(LOG_LEVEL_ERR, "Failed to read the main hash key entry '%s'. Will continue to purge other entries related to it.", hash); } else { SeqAppend(hostips, xstrdup(vtmp + 1)); } snprintf(tmp, CF_BUFSIZE, "k%s", hash); DeleteDB(dbp, tmp); snprintf(tmp, CF_BUFSIZE, "qi%s", hash); DeleteDB(dbp, tmp); snprintf(tmp, CF_BUFSIZE, "qo%s", hash); DeleteDB(dbp, tmp); RemovePublicKey(hash); for (int i = 0; i < SeqLength(hostips); ++i) { const char *myip = SeqAt(hostips, i); snprintf(tmp, CF_BUFSIZE, "a%s", myip); DeleteDB(dbp, tmp); } CloseDB(dbp); } SeqDestroy(hostips); return 0; } int ForceIpAddressRemoval(const char *ip) { /** Removal of an ip is made of two passes : Pass #1 (read-only) -> fetches the key hashes directly linked to the ip address Pass #2 (made of deletes) -> remove all the key hashes in the previous list -> remove the physical key hashes .pub files from the filesystem WARNING: Please backup your lastseen database before calling this function in the case where a 1-to-1 relatioship between the IP and a single keyhash does not exist **/ CF_DB *dbp; CF_DBC *dbcp; char *key; void *value; int ksize, vsize; Seq *hostkeys = SeqNew(100, free); if (OpenDB(&dbp, dbid_lastseen)) { if (NewDBCursor(dbp, &dbcp)) { while (NextDB(dbcp, &key, &ksize, &value, &vsize)) { if ((key[0] != 'k') || (value == NULL)) { continue; } if (!strncmp(ip, value, strlen(ip))) { SeqAppend(hostkeys, xstrdup(key + 1)); } } DeleteDBCursor(dbcp); } CloseDB(dbp); } if (OpenDB(&dbp, dbid_lastseen)) { char tmp[CF_BUFSIZE]; snprintf(tmp, CF_BUFSIZE, "a%s", ip); char vtmp[CF_BUFSIZE]; if (!ReadDB(dbp, tmp, &vtmp, sizeof(vtmp))) { Log(LOG_LEVEL_ERR, "Failed to read the main ip address entry '%s'. Will continue to purge other entries related to it.", ip); } else { SeqAppend(hostkeys, xstrdup(vtmp + 1)); } snprintf(tmp, CF_BUFSIZE, "a%s", ip); DeleteDB(dbp, tmp); for (int i = 0; i < SeqLength(hostkeys); ++i) { const char *myk = SeqAt(hostkeys, i); snprintf(tmp, CF_BUFSIZE, "k%s", myk); DeleteDB(dbp, tmp); snprintf(tmp, CF_BUFSIZE, "qi%s", myk); DeleteDB(dbp, tmp); snprintf(tmp, CF_BUFSIZE, "qo%s", myk); DeleteDB(dbp, tmp); RemovePublicKey(myk); } CloseDB(dbp); } SeqDestroy(hostkeys); return 0; } cfengine-3.6.2/libenv/0000775000175100017510000000000012413020722014266 5ustar00a10038a1003800000000000000cfengine-3.6.2/libenv/zones.h0000664000175100017510000000234512400110676015605 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ZONES_H #define CFENGINE_ZONES_H #include #ifndef __MINGW32__ bool IsGlobalZone(); bool ForeignZone(char *s); int CurrentZoneName(const char *s);/* s must point to at least ZONENAME_MAX bytes of space */ #endif #endif // ZONES_H cfengine-3.6.2/libenv/unix_iface.h0000664000175100017510000000231412400110676016555 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_UNIX_IFACE_H #define CFENGINE_UNIX_IFACE_H #include /* TODO libpromises depends on libenv, the opposite should not happen! */ #include void GetInterfacesInfo(EvalContext *ctx); #endif cfengine-3.6.2/libenv/unix_iface.c0000664000175100017510000006306512411001073016552 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include /* StringMatchFull */ #ifdef HAVE_SYS_JAIL_H # include #endif #ifdef HAVE_GETIFADDRS # include # ifdef HAVE_NET_IF_DL_H # include # endif #endif #define CF_IFREQ 2048 /* Reportedly the largest size that does not segfault 32/64 bit */ #define CF_IGNORE_INTERFACES "ignore_interfaces.rx" #ifndef __MINGW32__ # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN # ifdef _SIZEOF_ADDR_IFREQ # define SIZEOF_IFREQ(x) _SIZEOF_ADDR_IFREQ(x) # else # define SIZEOF_IFREQ(x) \ ((x).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ (x).ifr_addr.sa_len) : sizeof(struct ifreq)) # endif # else # define SIZEOF_IFREQ(x) sizeof(struct ifreq) # endif #ifdef _AIX #include #include static int aix_get_mac_addr(const char *device_name, uint8_t mac[6]); #endif #if defined (__sun) && !defined(HAVE_GETIFADDRS) #include #endif static void FindV6InterfacesInfo(EvalContext *ctx); static bool IgnoreJailInterface(int ifaceidx, struct sockaddr_in *inaddr); static bool IgnoreInterface(char *name); static void InitIgnoreInterfaces(void); static Rlist *IGNORE_INTERFACES = NULL; /* GLOBAL_E */ /*********************************************************************/ /******************************************************************/ static bool IgnoreJailInterface( #if !defined(HAVE_JAIL_GET) ARG_UNUSED int ifaceidx, ARG_UNUSED struct sockaddr_in *inaddr #else int ifaceidx, struct sockaddr_in *inaddr #endif ) { /* FreeBSD jails */ # ifdef HAVE_JAIL_GET struct iovec fbsd_jparams[4]; struct in_addr fbsd_jia; int fbsd_lastjid = 0; *(const void **) &fbsd_jparams[0].iov_base = "lastjid"; fbsd_jparams[0].iov_len = sizeof("lastjid"); fbsd_jparams[1].iov_base = &fbsd_lastjid; fbsd_jparams[1].iov_len = sizeof(fbsd_lastjid); *(const void **) &fbsd_jparams[2].iov_base = "ip4.addr"; fbsd_jparams[2].iov_len = sizeof("ip4.addr"); fbsd_jparams[3].iov_len = sizeof(struct in_addr); fbsd_jparams[3].iov_base = &fbsd_jia; while ((fbsd_lastjid = jail_get(fbsd_jparams, 4, 0)) > 0) { if (fbsd_jia.s_addr == inaddr->sin_addr.s_addr) { Log(LOG_LEVEL_VERBOSE, "Interface %d belongs to a FreeBSD jail %s", ifaceidx, inet_ntoa(fbsd_jia)); return true; } } # endif return false; } /******************************************************************/ static void GetMacAddress(EvalContext *ctx, int fd, struct ifreq *ifr, struct ifreq *ifp, Rlist **interfaces, Rlist **hardware) { char name[CF_MAXVARSIZE]; snprintf(name, sizeof(name), "hardware_mac[%s]", CanonifyName(ifp->ifr_name)); // mac address on a loopback interface doesn't make sense if (ifr->ifr_flags & IFF_LOOPBACK) { return; } # if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR) char hw_mac[CF_MAXVARSIZE]; if ((ioctl(fd, SIOCGIFHWADDR, ifr) == -1)) { Log(LOG_LEVEL_ERR, "Couldn't get mac address for '%s' interface. (ioctl: %s)", ifr->ifr_name, GetErrorStr()); return; } snprintf(hw_mac, sizeof(hw_mac), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned char) ifr->ifr_hwaddr.sa_data[0], (unsigned char) ifr->ifr_hwaddr.sa_data[1], (unsigned char) ifr->ifr_hwaddr.sa_data[2], (unsigned char) ifr->ifr_hwaddr.sa_data[3], (unsigned char) ifr->ifr_hwaddr.sa_data[4], (unsigned char) ifr->ifr_hwaddr.sa_data[5]); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, hw_mac, CF_DATA_TYPE_STRING, "source=agent"); RlistAppend(hardware, hw_mac, RVAL_TYPE_SCALAR); RlistAppend(interfaces, ifp->ifr_name, RVAL_TYPE_SCALAR); snprintf(name, sizeof(name), "mac_%s", CanonifyName(hw_mac)); EvalContextClassPutHard(ctx, name, "inventory,attribute_name=none,source=agent"); # elif defined(HAVE_GETIFADDRS) char hw_mac[CF_MAXVARSIZE]; char *m; struct ifaddrs *ifaddr, *ifa; struct sockaddr_dl *sdl; if (getifaddrs(&ifaddr) == -1) { Log(LOG_LEVEL_ERR, "!! Could not get interface %s addresses", ifp->ifr_name); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, "mac_unknown", CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, "mac_unknown", "source=agent"); return; } for (ifa = ifaddr; ifa != NULL; ifa=ifa->ifa_next) { if ( strcmp(ifa->ifa_name, ifp->ifr_name) == 0) { if (ifa->ifa_addr->sa_family == AF_LINK) { sdl = (struct sockaddr_dl *)ifa->ifa_addr; m = (char *) LLADDR(sdl); snprintf(hw_mac, sizeof(hw_mac), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned char) m[0], (unsigned char) m[1], (unsigned char) m[2], (unsigned char) m[3], (unsigned char) m[4], (unsigned char) m[5]); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, hw_mac, CF_DATA_TYPE_STRING, "source=agent"); RlistAppend(hardware, hw_mac, RVAL_TYPE_SCALAR); RlistAppend(interfaces, ifa->ifa_name, RVAL_TYPE_SCALAR); snprintf(name, sizeof(name), "mac_%s", CanonifyName(hw_mac)); EvalContextClassPutHard(ctx, name, "source=agent"); } } } freeifaddrs(ifaddr); # elif defined(_AIX) && !defined(HAVE_GETIFADDRS) char hw_mac[CF_MAXVARSIZE]; char mac[CF_MAXVARSIZE]; if (aix_get_mac_addr(ifp->ifr_name, mac) == 0) { sprintf(hw_mac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, hw_mac, CF_DATA_TYPE_STRING, "source=agent"); RlistAppend(hardware, hw_mac, RVAL_TYPE_SCALAR); RlistAppend(interfaces, ifp->ifr_name, RVAL_TYPE_SCALAR); snprintf(name, CF_MAXVARSIZE, "mac_%s", CanonifyName(hw_mac)); EvalContextClassPutHard(ctx, name, "inventory,attribute_name=none,source=agent"); } else { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, "mac_unknown", CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, "mac_unknown", "source=agent"); } # elif defined(__sun) && !defined(HAVE_GETIFADDRS) char hw_mac[CF_MAXVARSIZE]; struct ifaddrs *ifaddr, *ifa; struct sockaddr_dl *sdl; if (solaris_getifaddrs(&ifaddr) == -1) { Log(LOG_LEVEL_ERR, "!! Could not get interface %s addresses (getifaddrs)", ifp->ifr_name); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, "mac_unknown", CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, "mac_unknown", "source=agent"); return; } for (ifa = ifaddr; ifa != NULL; ifa=ifa->ifa_next) { struct sockaddr * saddr = ifaddr->ifa_addr; snprintf(hw_mac, sizeof(hw_mac), "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", (unsigned char) saddr->sa_data[0], (unsigned char) saddr->sa_data[1], (unsigned char) saddr->sa_data[2], (unsigned char) saddr->sa_data[3], (unsigned char) saddr->sa_data[4], (unsigned char) saddr->sa_data[5]); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, hw_mac, CF_DATA_TYPE_STRING, "source=agent"); RlistAppend(hardware, hw_mac, RVAL_TYPE_SCALAR); RlistAppend(interfaces, ifa->ifa_name, RVAL_TYPE_SCALAR); snprintf(name, sizeof(name), "mac_%s", CanonifyName(hw_mac)); EvalContextClassPutHard(ctx, name, "inventory,attribute_name=none,source=agent"); } solaris_freeifaddrs(ifaddr); # else EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, "mac_unknown", CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, "mac_unknown", "source=agent"); # endif } /******************************************************************/ static void GetInterfaceFlags(EvalContext *ctx, struct ifreq *ifr, Rlist **flags) { char name[CF_MAXVARSIZE]; char buffer[CF_BUFSIZE] = ""; char *fp = NULL; snprintf(name, sizeof(name), "interface_flags[%s]", ifr->ifr_name); if (ifr->ifr_flags & IFF_UP) strcat(buffer, " up"); if (ifr->ifr_flags & IFF_BROADCAST) strcat(buffer, " broadcast"); if (ifr->ifr_flags & IFF_DEBUG) strcat(buffer, " debug"); if (ifr->ifr_flags & IFF_LOOPBACK) strcat(buffer, " loopback"); if (ifr->ifr_flags & IFF_POINTOPOINT) strcat(buffer, " pointopoint"); #ifdef IFF_NOTRAILERS if (ifr->ifr_flags & IFF_NOTRAILERS) strcat(buffer, " notrailers"); #endif if (ifr->ifr_flags & IFF_RUNNING) strcat(buffer, " running"); if (ifr->ifr_flags & IFF_NOARP) strcat(buffer, " noarp"); if (ifr->ifr_flags & IFF_PROMISC) strcat(buffer, " promisc"); if (ifr->ifr_flags & IFF_ALLMULTI) strcat(buffer, " allmulti"); if (ifr->ifr_flags & IFF_MULTICAST) strcat(buffer, " multicast"); // If a least 1 flag is found if (strlen(buffer) > 1) { // Skip leading space fp = buffer + 1; EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, fp, CF_DATA_TYPE_STRING, "source=agent"); RlistAppend(flags, fp, RVAL_TYPE_SCALAR); } } /******************************************************************/ void GetInterfacesInfo(EvalContext *ctx) { bool address_set = false; int fd, len, i, j; struct ifreq ifbuf[CF_IFREQ], ifr, *ifp; struct ifconf list; struct sockaddr_in *sin; struct hostent *hp; char *sp, workbuf[CF_BUFSIZE]; char ip[CF_MAXVARSIZE]; char name[CF_MAXVARSIZE]; Rlist *interfaces = NULL, *hardware = NULL, *flags = NULL, *ips = NULL; /* This function may be called many times, while interfaces come and go */ /* TODO cache results for non-daemon processes? */ EvalContextDeleteIpAddresses(ctx); memset(ifbuf, 0, sizeof(ifbuf)); InitIgnoreInterfaces(); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { Log(LOG_LEVEL_ERR, "Couldn't open socket. (socket: %s)", GetErrorStr()); exit(EXIT_FAILURE); } list.ifc_len = sizeof(ifbuf); list.ifc_req = ifbuf; /* WARNING: *BSD use unsigned long as second argument to ioctl() while * POSIX specifies *signed* int. Using the largest possible signed type is * the best strategy.*/ #ifdef SIOCGIFCONF intmax_t request = SIOCGIFCONF; #else intmax_t request = OSIOCGIFCONF; #endif int ret = ioctl(fd, request, &list); if (ret == -1) { Log(LOG_LEVEL_ERR, "Couldn't get interfaces (ioctl(SIOCGIFCONF): %s)", GetErrorStr()); exit(EXIT_FAILURE); } if (list.ifc_len < (int) sizeof(struct ifreq)) { Log(LOG_LEVEL_VERBOSE, "Interface list returned is too small (%d bytes), " "assuming no interfaces present", list.ifc_len); list.ifc_len = 0; } char last_name[sizeof(ifp->ifr_name)] = ""; for (j = 0, len = 0, ifp = list.ifc_req; len < list.ifc_len; len += SIZEOF_IFREQ(*ifp), j++, ifp = (struct ifreq *) ((char *) ifp + SIZEOF_IFREQ(*ifp))) { if (ifp->ifr_addr.sa_family == 0) { continue; } if ((ifp->ifr_name == NULL) || (strlen(ifp->ifr_name) == 0)) { continue; } /* Skip virtual network interfaces for Linux, which seems to be a problem */ if (IgnoreInterface(ifp->ifr_name)) { continue; } if (strstr(ifp->ifr_name, ":")) { #ifdef __linux__ Log(LOG_LEVEL_VERBOSE, "Skipping apparent virtual interface %d: %s", j + 1, ifp->ifr_name); continue; #endif } else { Log(LOG_LEVEL_VERBOSE, "Interface %d: %s", j + 1, ifp->ifr_name); } /* If interface name appears a second time in a row then it has more than one IP addresses (linux: ip addr add $IP dev $IF). But the variable is already added so don't set it again. */ if (strcmp(last_name, ifp->ifr_name) != 0) { strcpy(last_name, ifp->ifr_name); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "interface", last_name, CF_DATA_TYPE_STRING, "source=agent"); } snprintf(workbuf, sizeof(workbuf), "net_iface_%s", CanonifyName(ifp->ifr_name)); EvalContextClassPutHard(ctx, workbuf, "source=agent"); /* TODO IPv6 should be handled transparently */ if (ifp->ifr_addr.sa_family == AF_INET) { strlcpy(ifr.ifr_name, ifp->ifr_name, sizeof(ifp->ifr_name)); if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) { Log(LOG_LEVEL_ERR, "No such network device. (ioctl: %s)", GetErrorStr()); continue; } else { GetInterfaceFlags(ctx, &ifr, &flags); } if (ifr.ifr_flags & IFF_UP) { sin = (struct sockaddr_in *) &ifp->ifr_addr; if (IgnoreJailInterface(j + 1, sin)) { Log(LOG_LEVEL_VERBOSE, "Ignoring interface %d", j + 1); continue; } /* No DNS lookup, just convert IP address to string. */ char txtaddr[CF_MAX_IP_LEN] = ""; assert(sizeof(VIPADDRESS) >= sizeof(txtaddr)); getnameinfo((struct sockaddr *) sin, sizeof(*sin), txtaddr, sizeof(txtaddr), NULL, 0, NI_NUMERICHOST); Log(LOG_LEVEL_DEBUG, "Adding hostip '%s'", txtaddr); EvalContextClassPutHard(ctx, txtaddr, "inventory,attribute_name=none,source=agent"); if ((hp = gethostbyaddr((char *) &(sin->sin_addr.s_addr), sizeof(sin->sin_addr.s_addr), AF_INET)) == NULL) { Log(LOG_LEVEL_DEBUG, "No hostinformation for '%s' found", txtaddr); } else { if (hp->h_name != NULL) { Log(LOG_LEVEL_DEBUG, "Adding hostname '%s'", hp->h_name); EvalContextClassPutHard(ctx, hp->h_name, "inventory,attribute_name=none,source=agent"); if (hp->h_aliases != NULL) { for (i = 0; hp->h_aliases[i] != NULL; i++) { Log(LOG_LEVEL_DEBUG, "Adding alias '%s'", hp->h_aliases[i]); EvalContextClassPutHard(ctx, hp->h_aliases[i], "inventory,attribute_name=none,source=agent"); } } } } if (strcmp(txtaddr, "0.0.0.0") == 0) { /* TODO remove, interface address can't be 0.0.0.0 and * even then DNS is not a safe way to set a variable... */ Log(LOG_LEVEL_VERBOSE, "Cannot discover hardware IP, using DNS value"); assert(sizeof(ip) >= sizeof(VIPADDRESS) + sizeof("ipv4_")); strcpy(ip, "ipv4_"); strcat(ip, VIPADDRESS); EvalContextAddIpAddress(ctx, VIPADDRESS); RlistAppendScalar(&ips, VIPADDRESS); for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; EvalContextClassPutHard(ctx, ip, "inventory,attribute_name=none,source=agent"); } } strcpy(ip, VIPADDRESS); i = 3; for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; snprintf(name, sizeof(name), "ipv4_%d[%s]", i--, CanonifyName(VIPADDRESS)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, ip, CF_DATA_TYPE_STRING, "source=agent"); } } continue; } assert(sizeof(ip) >= sizeof(txtaddr) + sizeof("ipv4_")); strcpy(ip, "ipv4_"); strcat(ip, txtaddr); EvalContextClassPutHard(ctx, ip, "inventory,attribute_name=none,source=agent"); /* VIPADDRESS has already been set to the DNS address of * VFQNAME by GetNameInfo3() during initialisation. Here we * reset VIPADDRESS to the address of the first non-loopback * interface. */ if (!address_set && !(ifr.ifr_flags & IFF_LOOPBACK)) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "ipv4", txtaddr, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=none"); strcpy(VIPADDRESS, txtaddr); Log(LOG_LEVEL_VERBOSE, "IP address of host set to %s", VIPADDRESS); address_set = true; } EvalContextAddIpAddress(ctx, txtaddr); RlistAppendScalar(&ips, txtaddr); for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; EvalContextClassPutHard(ctx, ip, "inventory,attribute_name=none,source=agent"); } } // Set the IPv4 on interface array strcpy(ip, txtaddr); snprintf(name, sizeof(name), "ipv4[%s]", CanonifyName(ifp->ifr_name)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, ip, CF_DATA_TYPE_STRING, "source=agent"); i = 3; for (sp = ip + strlen(ip) - 1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; snprintf(name, sizeof(name), "ipv4_%d[%s]", i--, CanonifyName(ifp->ifr_name)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, name, ip, CF_DATA_TYPE_STRING, "source=agent"); } } } // Set the hardware/mac address array GetMacAddress(ctx, fd, &ifr, ifp, &interfaces, &hardware); } } close(fd); if (interfaces) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "interfaces", interfaces, CF_DATA_TYPE_STRING_LIST, "inventory,source=agent,attribute_name=Interfaces"); } if (hardware) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "hardware_addresses", hardware, CF_DATA_TYPE_STRING_LIST, "inventory,source=agent,attribute_name=MAC addresses"); } if (flags) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "hardware_flags", flags, CF_DATA_TYPE_STRING_LIST, "source=agent"); } if (ips) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "ip_addresses", ips, CF_DATA_TYPE_STRING_LIST, "inventory,source=agent,attribute_name=IPv4 addresses"); } RlistDestroy(interfaces); RlistDestroy(hardware); RlistDestroy(flags); RlistDestroy(ips); FindV6InterfacesInfo(ctx); } /*******************************************************************/ static void FindV6InterfacesInfo(EvalContext *ctx) { FILE *pp = NULL; char buffer[CF_BUFSIZE]; /* Whatever the manuals might say, you cannot get IPV6 interface configuration from the ioctls. This seems to be implemented in a non standard way across OSes BSDi has done getifaddrs(), solaris 8 has a new ioctl, Stevens book shows the suggestion which has not been implemented... */ Log(LOG_LEVEL_VERBOSE, "Trying to locate my IPv6 address"); #if defined(__CYGWIN__) /* NT cannot do this */ return; #elif defined(__hpux) if ((pp = cf_popen("/usr/sbin/ifconfig -a", "r", true)) == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find interface info"); return; } #elif defined(_AIX) if ((pp = cf_popen("/etc/ifconfig -a", "r", true)) == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find interface info"); return; } #else if ((pp = cf_popen("/sbin/ifconfig -a", "r", true)) == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find interface info"); return; } #endif /* Don't know the output format of ifconfig on all these .. hope for the best*/ for(;;) { if (fgets(buffer, sizeof(buffer), pp) == NULL) { if (ferror(pp)) { UnexpectedError("Failed to read line from stream"); break; } else /* feof */ { break; } } if (strcasestr(buffer, "inet6")) { Item *ip, *list = NULL; char *sp; list = SplitStringAsItemList(buffer, ' '); for (ip = list; ip != NULL; ip = ip->next) { for (sp = ip->name; *sp != '\0'; sp++) { if (*sp == '/') /* Remove CIDR mask */ { *sp = '\0'; } } if ((IsIPV6Address(ip->name)) && ((strcmp(ip->name, "::1") != 0))) { Log(LOG_LEVEL_VERBOSE, "Found IPv6 address %s", ip->name); EvalContextAddIpAddress(ctx, ip->name); EvalContextClassPutHard(ctx, ip->name, "inventory,attribute_name=none,source=agent"); } } DeleteItemList(list); } } cf_pclose(pp); } /*******************************************************************/ static void InitIgnoreInterfaces() { FILE *fin; char filename[CF_BUFSIZE],regex[CF_MAXVARSIZE]; snprintf(filename, sizeof(filename), "%s%cinputs%c%s", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, CF_IGNORE_INTERFACES); if ((fin = fopen(filename,"r")) == NULL) { Log(LOG_LEVEL_VERBOSE, "No interface exception file %s",filename); return; } while (!feof(fin)) { regex[0] = '\0'; int scanCount = fscanf(fin,"%s",regex); if (scanCount != 0 && *regex != '\0') { RlistPrependScalarIdemp(&IGNORE_INTERFACES, regex); } } fclose(fin); } /*******************************************************************/ static bool IgnoreInterface(char *name) { Rlist *rp; for (rp = IGNORE_INTERFACES; rp != NULL; rp=rp->next) { /* FIXME: review this strcmp. Moved out from StringMatch */ if (!strcmp(RlistScalarValue(rp), name) || StringMatchFull(RlistScalarValue(rp), name)) { Log(LOG_LEVEL_VERBOSE, "Ignoring interface '%s' because it matches '%s'",name,CF_IGNORE_INTERFACES); return true; } } return false; } #ifdef _AIX static int aix_get_mac_addr(const char *device_name, uint8_t mac[6]) { size_t ksize; struct kinfo_ndd *ndd; int count, i; ksize = getkerninfo(KINFO_NDD, 0, 0, 0); if (ksize == 0) { errno = ENOSYS; return -1; } ndd = (struct kinfo_ndd *)xmalloc(ksize); if (ndd == NULL) { errno = ENOMEM; return -1; } if (getkerninfo(KINFO_NDD, ndd, &ksize, 0) == -1) { errno = ENOSYS; return -1; } count= ksize/sizeof(struct kinfo_ndd); for (i=0;i /* TODO libpromises depends on libenv, the opposite should not happen! */ #include void LoadSystemConstants(EvalContext *ctx); #endif cfengine-3.6.2/libenv/sysinfo.c0000664000175100017510000027013412411001073016127 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* StringMatchFull */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ZONE_H # include #endif // HP-UX mpctl() for $(sys.cpus) on HP-UX - Mantis #1069 #ifdef HAVE_SYS_MPCTL_H # include #endif /* Linux. WARNING keep this before the #include because of glibc bug: https://sourceware.org/bugzilla/show_bug.cgi?id=140 */ #ifdef HAVE_STRUCT_SYSINFO_UPTIME # include #endif /* BSD, MAC OS X uptime calculation use KERN_BOOTTIME sysctl. */ #ifdef HAVE_SYS_SYSCTL_H # ifdef HAVE_SYS_PARAM_H # include # endif # include #endif /*****************************************************/ // Uptime calculation settings for GetUptimeSeconds() - Mantis #1134 /* Listed here in priority order, i.e. first come the platform-specific * ways. If nothing works, one of the last, most generic ways should. */ #ifndef __MINGW32__ /* Windows is implemented in Enterprise */ // HP-UX: pstat_getproc(2) on init (pid 1) #if defined(__hpux) # define _PSTAT64 # include # include # define BOOT_TIME_WITH_PSTAT_GETPROC // Solaris: kstat() for kernel statistics // See http://dsc.sun.com/solaris/articles/kstatc.html // BSD also has a kstat.h (albeit in sys), so check __sun just to be paranoid /** * @WARNING: Commented out because inside a Solaris 10 zone this gives the * uptime of the host machine (the hypervisor). We thus choose to * use UTMP for Solaris. */ /* #elif defined(__sun) && defined(HAVE_KSTAT_H) # include # define BOOT_TIME_WITH_KSTAT */ // BSD: sysctl(3) to get kern.boottime, CPU count, etc. // See http://www.unix.com/man-page/FreeBSD/3/sysctl/ // Linux also has sys/sysctl.h, so we check KERN_BOOTTIME to make sure it's BSD #elif defined(HAVE_SYS_SYSCTL_H) && defined(KERN_BOOTTIME) # define BOOT_TIME_WITH_SYSCTL // GNU/Linux: struct sysinfo.uptime #elif defined(HAVE_STRUCT_SYSINFO_UPTIME) # define BOOT_TIME_WITH_SYSINFO /* Generic System V way, available in most platforms. */ #elif defined(HAVE_UTMP_H) # include # define BOOT_TIME_WITH_UTMP /* POSIX alternative (utmp.h does not exist on BSDs). */ #elif defined(HAVE_UTMPX_H) # include # define BOOT_TIME_WITH_UTMPX #else // Most generic way: {stat("/proc/1")}.st_ctime // TODO in Solaris zones init is not guaranteed to be PID 1! #define BOOT_TIME_WITH_PROCFS #endif /* Fallback uptime calculation: Parse the "uptime" command in case the * platform-specific way fails or returns absurd number. */ static time_t GetBootTimeFromUptimeCommand(time_t now); #endif /* ifndef __MINGW32__ */ /*****************************************************/ void CalculateDomainName(const char *nodename, const char *dnsname, char *fqname, char *uqname, char *domain); #ifdef __linux__ static int Linux_Fedora_Version(EvalContext *ctx); static int Linux_Redhat_Version(EvalContext *ctx); static void Linux_Oracle_VM_Server_Version(EvalContext *ctx); static void Linux_Oracle_Version(EvalContext *ctx); static int Linux_Suse_Version(EvalContext *ctx); static int Linux_Slackware_Version(EvalContext *ctx, char *filename); static int Linux_Debian_Version(EvalContext *ctx); static int Linux_Mandrake_Version(EvalContext *ctx); static int Linux_Mandriva_Version(EvalContext *ctx); static int Linux_Mandriva_Version_Real(EvalContext *ctx, char *filename, char *relstring, char *vendor); static int VM_Version(EvalContext *ctx); static int Xen_Domain(EvalContext *ctx); static int EOS_Version(EvalContext *ctx); static int MiscOS(EvalContext *ctx); static void OpenVZ_Detect(EvalContext *ctx); #ifdef XEN_CPUID_SUPPORT static void Xen_Cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); static int Xen_Hv_Check(void); #endif static bool ReadLine(const char *filename, char *buf, int bufsize); static FILE *ReadFirstLine(const char *filename, char *buf, int bufsize); #endif static void GetCPUInfo(EvalContext *ctx); static const char *const CLASSATTRIBUTES[][3] = { [PLATFORM_CONTEXT_UNKNOWN] = {"-", "-", "-"}, /* as appear here are matched. The fields are sysname and machine */ [PLATFORM_CONTEXT_OPENVZ] = {"virt_host_vz_vzps", ".*", ".*"}, /* VZ with vzps */ [PLATFORM_CONTEXT_HP] = {"hp-ux", ".*", ".*"}, /* hpux */ [PLATFORM_CONTEXT_AIX] = {"aix", ".*", ".*"}, /* aix */ [PLATFORM_CONTEXT_LINUX] = {"linux", ".*", ".*"}, /* linux */ [PLATFORM_CONTEXT_SOLARIS] = {"sunos", ".*", "5\\.1[1-9].*"}, /* new solaris, SunOS >= 5.11 */ [PLATFORM_CONTEXT_SUN_SOLARIS] = {"sunos", ".*", "5\\.([2-9]|10)(\\..*)?"}, /* old solaris, SunOS < 5.11 */ [PLATFORM_CONTEXT_FREEBSD] = {"freebsd", ".*", ".*"}, /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = {"netbsd", ".*", ".*"}, /* NetBSD */ [PLATFORM_CONTEXT_CRAYOS] = {"sn.*", "cray*", ".*"}, /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = {"cygwin_nt.*", ".*", ".*"}, /* NT (cygwin) */ [PLATFORM_CONTEXT_SYSTEMV] = {"unix_sv", ".*", ".*"}, /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = {"openbsd", ".*", ".*"}, /* OpenBSD */ [PLATFORM_CONTEXT_CFSCO] = {"sco_sv", ".*", ".*"}, /* SCO */ [PLATFORM_CONTEXT_DARWIN] = {"darwin", ".*", ".*"}, /* Darwin, aka MacOS X */ [PLATFORM_CONTEXT_QNX] = {"qnx", ".*", ".*"}, /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = {"dragonfly", ".*", ".*"}, /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = {"windows_nt.*", ".*", ".*"}, /* NT (native) */ [PLATFORM_CONTEXT_VMWARE] = {"vmkernel", ".*", ".*"}, /* VMWARE / ESX */ [PLATFORM_CONTEXT_ANDROID] = {"android", ".*", ".*"}, /* android: Warning uname returns linux */ }; static const char *const VRESOLVCONF[] = { [PLATFORM_CONTEXT_UNKNOWN] = "-", [PLATFORM_CONTEXT_OPENVZ] = "/etc/resolv.conf", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/etc/resolv.conf", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/etc/resolv.conf", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/etc/resolv.conf", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/etc/resolv.conf", /* new solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/etc/resolv.conf", /* old solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/etc/resolv.conf", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/etc/resolv.conf", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/etc/resolv.conf", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/etc/resolv.conf", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "/etc/resolv.conf", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/etc/resolv.conf", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/etc/resolv.conf", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/etc/resolv.conf", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/etc/resolv.conf", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/etc/resolv.conf", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/etc/resolv.conf", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "", /* android */ }; static const char *const VMAILDIR[] = { [PLATFORM_CONTEXT_UNKNOWN] = "-", [PLATFORM_CONTEXT_OPENVZ] = "/var/spool/mail", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/var/mail", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/var/spool/mail", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/var/spool/mail", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/var/mail", /* new solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/var/mail", /* old solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/var/mail", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/var/mail", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/usr/mail", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "N/A", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "/var/mail", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/var/mail", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/var/spool/mail", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/var/mail", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/var/spool/mail", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/var/mail", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/var/spool/mail", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "", /* android */ }; static const char *const VEXPORTS[] = { [PLATFORM_CONTEXT_UNKNOWN] = "-", [PLATFORM_CONTEXT_OPENVZ] = "/etc/exports", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/etc/exports", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/etc/exports", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/etc/exports", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/etc/dfs/dfstab", /* new solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/etc/dfs/dfstab", /* old solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/etc/exports", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/etc/exports", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/etc/exports", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/etc/exports", /* NT */ [PLATFORM_CONTEXT_SYSTEMV] = "/etc/dfs/dfstab", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/etc/exports", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/etc/dfs/dfstab", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/etc/exports", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/etc/exports", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/etc/exports", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "none", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "" , /* android */ }; /*******************************************************************/ void CalculateDomainName(const char *nodename, const char *dnsname, char *fqname, char *uqname, char *domain) { if (strstr(dnsname, ".")) { strlcpy(fqname, dnsname, CF_BUFSIZE); } else { strlcpy(fqname, nodename, CF_BUFSIZE); } if ((strncmp(nodename, fqname, strlen(nodename)) == 0) && (fqname[strlen(nodename)] == '.')) { /* If hostname is not qualified */ strcpy(domain, fqname + strlen(nodename) + 1); strcpy(uqname, nodename); } else { /* If hostname is qualified */ char *p = strchr(nodename, '.'); if (p != NULL) { strlcpy(uqname, nodename, MIN(CF_BUFSIZE, p - nodename + 1)); strlcpy(domain, p + 1, CF_BUFSIZE); } else { strcpy(uqname, nodename); strcpy(domain, ""); } } } /*******************************************************************/ void DetectDomainName(EvalContext *ctx, const char *orig_nodename) { char nodename[CF_BUFSIZE]; strcpy(nodename, orig_nodename); ToLowerStrInplace(nodename); char dnsname[CF_BUFSIZE] = ""; char fqn[CF_BUFSIZE]; if (gethostname(fqn, sizeof(fqn)) != -1) { struct hostent *hp; if ((hp = gethostbyname(fqn))) { strlcpy(dnsname, hp->h_name, CF_MAXVARSIZE); ToLowerStrInplace(dnsname); } } CalculateDomainName(nodename, dnsname, VFQNAME, VUQNAME, VDOMAIN); /* * VFQNAME = a.b.c.d -> * NewClass("a.b.c.d") * NewClass("b.c.d") * NewClass("c.d") * NewClass("d") */ char *ptr = VFQNAME; do { EvalContextClassPutHard(ctx, ptr, "inventory,attribute_name=none,source=agent,derived-from=sys.fqhost"); ptr = strchr(ptr, '.'); if (ptr != NULL) ptr++; } while (ptr != NULL); EvalContextClassPutHard(ctx, VUQNAME, "source=agent,derived-from=sys.uqhost"); EvalContextClassPutHard(ctx, VDOMAIN, "source=agent,derived-from=sys.domain"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "host", nodename, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=none"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "uqhost", VUQNAME, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=none"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fqhost", VFQNAME, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=Host name"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "domain", VDOMAIN, CF_DATA_TYPE_STRING, "source=agent"); } /*******************************************************************/ void DiscoverVersion(EvalContext *ctx) { int major = 0; int minor = 0; int patch = 0; if (3 == sscanf(Version(), "%d.%d.%d", &major, &minor, &patch)) { char workbuf[CF_BUFSIZE]; snprintf(workbuf, CF_MAXVARSIZE, "%d", major); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version_major", workbuf, CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_MAXVARSIZE, "%d", minor); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version_minor", workbuf, CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_MAXVARSIZE, "%d", patch); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version_patch", workbuf, CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_BUFSIZE, "%s%cinputs%clib%c%d.%d", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, FILE_SEPARATOR, major, minor); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "libdir", workbuf, CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_BUFSIZE, "lib%c%d.%d", FILE_SEPARATOR, major, minor); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "local_libdir", workbuf, CF_DATA_TYPE_STRING, "source=agent"); } else { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version_major", "BAD VERSION " VERSION, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version_minor", "BAD VERSION " VERSION, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version_patch", "BAD VERSION " VERSION, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "libdir", CFWORKDIR, CF_DATA_TYPE_STRING, "source=agent"); } } static void GetNameInfo3(EvalContext *ctx) { int i, found = false; char *sp, workbuf[CF_BUFSIZE]; time_t tloc; struct hostent *hp; struct sockaddr_in cin; unsigned char digest[EVP_MAX_MD_SIZE + 1]; #ifdef _AIX char real_version[_SYS_NMLN]; #endif #if defined(HAVE_SYSINFO) && (defined(SI_ARCHITECTURE) || defined(SI_PLATFORM)) long sz; #endif #define COMPONENTS_SIZE 13 char *components[COMPONENTS_SIZE] = { "cf-twin", "cf-agent", "cf-serverd", "cf-monitord", "cf-know", "cf-report", "cf-key", "cf-runagent", "cf-execd", "cf-hub", "cf-promises", "cf-upgrade", NULL }; int have_component[COMPONENTS_SIZE]; struct stat sb; char name[CF_MAXVARSIZE], quoteName[CF_MAXVARSIZE], shortname[CF_MAXVARSIZE]; if (uname(&VSYSNAME) == -1) { Log(LOG_LEVEL_ERR, "Couldn't get kernel name info!. (uname: %s)", GetErrorStr()); memset(&VSYSNAME, 0, sizeof(VSYSNAME)); } #ifdef _AIX snprintf(real_version, _SYS_NMLN, "%.80s.%.80s", VSYSNAME.version, VSYSNAME.release); strlcpy(VSYSNAME.release, real_version, _SYS_NMLN); #endif #ifdef __ANDROID__ /* * uname cannot differentiate android from linux */ strcpy(VSYSNAME.sysname, "android"); #endif ToLowerStrInplace(VSYSNAME.sysname); ToLowerStrInplace(VSYSNAME.machine); #ifdef _AIX switch (_system_configuration.architecture) { case POWER_RS: strlcpy(VSYSNAME.machine, "power", _SYS_NMLN); break; case POWER_PC: strlcpy(VSYSNAME.machine, "powerpc", _SYS_NMLN); break; case IA64: strlcpy(VSYSNAME.machine, "ia64", _SYS_NMLN); break; } #endif /* * solarisx86 is a historically defined class for Solaris on x86. We have to * define it manually now. */ #ifdef __sun if (strcmp(VSYSNAME.machine, "i86pc") == 0) { EvalContextClassPutHard(ctx, "solarisx86", "inventory,attribute_name=none,source=agent"); } #endif DetectDomainName(ctx, VSYSNAME.nodename); if ((tloc = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_ERR, "Couldn't read system clock"); } else { snprintf(workbuf, CF_BUFSIZE, "%jd", (intmax_t) tloc); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "systime", workbuf, CF_DATA_TYPE_INT, "time_based,source=agent"); snprintf(workbuf, CF_BUFSIZE, "%jd", (intmax_t) tloc / SECONDS_PER_DAY); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "sysday", workbuf, CF_DATA_TYPE_INT, "time_based,source=agent"); i = GetUptimeMinutes(tloc); if (i != -1) { snprintf(workbuf, CF_BUFSIZE, "%d", i); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "uptime", workbuf, CF_DATA_TYPE_INT, "inventory,time_based,source=agent,attribute_name=Uptime minutes"); } } for (i = 0; i < PLATFORM_CONTEXT_MAX; i++) { char sysname[CF_BUFSIZE]; strlcpy(sysname, VSYSNAME.sysname, CF_BUFSIZE); ToLowerStrInplace(sysname); /* FIXME: review those strcmps. Moved out from StringMatch */ if (!strcmp(CLASSATTRIBUTES[i][0], sysname) || StringMatchFull(CLASSATTRIBUTES[i][0], sysname)) { if (!strcmp(CLASSATTRIBUTES[i][1], VSYSNAME.machine) || StringMatchFull(CLASSATTRIBUTES[i][1], VSYSNAME.machine)) { if (!strcmp(CLASSATTRIBUTES[i][2], VSYSNAME.release) || StringMatchFull(CLASSATTRIBUTES[i][2], VSYSNAME.release)) { EvalContextClassPutHard(ctx, CLASSTEXT[i], "inventory,attribute_name=none,source=agent,derived-from=sys.class"); found = true; VSYSTEMHARDCLASS = (PlatformContext) i; EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "class", CLASSTEXT[i], CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=OS type"); break; } } else { Log(LOG_LEVEL_DEBUG, "I recognize '%s' but not '%s'", VSYSNAME.sysname, VSYSNAME.machine); continue; } } } if (!found) { i = 0; } snprintf(workbuf, CF_BUFSIZE, "%s", CLASSTEXT[i]); Log(LOG_LEVEL_VERBOSE, "%s", NameVersion()); if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------------"); } Log(LOG_LEVEL_VERBOSE, "Host name is: %s", VSYSNAME.nodename); Log(LOG_LEVEL_VERBOSE, "Operating System Type is %s", VSYSNAME.sysname); Log(LOG_LEVEL_VERBOSE, "Operating System Release is %s", VSYSNAME.release); Log(LOG_LEVEL_VERBOSE, "Architecture = %s", VSYSNAME.machine); Log(LOG_LEVEL_VERBOSE, "Using internal soft-class %s for host %s", workbuf, VSYSNAME.nodename); Log(LOG_LEVEL_VERBOSE, "The time is now %s", ctime(&tloc)); if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "------------------------------------------------------------------------"); } snprintf(workbuf, CF_MAXVARSIZE, "%s", ctime(&tloc)); if (Chop(workbuf, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "date", workbuf, CF_DATA_TYPE_STRING, "time_based,source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cdate", CanonifyName(workbuf), CF_DATA_TYPE_STRING, "time_based,source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "os", VSYSNAME.sysname, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "release", VSYSNAME.release, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=OS kernel"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "version", VSYSNAME.version, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "arch", VSYSNAME.machine, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=Architecture"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "workdir", CFWORKDIR, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "fstab", VFSTAB[VSYSTEMHARDCLASS], CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "resolv", VRESOLVCONF[VSYSTEMHARDCLASS], CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "maildir", VMAILDIR[VSYSTEMHARDCLASS], CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "exports", VEXPORTS[VSYSTEMHARDCLASS], CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "logdir", GetLogDir(), CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "piddir", GetPidDir(), CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "masterdir", GetMasterDir(), CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "inputdir", GetInputDir(), CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_BUFSIZE, "%s%cbin", CFWORKDIR, FILE_SEPARATOR); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "bindir", workbuf, CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_BUFSIZE, "%s%cfailsafe.cf", GetInputDir(), FILE_SEPARATOR); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "failsafe_policy_path", workbuf, CF_DATA_TYPE_STRING, "source=agent"); snprintf(workbuf, CF_BUFSIZE, "%s%cupdate.cf", GetInputDir(), FILE_SEPARATOR); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "update_policy_path", workbuf, CF_DATA_TYPE_STRING, "source=agent"); /* FIXME: type conversion */ EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cf_version", (char *) Version(), CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=CFEngine version"); DiscoverVersion(ctx); if (PUBKEY) { char pubkey_digest[CF_HOSTKEY_STRING_SIZE] = { 0 }; HashPubKey(PUBKEY, digest, CF_DEFAULT_DIGEST); HashPrintSafe(pubkey_digest, sizeof(pubkey_digest), digest, CF_DEFAULT_DIGEST, true); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "key_digest", pubkey_digest, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=CFEngine ID"); snprintf(workbuf, CF_MAXVARSIZE - 1, "PK_%s", pubkey_digest); CanonifyNameInPlace(workbuf); EvalContextClassPutHard(ctx, workbuf, "inventory,attribute_name=none,source=agent,derived-from=sys.key_digest"); } for (i = 0; components[i] != NULL; i++) { snprintf(shortname, CF_MAXVARSIZE - 1, "%s", CanonifyName(components[i])); #if defined(_WIN32) // twin has own dir, and is named agent if (i == 0) { snprintf(name, CF_MAXVARSIZE - 1, "%s%cbin-twin%ccf-agent.exe", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR); } else { snprintf(name, CF_MAXVARSIZE - 1, "%s%cbin%c%s.exe", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, components[i]); } #else snprintf(name, CF_MAXVARSIZE - 1, "%s%cbin%c%s", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, components[i]); #endif have_component[i] = false; if (stat(name, &sb) != -1) { snprintf(quoteName, sizeof(quoteName), "\"%s\"", name); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, shortname, quoteName, CF_DATA_TYPE_STRING, "cfe_internal,source=agent"); have_component[i] = true; } } // If no twin, fail over the agent if (!have_component[0]) { snprintf(shortname, CF_MAXVARSIZE - 1, "%s", CanonifyName(components[0])); #if defined(_WIN32) snprintf(name, CF_MAXVARSIZE - 1, "%s%cbin%c%s.exe", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, components[1]); #else snprintf(name, CF_MAXVARSIZE - 1, "%s%cbin%c%s", CFWORKDIR, FILE_SEPARATOR, FILE_SEPARATOR, components[1]); #endif if (stat(name, &sb) != -1) { snprintf(quoteName, sizeof(quoteName), "\"%s\"", name); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, shortname, quoteName, CF_DATA_TYPE_STRING, "cfe_internal,source=agent"); } } /* Windows special directories and tools */ #ifdef __MINGW32__ if (NovaWin_GetWinDir(workbuf, sizeof(workbuf))) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "windir", workbuf, CF_DATA_TYPE_STRING, "source=agent"); } if (NovaWin_GetSysDir(workbuf, sizeof(workbuf))) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "winsysdir", workbuf, CF_DATA_TYPE_STRING, "source=agent"); char filename[CF_BUFSIZE]; if (snprintf(filename, sizeof(filename), "%s%s", workbuf, "\\WindowsPowerShell\\v1.0\\powershell.exe") < sizeof(filename)) { if (NovaWin_FileExists(filename)) { EvalContextClassPutHard(ctx, "powershell", "inventory,attribute_name=none,source=agent"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", "powershell"); } } } if (NovaWin_GetProgDir(workbuf, sizeof(workbuf))) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "winprogdir", workbuf, CF_DATA_TYPE_STRING, "source=agent"); } # ifdef _WIN64 // only available on 64 bit windows systems if (NovaWin_GetEnv("PROGRAMFILES(x86)", workbuf, sizeof(workbuf))) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "winprogdir86", workbuf, CF_DATA_TYPE_STRING, "source=agent"); } # else/* NOT _WIN64 */ EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "winprogdir86", "", CF_DATA_TYPE_STRING, "source=agent"); # endif #endif /* !__MINGW32__ */ EnterpriseContext(ctx); snprintf(workbuf, sizeof(workbuf), "%u_bit", (unsigned) sizeof(void*) * 8); EvalContextClassPutHard(ctx, workbuf, "source=agent"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", CanonifyName(workbuf)); snprintf(workbuf, CF_BUFSIZE, "%s_%s", VSYSNAME.sysname, VSYSNAME.release); EvalContextClassPutHard(ctx, workbuf, "source=agent,derived-from=sys.sysname,derived-from=sys.release"); EvalContextClassPutHard(ctx, VSYSNAME.machine, "source=agent,derived-from=sys.machine"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", CanonifyName(workbuf)); snprintf(workbuf, CF_BUFSIZE, "%s_%s", VSYSNAME.sysname, VSYSNAME.machine); EvalContextClassPutHard(ctx, workbuf, "source=agent,derived-from=sys.sysname,derived-from=sys.machine"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", CanonifyName(workbuf)); snprintf(workbuf, CF_BUFSIZE, "%s_%s_%s", VSYSNAME.sysname, VSYSNAME.machine, VSYSNAME.release); EvalContextClassPutHard(ctx, workbuf, "source=agent,derived-from=sys.sysname,derived-from=sys.machine,derived-from=sys.release"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", CanonifyName(workbuf)); #ifdef HAVE_SYSINFO # ifdef SI_ARCHITECTURE sz = sysinfo(SI_ARCHITECTURE, workbuf, CF_BUFSIZE); if (sz == -1) { Log(LOG_LEVEL_VERBOSE, "cfengine internal: sysinfo returned -1"); } else { EvalContextClassPutHard(ctx, workbuf, "inventory,attribute_name=none,source=agent"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", workbuf); } # endif # ifdef SI_PLATFORM sz = sysinfo(SI_PLATFORM, workbuf, CF_BUFSIZE); if (sz == -1) { Log(LOG_LEVEL_VERBOSE, "cfengine internal: sysinfo returned -1"); } else { EvalContextClassPutHard(ctx, workbuf, "inventory,attribute_name=none,source=agent"); Log(LOG_LEVEL_VERBOSE, "Additional hard class defined as: %s", workbuf); } # endif #endif snprintf(workbuf, CF_BUFSIZE, "%s_%s_%s_%s", VSYSNAME.sysname, VSYSNAME.machine, VSYSNAME.release, VSYSNAME.version); if (strlen(workbuf) > CF_MAXVARSIZE - 2) { Log(LOG_LEVEL_VERBOSE, "cfengine internal: $(arch) overflows CF_MAXVARSIZE! Truncating"); } sp = xstrdup(CanonifyName(workbuf)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "long_arch", sp, CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, sp, "source=agent,derived-from=sys.long_arch"); free(sp); snprintf(workbuf, CF_BUFSIZE, "%s_%s", VSYSNAME.sysname, VSYSNAME.machine); sp = xstrdup(CanonifyName(workbuf)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "ostype", sp, CF_DATA_TYPE_STRING, "source=agent"); EvalContextClassPutHard(ctx, sp, "inventory,attribute_name=none,source=agent,derived-from=sys.ostype"); free(sp); if (!found) { Log(LOG_LEVEL_ERR, "I don't understand what architecture this is"); } strcpy(workbuf, "compiled_on_"); strcat(workbuf, CanonifyName(AUTOCONF_SYSNAME)); EvalContextClassPutHard(ctx, workbuf, "source=agent"); Log(LOG_LEVEL_VERBOSE, "GNU autoconf class from compile time: %s", workbuf); /* Get IP address from nameserver */ if ((hp = gethostbyname(VFQNAME)) == NULL) { Log(LOG_LEVEL_VERBOSE, "Hostname lookup failed on node name '%s'", VSYSNAME.nodename); return; } else { memset(&cin, 0, sizeof(cin)); cin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; Log(LOG_LEVEL_VERBOSE, "Address given by nameserver: %s", inet_ntoa(cin.sin_addr)); strcpy(VIPADDRESS, inet_ntoa(cin.sin_addr)); for (i = 0; hp->h_aliases[i] != NULL; i++) { Log(LOG_LEVEL_DEBUG, "Adding alias '%s'", hp->h_aliases[i]); EvalContextClassPutHard(ctx, hp->h_aliases[i], "inventory,attribute_name=none,source=agent,based-on=sys.fqhost"); } } #ifdef HAVE_GETZONEID zoneid_t zid; char zone[ZONENAME_MAX]; char vbuff[CF_BUFSIZE]; zid = getzoneid(); getzonenamebyid(zid, zone, ZONENAME_MAX); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "zone", zone, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=Solaris zone"); snprintf(vbuff, CF_BUFSIZE - 1, "zone_%s", zone); EvalContextClassPutHard(ctx, vbuff, "source=agent,derived-from=sys.zone"); if (strcmp(zone, "global") == 0) { Log(LOG_LEVEL_VERBOSE, "CFEngine seems to be running inside a global solaris zone of name '%s'", zone); } else { Log(LOG_LEVEL_VERBOSE, "CFEngine seems to be running inside a local solaris zone of name '%s'", zone); } #endif } /*******************************************************************/ static void Get3Environment(EvalContext *ctx) { char env[CF_BUFSIZE], context[CF_BUFSIZE], name[CF_MAXVARSIZE], value[CF_BUFSIZE]; FILE *fp; struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_VERBOSE, "Looking for environment from cf-monitord..."); snprintf(env, CF_BUFSIZE, "%s/state/%s", CFWORKDIR, CF_ENV_FILE); MapName(env); if (stat(env, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to detect environment from cf-monitord"); return; } if (statbuf.st_mtime < (now - 60 * 60)) { Log(LOG_LEVEL_VERBOSE, "Environment data are too old - discarding"); unlink(env); return; } snprintf(value, CF_MAXVARSIZE - 1, "%s", ctime(&statbuf.st_mtime)); if (Chop(value, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_MON, "env_time", value, CF_DATA_TYPE_STRING, "time_based,source=agent"); Log(LOG_LEVEL_VERBOSE, "Loading environment..."); if ((fp = fopen(env, "r")) == NULL) { Log(LOG_LEVEL_VERBOSE, "\nUnable to detect environment from cf-monitord"); return; } for(;;) { name[0] = '\0'; value[0] = '\0'; if (fgets(context, sizeof(context), fp) == NULL) { if (ferror(fp)) { UnexpectedError("Failed to read line from stream"); break; } else /* feof */ { break; } } if (*context == '@') { if (sscanf(context + 1, "%[^=]=%[^\n]", name, value) == 2) { Log(LOG_LEVEL_DEBUG, "Setting new monitoring list '%s' => '%s'", name, value); Rlist *list = RlistParseShown(value); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_MON, name, list, CF_DATA_TYPE_STRING_LIST, "monitoring,source=environment"); RlistDestroy(list); } else { Log(LOG_LEVEL_ERR, "Failed to parse '%s' as '@variable=list' monitoring list", context); } } else if (strchr(context, '=')) { if (sscanf(context, "%255[^=]=%255[^\n]", name, value) == 2) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_MON, name, value, CF_DATA_TYPE_STRING, "monitoring,source=environment"); Log(LOG_LEVEL_DEBUG, "Setting new monitoring scalar '%s' => '%s'", name, value); } else { Log(LOG_LEVEL_ERR, "Failed to parse '%s' as 'variable=value' monitoring scalar", context); } } else { StripTrailingNewline(context, CF_BUFSIZE); EvalContextClassPutHard(ctx, context, "monitoring,source=environment"); } } fclose(fp); Log(LOG_LEVEL_VERBOSE, "Environment data loaded"); LoadSlowlyVaryingObservations(ctx); } static void BuiltinClasses(EvalContext *ctx) { char vbuff[CF_BUFSIZE]; EvalContextClassPutHard(ctx, "any", "source=agent"); /* This is a reserved word / wildcard */ snprintf(vbuff, CF_BUFSIZE, "cfengine_%s", CanonifyName(Version())); CreateHardClassesFromCanonification(ctx, vbuff, "inventory,attribute_name=none,source=agent"); } /*******************************************************************/ void CreateHardClassesFromCanonification(EvalContext *ctx, const char *canonified, char *tags) { char buf[CF_MAXVARSIZE]; strlcpy(buf, canonified, sizeof(buf)); EvalContextClassPutHard(ctx, buf, tags); char *sp; while ((sp = strrchr(buf, '_'))) { *sp = 0; EvalContextClassPutHard(ctx, buf, tags); } } static void SetFlavour(EvalContext *ctx, const char *flavour) { EvalContextClassPutHard(ctx, flavour, "inventory,attribute_name=none,source=agent,derived-from=sys.flavor"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "flavour", flavour, CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "flavor", flavour, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=none"); } static void OSClasses(EvalContext *ctx) { #ifdef __linux__ struct stat statbuf; /* Mandrake/Mandriva, Fedora and Oracle VM Server supply /etc/redhat-release, so we test for those distributions first */ if (stat("/etc/mandriva-release", &statbuf) != -1) { Linux_Mandriva_Version(ctx); } else if (stat("/etc/mandrake-release", &statbuf) != -1) { Linux_Mandrake_Version(ctx); } else if (stat("/etc/fedora-release", &statbuf) != -1) { Linux_Fedora_Version(ctx); } else if (stat("/etc/ovs-release", &statbuf) != -1) { Linux_Oracle_VM_Server_Version(ctx); } else if (stat("/etc/redhat-release", &statbuf) != -1) { Linux_Redhat_Version(ctx); } /* Oracle Linux >= 6 supplies separate /etc/oracle-release alongside /etc/redhat-release, use it to precisely identify version */ if (stat("/etc/oracle-release", &statbuf) != -1) { Linux_Oracle_Version(ctx); } if (stat("/etc/generic-release", &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be a sun cobalt system."); SetFlavour(ctx, "SunCobalt"); } if (stat("/etc/SuSE-release", &statbuf) != -1) { Linux_Suse_Version(ctx); } # define SLACKWARE_ANCIENT_VERSION_FILENAME "/etc/slackware-release" # define SLACKWARE_VERSION_FILENAME "/etc/slackware-version" if (stat(SLACKWARE_VERSION_FILENAME, &statbuf) != -1) { Linux_Slackware_Version(ctx, SLACKWARE_VERSION_FILENAME); } else if (stat(SLACKWARE_ANCIENT_VERSION_FILENAME, &statbuf) != -1) { Linux_Slackware_Version(ctx, SLACKWARE_ANCIENT_VERSION_FILENAME); } if (stat("/etc/debian_version", &statbuf) != -1) { Linux_Debian_Version(ctx); } if (stat("/usr/bin/aptitude", &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This system seems to have the aptitude package system"); EvalContextClassPutHard(ctx, "have_aptitude", "inventory,attribute_name=none,source=agent"); } if (stat("/etc/UnitedLinux-release", &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be a UnitedLinux system."); SetFlavour(ctx, "UnitedLinux"); } if (stat("/etc/alpine-release", &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be an AlpineLinux system."); SetFlavour(ctx, "alpinelinux"); } if (stat("/etc/gentoo-release", &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be a gentoo system."); SetFlavour(ctx, "gentoo"); } if (stat("/etc/arch-release", &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be an Arch Linux system."); SetFlavour(ctx, "archlinux"); } if (stat("/proc/vmware/version", &statbuf) != -1 || stat("/etc/vmware-release", &statbuf) != -1) { VM_Version(ctx); } else if (stat("/etc/vmware", &statbuf) != -1 && S_ISDIR(statbuf.st_mode)) { VM_Version(ctx); } if (stat("/proc/xen/capabilities", &statbuf) != -1) { Xen_Domain(ctx); } if (stat("/etc/Eos-release", &statbuf) != -1) { EOS_Version(ctx); SetFlavour(ctx, "Eos"); } if (stat("/etc/issue", &statbuf) != -1) { MiscOS(ctx); } if (stat("/proc/self/status", &statbuf) != -1) { OpenVZ_Detect(ctx); } #ifdef XEN_CPUID_SUPPORT else if (Xen_Hv_Check()) { Log(LOG_LEVEL_VERBOSE, "This appears to be a xen hv system."); EvalContextClassPutHard(ctx, "xen", "inventory,attribute_name=Virtual host,source=agent"); EvalContextClassPutHard(ctx, "xen_domu_hv", "source=agent"); } #endif #else char vbuff[CF_MAXVARSIZE]; strlcpy(vbuff, VSYSNAME.release, CF_MAXVARSIZE); for (char *sp = vbuff; *sp != '\0'; sp++) { if (*sp == '-') { *sp = '\0'; break; } } char context[CF_BUFSIZE]; snprintf(context, CF_BUFSIZE, "%s_%s", VSYSNAME.sysname, vbuff); SetFlavour(ctx, context); #endif GetCPUInfo(ctx); #ifdef __CYGWIN__ for (char *sp = VSYSNAME.sysname; *sp != '\0'; sp++) { if (*sp == '-') { sp++; if (strncmp(sp, "5.0", 3) == 0) { Log(LOG_LEVEL_VERBOSE, "This appears to be Windows 2000"); EvalContextClassPutHard(ctx, "Win2000", "inventory,attribute_name=none,source=agent"); } if (strncmp(sp, "5.1", 3) == 0) { Log(LOG_LEVEL_VERBOSE, "This appears to be Windows XP"); EvalContextClassPutHard(ctx, "WinXP", "inventory,attribute_name=none,source=agent"); } if (strncmp(sp, "5.2", 3) == 0) { Log(LOG_LEVEL_VERBOSE, "This appears to be Windows Server 2003"); EvalContextClassPutHard(ctx, "WinServer2003", "inventory,attribute_name=none,source=agent"); } if (strncmp(sp, "6.1", 3) == 0) { Log(LOG_LEVEL_VERBOSE, "This appears to be Windows Vista"); EvalContextClassPutHard(ctx, "WinVista", "inventory,attribute_name=none,source=agent"); } if (strncmp(sp, "6.3", 3) == 0) { Log(LOG_LEVEL_VERBOSE, "This appears to be Windows Server 2008"); EvalContextClassPutHard(ctx, "WinServer2008", "inventory,attribute_name=none,source=agent"); } } } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "crontab", "", CF_DATA_TYPE_STRING, "source=agent"); #endif /* __CYGWIN__ */ #ifdef __MINGW32__ EvalContextClassPutHard(ctx, VSYSNAME.release, "inventory,attribute_name=none,source=agent,derived-from=sys.release"); // code name - e.g. Windows Vista EvalContextClassPutHard(ctx, VSYSNAME.version, "inventory,attribute_name=none,source=agent,derived-from=sys.version"); // service pack number - e.g. Service Pack 3 if (strstr(VSYSNAME.sysname, "workstation")) { EvalContextClassPutHard(ctx, "WinWorkstation", "inventory,attribute_name=Windows roles,source=agent,derived-from=sys.sysname"); } else if (strstr(VSYSNAME.sysname, "server")) { EvalContextClassPutHard(ctx, "WinServer", "inventory,attribute_name=Windows roles,source=agent,derived-from=sys.sysname"); } else if (strstr(VSYSNAME.sysname, "domain controller")) { EvalContextClassPutHard(ctx, "DomainController", "inventory,attribute_name=Windows roles,source=agent,derived-from=sys.sysname"); EvalContextClassPutHard(ctx, "WinServer", "inventory,attribute_name=Windows roles,source=agent,derived-from=sys.sysname"); } else { EvalContextClassPutHard(ctx, "unknown_ostype", "source=agent,derived-from=sys.sysname"); } SetFlavour(ctx, "windows"); #endif /* __MINGW32__ */ #ifndef _WIN32 struct passwd *pw; if ((pw = getpwuid(getuid())) == NULL) { Log(LOG_LEVEL_ERR, "Unable to get username for uid '%ju'. (getpwuid: %s)", (uintmax_t)getuid(), GetErrorStr()); } else { char vbuff[CF_BUFSIZE]; if (EvalContextClassGet(ctx, NULL, "SUSE")) { snprintf(vbuff, CF_BUFSIZE, "/var/spool/cron/tabs/%s", pw->pw_name); } else if (EvalContextClassGet(ctx, NULL, "redhat")) { snprintf(vbuff, CF_BUFSIZE, "/var/spool/cron/%s", pw->pw_name); } else if (EvalContextClassGet(ctx, NULL, "freebsd")) { snprintf(vbuff, CF_BUFSIZE, "/var/cron/tabs/%s", pw->pw_name); } else { snprintf(vbuff, CF_BUFSIZE, "/var/spool/cron/crontabs/%s", pw->pw_name); } EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "crontab", vbuff, CF_DATA_TYPE_STRING, "source=agent"); } #endif #if defined(__ANDROID__) SetFlavour(ctx, "android"); #endif #ifdef __sun if (StringMatchFull("joyent.*", VSYSNAME.version)) { EvalContextClassPutHard(ctx, "smartos", "inventory,attribute_name=none,source=agent,derived-from=sys.version"); EvalContextClassPutHard(ctx, "smartmachine", "source=agent,derived-from=sys.version"); } #endif /* FIXME: this variable needs redhat/SUSE/debian classes to be defined and * hence can't be initialized earlier */ if (EvalContextClassGet(ctx, NULL, "redhat")) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "doc_root", "/var/www/html", CF_DATA_TYPE_STRING, "source=agent"); } if (EvalContextClassGet(ctx, NULL, "SUSE")) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "doc_root", "/srv/www/htdocs", CF_DATA_TYPE_STRING, "source=agent"); } if (EvalContextClassGet(ctx, NULL, "debian")) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "doc_root", "/var/www", CF_DATA_TYPE_STRING, "source=agent"); } } /*********************************************************************************/ #ifdef __linux__ static void Linux_Oracle_VM_Server_Version(EvalContext *ctx) { char relstring[CF_MAXVARSIZE]; char *r; int major, minor, patch; int revcomps; #define ORACLE_VM_SERVER_REL_FILENAME "/etc/ovs-release" #define ORACLE_VM_SERVER_ID "Oracle VM server" Log(LOG_LEVEL_VERBOSE, "This appears to be Oracle VM Server"); EvalContextClassPutHard(ctx, "redhat", "inventory,attribute_name=none,source=agent"); EvalContextClassPutHard(ctx, "oraclevmserver", "inventory,attribute_name=Virtual host,source=agent"); if (!ReadLine(ORACLE_VM_SERVER_REL_FILENAME, relstring, sizeof(relstring))) { return; } if (strncmp(relstring, ORACLE_VM_SERVER_ID, strlen(ORACLE_VM_SERVER_ID))) { Log(LOG_LEVEL_VERBOSE, "Could not identify distribution from %s", ORACLE_VM_SERVER_REL_FILENAME); return; } if ((r = strstr(relstring, "release ")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find distribution version in %s", ORACLE_VM_SERVER_REL_FILENAME); return; } revcomps = sscanf(r + strlen("release "), "%d.%d.%d", &major, &minor, &patch); if (revcomps > 0) { char buf[CF_BUFSIZE]; snprintf(buf, CF_BUFSIZE, "oraclevmserver_%d", major); SetFlavour(ctx, buf); } if (revcomps > 1) { char buf[CF_BUFSIZE]; snprintf(buf, CF_BUFSIZE, "oraclevmserver_%d_%d", major, minor); EvalContextClassPutHard(ctx, buf, "inventory,attribute_name=none,source=agent"); } if (revcomps > 2) { char buf[CF_BUFSIZE]; snprintf(buf, CF_BUFSIZE, "oraclevmserver_%d_%d_%d", major, minor, patch); EvalContextClassPutHard(ctx, buf, "inventory,attribute_name=none,source=agent"); } } /*********************************************************************************/ static void Linux_Oracle_Version(EvalContext *ctx) { char relstring[CF_MAXVARSIZE]; char *r; int major, minor; #define ORACLE_REL_FILENAME "/etc/oracle-release" #define ORACLE_ID "Oracle Linux Server" Log(LOG_LEVEL_VERBOSE, "This appears to be Oracle Linux"); EvalContextClassPutHard(ctx, "oracle", "inventory,attribute_name=none,source=agent"); if (!ReadLine(ORACLE_REL_FILENAME, relstring, sizeof(relstring))) { return; } if (strncmp(relstring, ORACLE_ID, strlen(ORACLE_ID))) { Log(LOG_LEVEL_VERBOSE, "Could not identify distribution from %s", ORACLE_REL_FILENAME); return; } if ((r = strstr(relstring, "release ")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find distribution version in %s", ORACLE_REL_FILENAME); return; } if (sscanf(r + strlen("release "), "%d.%d", &major, &minor) == 2) { char buf[CF_BUFSIZE]; snprintf(buf, CF_BUFSIZE, "oracle_%d", major); SetFlavour(ctx, buf); snprintf(buf, CF_BUFSIZE, "oracle_%d_%d", major, minor); EvalContextClassPutHard(ctx, buf, "inventory,attribute_name=none,source=agent"); } } /*********************************************************************************/ static int Linux_Fedora_Version(EvalContext *ctx) { #define FEDORA_ID "Fedora" #define RELEASE_FLAG "release " /* We are looking for one of the following strings... * * Fedora Core release 1 (Yarrow) * Fedora release 7 (Zodfoobar) */ #define FEDORA_REL_FILENAME "/etc/fedora-release" /* The full string read in from fedora-release */ char relstring[CF_MAXVARSIZE]; Log(LOG_LEVEL_VERBOSE, "This appears to be a fedora system."); EvalContextClassPutHard(ctx, "redhat", "inventory,attribute_name=none,source=agent"); EvalContextClassPutHard(ctx, "fedora", "inventory,attribute_name=none,source=agent"); /* Grab the first line from the file and then close it. */ if (!ReadLine(FEDORA_REL_FILENAME, relstring, sizeof(relstring))) { return 1; } Log(LOG_LEVEL_VERBOSE, "Looking for fedora core linux info..."); char *vendor = ""; if (!strncmp(relstring, FEDORA_ID, strlen(FEDORA_ID))) { vendor = "fedora"; } else { Log(LOG_LEVEL_VERBOSE, "Could not identify OS distro from %s", FEDORA_REL_FILENAME); return 2; } /* Now, grok the release. We assume that all the strings will * have the word 'release' before the numerical release. */ int major = -1; char strmajor[PRINTSIZE(major)]; char *release = strstr(relstring, RELEASE_FLAG); if (release == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", FEDORA_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); strmajor[0] = '\0'; if (sscanf(release, "%d", &major) != 0) { xsnprintf(strmajor, sizeof(strmajor), "%d", major); } } if (major != -1 && vendor[0] != '\0') { char classbuf[CF_MAXVARSIZE]; classbuf[0] = '\0'; strcat(classbuf, vendor); EvalContextClassPutHard(ctx,classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strmajor); SetFlavour(ctx, classbuf); } return 0; } /*********************************************************************************/ static int Linux_Redhat_Version(EvalContext *ctx) { #define REDHAT_ID "Red Hat Linux" #define REDHAT_AS_ID "Red Hat Enterprise Linux AS" #define REDHAT_AS21_ID "Red Hat Linux Advanced Server" #define REDHAT_ES_ID "Red Hat Enterprise Linux ES" #define REDHAT_WS_ID "Red Hat Enterprise Linux WS" #define REDHAT_C_ID "Red Hat Enterprise Linux Client" #define REDHAT_S_ID "Red Hat Enterprise Linux Server" #define REDHAT_W_ID "Red Hat Enterprise Linux Workstation" #define MANDRAKE_ID "Linux Mandrake" #define MANDRAKE_10_1_ID "Mandrakelinux" #define WHITEBOX_ID "White Box Enterprise Linux" #define CENTOS_ID "CentOS" #define SCIENTIFIC_SL_ID "Scientific Linux SL" #define SCIENTIFIC_SL6_ID "Scientific Linux" #define SCIENTIFIC_CERN_ID "Scientific Linux CERN" #define RELEASE_FLAG "release " #define ORACLE_4_5_ID "Enterprise Linux Enterprise Linux Server" /* We are looking for one of the following strings... * * Red Hat Linux release 6.2 (Zoot) * Red Hat Linux Advanced Server release 2.1AS (Pensacola) * Red Hat Enterprise Linux AS release 3 (Taroon) * Red Hat Enterprise Linux WS release 3 (Taroon) * Red Hat Enterprise Linux Client release 5 (Tikanga) * Red Hat Enterprise Linux Server release 5 (Tikanga) * Linux Mandrake release 7.1 (helium) * Red Hat Enterprise Linux ES release 2.1 (Panama) * White Box Enterprise linux release 3.0 (Liberation) * Scientific Linux SL Release 4.0 (Beryllium) * CentOS release 4.0 (Final) */ #define RH_REL_FILENAME "/etc/redhat-release" Log(LOG_LEVEL_VERBOSE, "This appears to be a redhat (or redhat-based) system."); EvalContextClassPutHard(ctx, "redhat", "inventory,attribute_name=none,source=agent"); /* Grab the first line from the file and then close it. */ char relstring[CF_MAXVARSIZE]; if (!ReadLine(RH_REL_FILENAME, relstring, sizeof(relstring))) { return 1; } Log(LOG_LEVEL_VERBOSE, "Looking for redhat linux info in '%s'", relstring); /* First, try to grok the vendor and edition (if any) */ char *edition = ""; /* as (Advanced Server, Enterprise) */ char *vendor = ""; /* Red Hat, Mandrake */ if (!strncmp(relstring, REDHAT_ES_ID, strlen(REDHAT_ES_ID))) { vendor = "redhat"; edition = "es"; } else if (!strncmp(relstring, REDHAT_WS_ID, strlen(REDHAT_WS_ID))) { vendor = "redhat"; edition = "ws"; } else if (!strncmp(relstring, REDHAT_WS_ID, strlen(REDHAT_WS_ID))) { vendor = "redhat"; edition = "ws"; } else if (!strncmp(relstring, REDHAT_AS_ID, strlen(REDHAT_AS_ID)) || !strncmp(relstring, REDHAT_AS21_ID, strlen(REDHAT_AS21_ID))) { vendor = "redhat"; edition = "as"; } else if (!strncmp(relstring, REDHAT_S_ID, strlen(REDHAT_S_ID))) { vendor = "redhat"; edition = "s"; } else if (!strncmp(relstring, REDHAT_C_ID, strlen(REDHAT_C_ID)) || !strncmp(relstring, REDHAT_W_ID, strlen(REDHAT_W_ID))) { vendor = "redhat"; edition = "c"; } else if (!strncmp(relstring, REDHAT_ID, strlen(REDHAT_ID))) { vendor = "redhat"; } else if (!strncmp(relstring, MANDRAKE_ID, strlen(MANDRAKE_ID))) { vendor = "mandrake"; } else if (!strncmp(relstring, MANDRAKE_10_1_ID, strlen(MANDRAKE_10_1_ID))) { vendor = "mandrake"; } else if (!strncmp(relstring, WHITEBOX_ID, strlen(WHITEBOX_ID))) { vendor = "whitebox"; } else if (!strncmp(relstring, SCIENTIFIC_SL_ID, strlen(SCIENTIFIC_SL_ID))) { vendor = "scientific"; edition = "sl"; } else if (!strncmp(relstring, SCIENTIFIC_CERN_ID, strlen(SCIENTIFIC_CERN_ID))) { vendor = "scientific"; edition = "cern"; } else if (!strncmp(relstring, SCIENTIFIC_SL6_ID, strlen(SCIENTIFIC_SL6_ID))) { vendor = "scientific"; edition = "sl"; } else if (!strncmp(relstring, CENTOS_ID, strlen(CENTOS_ID))) { vendor = "centos"; } else if (!strncmp(relstring, ORACLE_4_5_ID, strlen(ORACLE_4_5_ID))) { vendor = "oracle"; edition = "s"; } else { Log(LOG_LEVEL_VERBOSE, "Could not identify OS distro from %s", RH_REL_FILENAME); return 2; } /* Now, grok the release. For AS, we neglect the AS at the end of the * numerical release because we already figured out that it *is* AS * from the infomation above. We assume that all the strings will * have the word 'release' before the numerical release. */ /* Convert relstring to lowercase so that vendors like Scientific Linux don't fall through the cracks. */ for (int i = 0; i < strlen(relstring); i++) { relstring[i] = tolower(relstring[i]); } /* Where the numerical release will be found */ int major = -1, minor = -1; char strmajor[PRINTSIZE(major)], strminor[PRINTSIZE(minor)]; char *release = strstr(relstring, RELEASE_FLAG); if (release == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", RH_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d.%d", &major, &minor) == 2) { xsnprintf(strmajor, sizeof(strmajor), "%d", major); xsnprintf(strminor, sizeof(strminor), "%d", minor); } /* red hat 9 is *not* red hat 9.0. * and same thing with RHEL AS 3 */ else if (sscanf(release, "%d", &major) == 1) { xsnprintf(strmajor, sizeof(strmajor), "%d", major); minor = -2; } } char classbuf[CF_MAXVARSIZE]; if (major != -1 && minor != -1 && (strcmp(vendor, "") != 0)) { classbuf[0] = '\0'; strcat(classbuf, vendor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); if (strcmp(edition, "") != 0) { strcat(classbuf, edition); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); } strcat(classbuf, strmajor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); } } // Now a version without the edition if (major != -1 && minor != -1 && vendor[0] != '\0') { classbuf[0] = '\0'; strcat(classbuf, vendor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strmajor); SetFlavour(ctx, classbuf); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); } } return 0; } /******************************************************************/ static int Linux_Suse_Version(EvalContext *ctx) { #define SUSE_REL_FILENAME "/etc/SuSE-release" /* Check if it's a SUSE Enterprise version (all in lowercase) */ #define SUSE_SLES8_ID "suse sles-8" #define SUSE_SLES_ID "suse linux enterprise server" #define SUSE_SLED_ID "suse linux enterprise desktop" #define SUSE_RELEASE_FLAG "linux " char classbuf[CF_MAXVARSIZE]; Log(LOG_LEVEL_VERBOSE, "This appears to be a SUSE system."); EvalContextClassPutHard(ctx, "SUSE", "inventory,attribute_name=none,source=agent"); EvalContextClassPutHard(ctx, "suse", "inventory,attribute_name=none,source=agent"); /* The correct spelling for SUSE is "SUSE" but CFEngine used to use "SuSE". * Keep this for backwards compatibility until CFEngine 3.7 */ EvalContextClassPutHard(ctx, "SuSE", "inventory,attribute_name=none,source=agent"); /* Grab the first line from the SuSE-release file and then close it. */ char relstring[CF_MAXVARSIZE]; FILE *fp = ReadFirstLine(SUSE_REL_FILENAME, relstring, sizeof(relstring)); if (fp == NULL) { return 1; } char vbuf[CF_BUFSIZE], strversion[CF_MAXVARSIZE], strpatch[CF_MAXVARSIZE]; strversion[0] = '\0'; strpatch[0] = '\0'; int major = -1, minor = -1; while (fgets(vbuf, sizeof(vbuf), fp) != NULL) { if (strncmp(vbuf, "VERSION", strlen("version")) == 0) { strlcpy(strversion, vbuf, sizeof(strversion)); sscanf(vbuf, "VERSION = %d", &major); } if (strncmp(vbuf, "PATCH", strlen("PATCH")) == 0) { strlcpy(strpatch, vbuf, sizeof(strpatch)); sscanf(vbuf, "PATCHLEVEL = %d", &minor); } } if (ferror(fp)) { UnexpectedError("Failed to read line from stream"); } else { assert(feof(fp)); } fclose(fp); /* Check if it's a SUSE Enterprise version */ Log(LOG_LEVEL_VERBOSE, "Looking for SUSE enterprise info in '%s'", relstring); /* Convert relstring to lowercase to handle rename of SuSE to * SUSE with SUSE 10.0. */ for (int i = 0; i < strlen(relstring); i++) { relstring[i] = tolower(relstring[i]); } /* Check if it's a SUSE Enterprise version (all in lowercase) */ if (!strncmp(relstring, SUSE_SLES8_ID, strlen(SUSE_SLES8_ID))) { classbuf[0] = '\0'; strcat(classbuf, "SLES8"); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); } else if (strncmp(relstring, "sles", 4) == 0) { Item *list, *ip; sscanf(relstring, "%[-_a-zA-Z0-9]", vbuf); EvalContextClassPutHard(ctx, vbuf, "inventory,attribute_name=none,source=agent"); list = SplitString(vbuf, '-'); for (ip = list; ip != NULL; ip = ip->next) { EvalContextClassPutHard(ctx, ip->name, "inventory,attribute_name=none,source=agent"); } DeleteItemList(list); } else { for (int version = 9; version < 13; version++) { snprintf(vbuf, CF_BUFSIZE, "%s %d ", SUSE_SLES_ID, version); Log(LOG_LEVEL_DEBUG, "Checking for SUSE [%s]", vbuf); if (!strncmp(relstring, vbuf, strlen(vbuf))) { snprintf(classbuf, CF_MAXVARSIZE, "SLES%d", version); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); } else { snprintf(vbuf, CF_BUFSIZE, "%s %d ", SUSE_SLED_ID, version); Log(LOG_LEVEL_DEBUG, "Checking for SUSE [%s]", vbuf); if (!strncmp(relstring, vbuf, strlen(vbuf))) { snprintf(classbuf, CF_MAXVARSIZE, "SLED%d", version); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); } } } } /* Determine release version. We assume that the version follows * the string "SuSE Linux" or "SUSE LINUX". */ char *release = strstr(relstring, SUSE_RELEASE_FLAG); if (release == NULL) { release = strstr(relstring, "opensuse"); if (release == NULL) { release = strversion; } } if (release == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", SUSE_REL_FILENAME); return 2; } else { char strmajor[PRINTSIZE(major)], strminor[PRINTSIZE(minor)]; if (strchr(release, '.')) { sscanf(release, "%*s %d.%d", &major, &minor); xsnprintf(strmajor, sizeof(strmajor), "%d", major); xsnprintf(strminor, sizeof(strminor), "%d", minor); if (major != -1 && minor != -1) { strcpy(classbuf, "SUSE"); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strmajor); SetFlavour(ctx, classbuf); strcat(classbuf, "_"); strcat(classbuf, strminor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); /* The correct spelling for SUSE is "SUSE" but CFEngine used to use "SuSE". * Keep this for backwards compatibility until CFEngine 3.7 */ strcpy(classbuf, "SuSE"); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strmajor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strminor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); Log(LOG_LEVEL_VERBOSE, "Discovered SUSE version %s", classbuf); return 0; } } else { sscanf(strversion, "VERSION = %s", strmajor); sscanf(strpatch, "PATCHLEVEL = %s", strminor); if (major != -1 && minor != -1) { strcpy(classbuf, "SLES"); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strmajor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strminor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); snprintf(classbuf, CF_MAXVARSIZE, "SUSE_%d", major); SetFlavour(ctx, classbuf); /* The correct spelling for SUSE is "SUSE" but CFEngine used to use "SuSE". * Keep this for backwards compatibility until CFEngine 3.7 */ snprintf(classbuf, CF_MAXVARSIZE, "SuSE_%d", major); EvalContextClassPutHard(ctx, classbuf, "source=agent"); Log(LOG_LEVEL_VERBOSE, "Discovered SUSE version %s", classbuf); return 0; } } } Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", SUSE_REL_FILENAME); return 0; } /******************************************************************/ static int Linux_Slackware_Version(EvalContext *ctx, char *filename) { int major = -1; int minor = -1; int release = -1; char classname[CF_MAXVARSIZE] = ""; char buffer[CF_MAXVARSIZE]; Log(LOG_LEVEL_VERBOSE, "This appears to be a slackware system."); EvalContextClassPutHard(ctx, "slackware", "inventory,attribute_name=none,source=agent"); if (!ReadLine(filename, buffer, sizeof(buffer))) { return 1; } Log(LOG_LEVEL_VERBOSE, "Looking for Slackware version..."); switch (sscanf(buffer, "Slackware %d.%d.%d", &major, &minor, &release)) { case 3: Log(LOG_LEVEL_VERBOSE, "This appears to be a Slackware %u.%u.%u system.", major, minor, release); snprintf(classname, CF_MAXVARSIZE, "slackware_%u_%u_%u", major, minor, release); EvalContextClassPutHard(ctx, classname, "inventory,attribute_name=none,source=agent"); /* Fall-through */ case 2: Log(LOG_LEVEL_VERBOSE, "This appears to be a Slackware %u.%u system.", major, minor); snprintf(classname, CF_MAXVARSIZE, "slackware_%u_%u", major, minor); EvalContextClassPutHard(ctx, classname, "inventory,attribute_name=none,source=agent"); /* Fall-through */ case 1: Log(LOG_LEVEL_VERBOSE, "This appears to be a Slackware %u system.", major); snprintf(classname, CF_MAXVARSIZE, "slackware_%u", major); EvalContextClassPutHard(ctx, classname, "inventory,attribute_name=none,source=agent"); break; case 0: Log(LOG_LEVEL_VERBOSE, "No Slackware version number found."); return 2; } return 0; } /* * @brief : /etc/issue on debian can include special characters * escaped with '/' or '@'. This function will get rid * them. * * @param[in,out] buffer: string to be sanitized * * @return : 0 if everything went fine, <>0 otherwise */ static int LinuxDebianSanitizeIssue(char *buffer) { bool escaped = false; char *s2, *s; s2 = buffer; for (s = buffer; *s != '\0'; s++) { if (*s=='\\' || *s=='@') { if (escaped == false) { escaped = true; } else { escaped = false; } } else { if (escaped == false) { *s2 = *s; s2++; } else { escaped = false; } } } *s2 = '\0'; s2--; while (*s2 == ' ') { *s2 = '\0'; s2--; } return 0; } /******************************************************************/ static int Linux_Debian_Version(EvalContext *ctx) { #define DEBIAN_VERSION_FILENAME "/etc/debian_version" #define DEBIAN_ISSUE_FILENAME "/etc/issue" int major = -1; int release = -1; int result; char classname[CF_MAXVARSIZE], buffer[CF_MAXVARSIZE], os[CF_MAXVARSIZE], version[CF_MAXVARSIZE]; Log(LOG_LEVEL_VERBOSE, "This appears to be a debian system."); EvalContextClassPutHard(ctx, "debian", "inventory,attribute_name=none,source=agent"); buffer[0] = classname[0] = '\0'; Log(LOG_LEVEL_VERBOSE, "Looking for Debian version..."); if (!ReadLine(DEBIAN_VERSION_FILENAME, buffer, sizeof(buffer))) { return 1; } result = sscanf(buffer, "%d.%d", &major, &release); switch (result) { case 2: Log(LOG_LEVEL_VERBOSE, "This appears to be a Debian %u.%u system.", major, release); snprintf(classname, CF_MAXVARSIZE, "debian_%u_%u", major, release); EvalContextClassPutHard(ctx, classname, "inventory,attribute_name=none,source=agent"); snprintf(classname, CF_MAXVARSIZE, "debian_%u", major); SetFlavour(ctx, classname); break; /* Fall-through */ case 1: Log(LOG_LEVEL_VERBOSE, "This appears to be a Debian %u system.", major); snprintf(classname, CF_MAXVARSIZE, "debian_%u", major); SetFlavour(ctx, classname); break; default: version[0] = '\0'; sscanf(buffer, "%25[^/]", version); if (strlen(version) > 0) { snprintf(classname, CF_MAXVARSIZE, "debian_%s", version); EvalContextClassPutHard(ctx, classname, "inventory,attribute_name=none,source=agent"); } break; } if (!ReadLine(DEBIAN_ISSUE_FILENAME, buffer, sizeof(buffer))) { return 1; } os[0] = '\0'; sscanf(buffer, "%250s", os); if (strcmp(os, "Debian") == 0) { LinuxDebianSanitizeIssue(buffer); sscanf(buffer, "%*s %*s %[^./]", version); snprintf(buffer, CF_MAXVARSIZE, "debian_%s", version); EvalContextClassPutHard(ctx, "debian", "inventory,attribute_name=none,source=agent"); SetFlavour(ctx, buffer); } else if (strcmp(os, "Ubuntu") == 0) { LinuxDebianSanitizeIssue(buffer); sscanf(buffer, "%*s %[^.].%d", version, &release); snprintf(buffer, CF_MAXVARSIZE, "ubuntu_%s", version); SetFlavour(ctx, buffer); EvalContextClassPutHard(ctx, "ubuntu", "inventory,attribute_name=none,source=agent"); if (release >= 0) { snprintf(buffer, CF_MAXVARSIZE, "ubuntu_%s_%d", version, release); EvalContextClassPutHard(ctx, buffer, "inventory,attribute_name=none,source=agent"); } } return 0; } /******************************************************************/ static int Linux_Mandrake_Version(EvalContext *ctx) { /* We are looking for one of the following strings... */ #define MANDRAKE_ID "Linux Mandrake" #define MANDRAKE_REV_ID "Mandrake Linux" #define MANDRAKE_10_1_ID "Mandrakelinux" #define MANDRAKE_REL_FILENAME "/etc/mandrake-release" char relstring[CF_MAXVARSIZE]; char *vendor = NULL; Log(LOG_LEVEL_VERBOSE, "This appears to be a mandrake system."); EvalContextClassPutHard(ctx, "Mandrake", "inventory,attribute_name=none,source=agent"); if (!ReadLine(MANDRAKE_REL_FILENAME, relstring, sizeof(relstring))) { return 1; } Log(LOG_LEVEL_VERBOSE, "Looking for Mandrake linux info in '%s'", relstring); /* Older Mandrakes had the 'Mandrake Linux' string in reverse order */ if (!strncmp(relstring, MANDRAKE_ID, strlen(MANDRAKE_ID))) { vendor = "mandrake"; } else if (!strncmp(relstring, MANDRAKE_REV_ID, strlen(MANDRAKE_REV_ID))) { vendor = "mandrake"; } else if (!strncmp(relstring, MANDRAKE_10_1_ID, strlen(MANDRAKE_10_1_ID))) { vendor = "mandrake"; } else { Log(LOG_LEVEL_VERBOSE, "Could not identify OS distro from %s", MANDRAKE_REL_FILENAME); return 2; } return Linux_Mandriva_Version_Real(ctx, MANDRAKE_REL_FILENAME, relstring, vendor); } /******************************************************************/ static int Linux_Mandriva_Version(EvalContext *ctx) { /* We are looking for the following strings... */ #define MANDRIVA_ID "Mandriva Linux" #define MANDRIVA_REL_FILENAME "/etc/mandriva-release" char relstring[CF_MAXVARSIZE]; char *vendor = NULL; Log(LOG_LEVEL_VERBOSE, "This appears to be a mandriva system."); EvalContextClassPutHard(ctx, "Mandrake", "inventory,attribute_name=none,source=agent"); EvalContextClassPutHard(ctx, "Mandriva", "inventory,attribute_name=none,source=agent"); if (!ReadLine(MANDRIVA_REL_FILENAME, relstring, sizeof(relstring))) { return 1; } Log(LOG_LEVEL_VERBOSE, "Looking for Mandriva linux info in '%s'", relstring); if (!strncmp(relstring, MANDRIVA_ID, strlen(MANDRIVA_ID))) { vendor = "mandriva"; } else { Log(LOG_LEVEL_VERBOSE, "Could not identify OS distro from '%s'", MANDRIVA_REL_FILENAME); return 2; } return Linux_Mandriva_Version_Real(ctx, MANDRIVA_REL_FILENAME, relstring, vendor); } /******************************************************************/ static int Linux_Mandriva_Version_Real(EvalContext *ctx, char *filename, char *relstring, char *vendor) { int major = -1, minor = -1; char strmajor[PRINTSIZE(major)], strminor[PRINTSIZE(minor)]; #define RELEASE_FLAG "release " char *release = strstr(relstring, RELEASE_FLAG); if (release == NULL) { Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", filename); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d.%d", &major, &minor) == 2) { xsnprintf(strmajor, sizeof(strmajor), "%d", major); xsnprintf(strminor, sizeof(strminor), "%d", minor); } else { Log(LOG_LEVEL_VERBOSE, "Could not break down release version numbers in %s", filename); } } if (major != -1 && minor != -1 && strcmp(vendor, "")) { char classbuf[CF_MAXVARSIZE]; classbuf[0] = '\0'; strcat(classbuf, vendor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); strcat(classbuf, "_"); strcat(classbuf, strmajor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); } } return 0; } /******************************************************************/ static int EOS_Version(EvalContext *ctx) { char buffer[CF_BUFSIZE]; // e.g. Arista Networks EOS 4.10.2 if (ReadLine("/etc/Eos-release", buffer, sizeof(buffer))) { if (strstr(buffer, "EOS")) { char version[CF_MAXVARSIZE], class[CF_MAXVARSIZE]; EvalContextClassPutHard(ctx, "eos", "inventory,attribute_name=none,source=agent"); EvalContextClassPutHard(ctx, "arista", "source=agent"); version[0] = '\0'; sscanf(buffer, "%*s %*s %*s %s", version); CanonifyNameInPlace(version); snprintf(class, CF_MAXVARSIZE, "eos_%s", version); EvalContextClassPutHard(ctx, class, "inventory,attribute_name=none,source=agent"); } } return 0; } /******************************************************************/ static int MiscOS(EvalContext *ctx) { char buffer[CF_BUFSIZE]; // e.g. BIG-IP 10.1.0 Build 3341.1084 if (ReadLine("/etc/issue", buffer, sizeof(buffer))) { if (strstr(buffer, "BIG-IP")) { char version[CF_MAXVARSIZE], build[CF_MAXVARSIZE], class[CF_MAXVARSIZE]; EvalContextClassPutHard(ctx, "big_ip", "inventory,attribute_name=none,source=agent"); sscanf(buffer, "%*s %s %*s %s", version, build); CanonifyNameInPlace(version); CanonifyNameInPlace(build); snprintf(class, CF_MAXVARSIZE, "big_ip_%s", version); EvalContextClassPutHard(ctx, class, "inventory,attribute_name=none,source=agent"); snprintf(class, CF_MAXVARSIZE, "big_ip_%s_%s", version, build); EvalContextClassPutHard(ctx, class, "inventory,attribute_name=none,source=agent"); SetFlavour(ctx, "BIG-IP"); } } return 0; } /******************************************************************/ static int VM_Version(EvalContext *ctx) { char *sp, buffer[CF_BUFSIZE], classbuf[CF_BUFSIZE], version[CF_BUFSIZE]; int major, minor, bug; int sufficient = 0; Log(LOG_LEVEL_VERBOSE, "This appears to be a VMware Server ESX/xSX system."); EvalContextClassPutHard(ctx, "VMware", "inventory,attribute_name=Virtual host,source=agent"); /* VMware Server ESX >= 3 has version info in /proc */ if (ReadLine("/proc/vmware/version", buffer, sizeof(buffer))) { if (sscanf(buffer, "VMware ESX Server %d.%d.%d", &major, &minor, &bug) > 0) { snprintf(classbuf, CF_BUFSIZE, "VMware ESX Server %d", major); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); snprintf(classbuf, CF_BUFSIZE, "VMware ESX Server %d.%d", major, minor); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); snprintf(classbuf, CF_BUFSIZE, "VMware ESX Server %d.%d.%d", major, minor, bug); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); sufficient = 1; } else if (sscanf(buffer, "VMware ESX Server %s", version) > 0) { snprintf(classbuf, CF_BUFSIZE, "VMware ESX Server %s", version); EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent"); sufficient = 1; } } /* Fall back to checking for other files */ if (sufficient < 1 && (ReadLine("/etc/vmware-release", buffer, sizeof(buffer)) || ReadLine("/etc/issue", buffer, sizeof(buffer)))) { EvalContextClassPutHard(ctx, buffer, "inventory,attribute_name=none,source=agent"); /* Strip off the release code name e.g. "(Dali)" */ if ((sp = strchr(buffer, '(')) != NULL) { *sp = 0; Chop(buffer, CF_EXPANDSIZE); EvalContextClassPutHard(ctx, buffer, "inventory,attribute_name=none,source=agent"); } sufficient = 1; } return sufficient < 1 ? 1 : 0; } /******************************************************************/ static int Xen_Domain(EvalContext *ctx) { FILE *fp; int sufficient = 0; Log(LOG_LEVEL_VERBOSE, "This appears to be a xen pv system."); EvalContextClassPutHard(ctx, "xen", "inventory,attribute_name=Virtual host,source=agent"); /* xen host will have "control_d" in /proc/xen/capabilities, xen guest will not */ if ((fp = fopen("/proc/xen/capabilities", "r")) != NULL) { size_t buffer_size = CF_BUFSIZE; char *buffer = xmalloc(buffer_size); for (;;) { ssize_t res = CfReadLine(&buffer, &buffer_size, fp); if (res == -1) { if (!feof(fp)) { /* Failure reading Xen capabilites. Do we care? */ fclose(fp); free(buffer); return 1; } else { break; } } if (strstr(buffer, "control_d")) { EvalContextClassPutHard(ctx, "xen_dom0", "inventory,attribute_name=Virtual host,source=agent"); sufficient = 1; } } if (!sufficient) { EvalContextClassPutHard(ctx, "xen_domu_pv", "inventory,attribute_name=Virtual host,source=agent"); sufficient = 1; } fclose(fp); free(buffer); } return sufficient < 1 ? 1 : 0; } /******************************************************************/ static void OpenVZ_Detect(EvalContext *ctx) { /* paths to file defining the type of vm (guest or host) */ #define OPENVZ_HOST_FILENAME "/proc/bc/0" #define OPENVZ_GUEST_FILENAME "/proc/vz" /* path to the vzps binary */ #define OPENVZ_VZPS_FILE "/bin/vzps" struct stat statbuf; /* The file /proc/bc/0 is present on host The file /proc/vz is present on guest If the host has /bin/vzps, we should use it for checking processes */ if (stat(OPENVZ_HOST_FILENAME, &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be an OpenVZ/Virtuozzo/Parallels Cloud Server host system.\n"); EvalContextClassPutHard(ctx, "virt_host_vz", "inventory,attribute_name=Virtual host,source=agent"); /* if the file /bin/vzps is there, it is safe to use the processes promise type */ if (stat(OPENVZ_VZPS_FILE, &statbuf) != -1) { EvalContextClassPutHard(ctx, "virt_host_vz_vzps", "inventory,attribute_name=Virtual host,source=agent"); } else { Log(LOG_LEVEL_NOTICE, "This OpenVZ/Virtuozzo/Parallels Cloud Server host system does not have vzps installed; the processes promise type may not work as expected.\n"); } } else if (stat(OPENVZ_GUEST_FILENAME, &statbuf) != -1) { Log(LOG_LEVEL_VERBOSE, "This appears to be an OpenVZ/Virtuozzo/Parallels Cloud Server guest system.\n"); EvalContextClassPutHard(ctx, "virt_guest_vz", "inventory,attribute_name=Virtual host,source=agent"); } } /******************************************************************/ #ifdef XEN_CPUID_SUPPORT /* borrowed from Xen source/tools/libxc/xc_cpuid_x86.c */ static void Xen_Cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { asm( /* %ebx register need to be saved before usage and restored thereafter * for PIC-compliant code on i386 */ # ifdef __i386__ "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx" # else "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx" # endif : "=a"(*eax), "=r"(*ebx), "=c"(*ecx), "=d"(*edx):"0"(idx), "2"(0)); } /******************************************************************/ static int Xen_Hv_Check(void) { uint32_t eax; union { uint32_t u[3]; char s[13]; } sig = {{0}}; Xen_Cpuid(0x40000000, &eax, &sig.u[0], &sig.u[1], &sig.u[2]); if (strcmp("XenVMMXenVMM", sig.s) || (eax < 0x40000002)) { return 0; } Xen_Cpuid(0x40000001, &eax, &sig.u[0], &sig.u[1], &sig.u[2]); return 1; } #endif /******************************************************************/ static bool ReadLine(const char *filename, char *buf, int bufsize) { FILE *fp = ReadFirstLine(filename, buf, bufsize); if (fp == NULL) { return false; } else { fclose(fp); return true; } } static FILE *ReadFirstLine(const char *filename, char *buf, int bufsize) { FILE *fp = safe_fopen(filename, "r"); if (fp == NULL) { return NULL; } if (fgets(buf, bufsize, fp) == NULL) { fclose(fp); return NULL; } StripTrailingNewline(buf, CF_EXPANDSIZE); return fp; } #endif /* __linux__ */ static void GetCPUInfo(EvalContext *ctx) { #if defined(MINGW) || defined(NT) Log(LOG_LEVEL_VERBOSE, "!! cpu count not implemented on Windows platform"); return; #else int count = 0; // http://preview.tinyurl.com/c9l2sh - StackOverflow on cross-platform CPU counting #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) // Linux, AIX, Solaris, Darwin >= 10.4 count = (int)sysconf(_SC_NPROCESSORS_ONLN); #endif #if defined(HAVE_SYS_SYSCTL_H) && defined(HW_NCPU) // BSD-derived platforms int mib[2] = { CTL_HW, HW_NCPU }; size_t len; len = sizeof(count); if(sysctl(mib, 2, &count, &len, NULL, 0) < 0) { Log(LOG_LEVEL_ERR, "!! failed to get cpu count: %s", strerror(errno)); } #endif #ifdef HAVE_SYS_MPCTL_H // Itanium processors have Intel Hyper-Threading virtual-core capability, // and the MPC_GETNUMCORES_SYS operation counts each HT virtual core, // which is equivalent to what the /proc/stat scan delivers for Linux. // // A build on 11i v3 PA would have the GETNUMCORES define, but if run on an // 11i v1 system it would fail since that OS release has only GETNUMSPUS. // So in the presence of GETNUMCORES, we check for an invalid arg error // and fall back to GETNUMSPUS if necessary. An 11i v1 build would work // normally on 11i v3, because on PA-RISC cores == spus since there's no // HT on PA-RISC, and 11i v1 only runs on PA-RISC. # ifdef MPC_GETNUMCORES_SYS count = mpctl(MPC_GETNUMCORES_SYS, 0, 0); if (count == -1 && errno == EINVAL) { count = mpctl(MPC_GETNUMSPUS_SYS, 0, 0); } # else count = mpctl(MPC_GETNUMSPUS_SYS, 0, 0); // PA-RISC processor count # endif #endif /* HAVE_SYS_MPCTL_H */ if (count < 1) { Log(LOG_LEVEL_VERBOSE, "invalid processor count: %d", count); return; } Log(LOG_LEVEL_VERBOSE, "Found %d processor%s", count, count > 1 ? "s" : ""); char buf[CF_SMALLBUF] = "1_cpu"; if (count == 1) { EvalContextClassPutHard(ctx, buf, "source=agent,derived-from=sys.cpus"); // "1_cpu" from init - change if buf is ever used above EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cpus", "1", CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=CPU logical cores"); } else { snprintf(buf, CF_SMALLBUF, "%d_cpus", count); EvalContextClassPutHard(ctx, buf, "source=agent,derived-from=sys.cpus"); snprintf(buf, CF_SMALLBUF, "%d", count); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_SYS, "cpus", buf, CF_DATA_TYPE_STRING, "inventory,source=agent,attribute_name=CPU logical cores"); } #endif /* MINGW || NT */ } /******************************************************************/ // Implemented in Windows specific section. #ifndef __MINGW32__ /** Return the number of seconds the system has been online given the current time() as an argument, or return -1 if unavailable or unimplemented. */ int GetUptimeSeconds(time_t now) { time_t boot_time = 0; errno = 0; #if defined(BOOT_TIME_WITH_SYSINFO) // Most GNU, Linux platforms struct sysinfo s; if (sysinfo(&s) == 0) { // Don't return yet, sanity checking below boot_time = now - s.uptime; } #elif defined(BOOT_TIME_WITH_KSTAT) // Solaris platform /* From command line you can get this with: kstat -p unix:0:system_misc:boot_time */ kstat_ctl_t *kc = kstat_open(); if(kc != 0) { kstat_t *kp = kstat_lookup(kc, "unix", 0, "system_misc"); if(kp != 0) { if (kstat_read(kc, kp, NULL) != -1) { kstat_named_t *knp = kstat_data_lookup(kp, "boot_time"); if (knp != NULL) { boot_time = knp->value.ui32; } } } kstat_close(kc); } #elif defined(BOOT_TIME_WITH_PSTAT_GETPROC) // HP-UX platform only struct pst_status p; if (pstat_getproc(&p, sizeof(p), 0, 1) == 1) { boot_time = (time_t)p.pst_start; } #elif defined(BOOT_TIME_WITH_SYSCTL) // BSD-derived platforms int mib[2] = { CTL_KERN, KERN_BOOTTIME }; struct timeval boot; size_t len = sizeof(boot); if (sysctl(mib, 2, &boot, &len, NULL, 0) == 0) { boot_time = boot.tv_sec; } #elif defined(BOOT_TIME_WITH_PROCFS) struct stat p; if (stat("/proc/1", &p) == 0) { boot_time = p.st_ctime; } #elif defined(BOOT_TIME_WITH_UTMP) /* SystemV, highly portable way */ struct utmp query = { .ut_type = BOOT_TIME }; struct utmp *result; setutent(); result = getutid(&query); if (result != NULL) { boot_time = result->ut_time; } endutent(); #elif defined(BOOT_TIME_WITH_UTMPX) /* POSIX way */ struct utmpx query = { .ut_type = BOOT_TIME }; struct utmpx *result; setutxent(); result = getutxid(&query); if (result != NULL) { boot_time = result->ut_tv.tv_sec; } endutxent(); #endif if(errno) { Log(LOG_LEVEL_VERBOSE, "boot time discovery error: %s", GetErrorStr()); } if(boot_time > now || boot_time <= 0) { Log(LOG_LEVEL_VERBOSE, "invalid boot time found; trying uptime command"); boot_time = GetBootTimeFromUptimeCommand(now); } return boot_time > 0 ? now - boot_time : -1; } #endif // !__MINGW32__ int GetUptimeMinutes(time_t now) { return GetUptimeSeconds(now) / SECONDS_PER_MINUTE; } /******************************************************************/ // Last resort: parse the output of the uptime command with a PCRE regexp // and convert the uptime to boot time using "now" argument. // // The regexp needs to match all variants of the uptime command's output. // Solaris 8/9/10: 10:45am up 109 day(s), 19:56, 1 user, load average: // HP-UX 11.11: 9:24am up 1 min, 1 user, load average: // 8:23am up 23 hrs, 0 users, load average: // 9:33am up 2 days, 10 mins, 0 users, load average: // 11:23am up 2 days, 2 hrs, 0 users, load average: // Red Hat Linux: 10:51:23 up 5 days, 19:54, 1 user, load average: // // UPTIME_BACKREFS must be set to this regexp's maximum backreference // index number (i.e., the count of left-parentheses): #define UPTIME_REGEXP " up (\\d+ day[^,]*,|) *(\\d+( ho?u?r|:(\\d+))|(\\d+) min)" #define UPTIME_BACKREFS 5 #define UPTIME_OVECTOR ((UPTIME_BACKREFS + 1) * 3) static time_t GetBootTimeFromUptimeCommand(time_t now) { FILE *uptimecmd; pcre *rx; int ovector[UPTIME_OVECTOR], i, seconds; char *backref = NULL; const char *uptimepath = "/usr/bin/uptime"; time_t uptime = 0; const char *errptr; int erroffset; rx = pcre_compile(UPTIME_REGEXP, 0, &errptr, &erroffset, NULL); if (rx == NULL) { Log(LOG_LEVEL_DEBUG, "failed to compile regexp to parse uptime command"); return(-1); } // Try "/usr/bin/uptime" first, then "/bin/uptime" uptimecmd = cf_popen(uptimepath, "r", false); uptimecmd = uptimecmd ? uptimecmd : cf_popen((uptimepath + 4), "r", false); if (!uptimecmd) { Log(LOG_LEVEL_ERR, "uptime failed: (cf_popen: %s)", GetErrorStr()); return -1; } size_t uptime_output_size = CF_SMALLBUF; char *uptime_output = xmalloc(uptime_output_size); i = CfReadLine(&uptime_output, &uptime_output_size, uptimecmd); cf_pclose(uptimecmd); if (i == -1 && !feof(uptimecmd)) { Log(LOG_LEVEL_ERR, "Reading uptime output failed. (getline: '%s')", GetErrorStr()); return -1; } if ((i > 0) && (pcre_exec(rx, NULL, (const char *)uptime_output, i, 0, 0, ovector, UPTIME_OVECTOR) > 1)) { for (i = 1; i <= UPTIME_BACKREFS ; i++) { if (ovector[i * 2 + 1] - ovector[i * 2] == 0) // strlen(backref) { continue; } backref = uptime_output + ovector[i * 2]; // atoi() ignores non-digits, so no need to null-terminate backref switch(i) { case 1: // Day seconds = SECONDS_PER_DAY; break; case 2: // Hour seconds = SECONDS_PER_HOUR; break; case 4: // Minute case 5: seconds = SECONDS_PER_MINUTE; break; default: seconds = 0; } uptime += atoi(backref) * seconds; } } else { Log(LOG_LEVEL_ERR, "uptime PCRE match failed: regexp: '%s', uptime: '%s'", UPTIME_REGEXP, uptime_output); } pcre_free(rx); Log(LOG_LEVEL_VERBOSE, "Reading boot time from uptime command successful."); return(uptime ? (now - uptime) : -1); } void DetectEnvironment(EvalContext *ctx) { GetNameInfo3(ctx); GetInterfacesInfo(ctx); Get3Environment(ctx); BuiltinClasses(ctx); OSClasses(ctx); } cfengine-3.6.2/libenv/sysinfo_priv.h0000644000175100017510000000225212316547775017220 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SYSINFO_PRIV_H #define CFENGINE_SYSINFO_PRIV_H #include void DiscoverVersion(EvalContext *ctx); void DetectDomainName(EvalContext *ctx, const char *orig_nodename); #endif cfengine-3.6.2/libenv/constants.c0000664000175100017510000000350012361573604016462 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include void LoadSystemConstants(EvalContext *ctx) { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_CONST, "dollar", "$", CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_CONST, "n", "\n", CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_CONST, "r", "\r", CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_CONST, "t", "\t", CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_CONST, "endl", "\n", CF_DATA_TYPE_STRING, "source=agent"); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_CONST, "dirsep", FILE_SEPARATOR_STR, CF_DATA_TYPE_STRING, "source=agent"); /* NewScalar("const","0","\0",cf_str); - this cannot work */ } cfengine-3.6.2/libenv/Makefile.in0000664000175100017510000005231412412324464016351 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = libenv DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libenv_la_DEPENDENCIES = am_libenv_la_OBJECTS = constants.lo sysinfo.lo time_classes.lo \ unix_iface.lo zones.lo libenv_la_OBJECTS = $(am_libenv_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libenv_la_SOURCES) DIST_SOURCES = $(libenv_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libenv.la libenv_la_SOURCES = \ constants.c constants.h \ sysinfo.c sysinfo.h sysinfo_priv.h \ time_classes.c time_classes.h \ unix_iface.c unix_iface.h \ zones.c zones.h @SOLARIS_TRUE@libenv_la_LIBADD = -lkstat # Those dependencies are ought to go away ASAP AM_CPPFLAGS = -I$(top_srcdir)/libutils $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) -I$(top_srcdir)/libcfnet \ -I$(top_srcdir)/libpromises CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = config.h.in 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) --foreign libenv/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libenv/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libenv.la: $(libenv_la_OBJECTS) $(libenv_la_DEPENDENCIES) $(EXTRA_libenv_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libenv_la_OBJECTS) $(libenv_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_classes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_iface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zones.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool 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 TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am 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 tags-am uninstall uninstall-am # libcompat dependency .PRECIOUS: ../libcompat/libcompat.la ../libcompat/libcompat.la: $(MAKE) -C ../libcompat $(AM_MAKEFLAGS) libcompat.la # 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: cfengine-3.6.2/libenv/Makefile.am0000664000175100017510000000170312411001073016317 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libenv.la libenv_la_SOURCES = \ constants.c constants.h \ sysinfo.c sysinfo.h sysinfo_priv.h \ time_classes.c time_classes.h \ unix_iface.c unix_iface.h \ zones.c zones.h if SOLARIS libenv_la_LIBADD = -lkstat endif AM_CPPFLAGS = -I$(top_srcdir)/libutils AM_CPPFLAGS += $(OPENSSL_CPPFLAGS) # because libutils needs it AM_CPPFLAGS += $(PCRE_CPPFLAGS) # Those dependencies are ought to go away ASAP AM_CPPFLAGS += -I$(top_srcdir)/libcfnet AM_CPPFLAGS += -I$(top_srcdir)/libpromises CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = config.h.in # libcompat dependency .PRECIOUS: ../libcompat/libcompat.la ../libcompat/libcompat.la: $(MAKE) -C ../libcompat $(AM_MAKEFLAGS) libcompat.la cfengine-3.6.2/libenv/zones.c0000664000175100017510000000426512411001073015573 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #ifdef HAVE_ZONE_H # include #endif #ifndef __MINGW32__ bool IsGlobalZone() { #ifdef HAVE_GETZONEID zoneid_t zid; char zone[ZONENAME_MAX]; zid = getzoneid(); getzonenamebyid(zid, zone, ZONENAME_MAX); if (strcmp(zone, "global") == 0) { return true; } #endif return false; } bool ForeignZone(char *s) { // We want to keep the banner if (strstr(s, "PID")) { return false; } # ifdef HAVE_GETZONEID zoneid_t zid; char *sp, zone[ZONENAME_MAX]; zid = getzoneid(); getzonenamebyid(zid, zone, ZONENAME_MAX); if (strcmp(zone, "global") == 0) { if (StringStartsWith(s, "global") && isspace(s[6])) { for (sp = s + strlen(s) - 1; isspace(*sp); sp--) { *sp = '\0'; } return false; } else { return true; } } # endif return false; } int CurrentZoneName(ARG_UNUSED const char *s) { # ifdef HAVE_GETZONEID zoneid_t zid = getzoneid(); if (zid >= 0) { return getzonenamebyid(zid, s, ZONENAME_MAX); } # endif return -1; } #endif // !__MINGW32__ cfengine-3.6.2/libenv/time_classes.h0000644000175100017510000000216212316547775017141 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_TIME_CLASSES_H #define CFENGINE_TIME_CLASSES_H #include void UpdateTimeClasses(EvalContext *ctx, time_t t); #endif cfengine-3.6.2/libenv/sysinfo.h0000664000175100017510000000240312411001073016124 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SYSINFO_H #define CFENGINE_SYSINFO_H #include void DetectEnvironment(EvalContext *ctx); void CreateHardClassesFromCanonification(EvalContext *ctx, const char *canonified, char *tags); int GetUptimeMinutes(time_t now); int GetUptimeSeconds(time_t now); #endif cfengine-3.6.2/libenv/time_classes.c0000644000175100017510000001627312316547775017144 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static void RemoveTimeClass(EvalContext *ctx, time_t time) { // The first element is the local timezone const char* tz_prefix[2] = { "", "GMT_" }; const char* tz_function[2] = { "localtime_r", "gmtime_r" }; struct tm tz_parsed_time[2]; const struct tm* tz_tm[2] = { localtime_r(&time, &(tz_parsed_time[0])), gmtime_r(&time, &(tz_parsed_time[1])) }; for (int tz = 0; tz < 2; tz++) { int i, j; char buf[CF_BUFSIZE]; if (tz_tm[tz] == NULL) { Log(LOG_LEVEL_ERR, "Unable to parse passed time. (%s: %s)", tz_function[tz], GetErrorStr()); return; } /* Lifecycle */ for( i = 0; i < 3; i++ ) { snprintf(buf, CF_BUFSIZE, "%sLcycle_%d", tz_prefix[tz], i); EvalContextClassRemove(ctx, NULL, buf); } /* Year */ snprintf(buf, CF_BUFSIZE, "%sYr%04d", tz_prefix[tz], tz_parsed_time[tz].tm_year - 1 + 1900); EvalContextClassRemove(ctx, NULL, buf); snprintf(buf, CF_BUFSIZE, "%sYr%04d", tz_prefix[tz], tz_parsed_time[tz].tm_year + 1900); EvalContextClassRemove(ctx, NULL, buf); /* Month */ for( i = 0; i < 12; i++ ) { snprintf(buf, CF_BUFSIZE, "%s%s", tz_prefix[tz], MONTH_TEXT[i]); EvalContextClassRemove(ctx, NULL, buf); } /* Day of week */ for( i = 0; i < 7; i++ ) { snprintf(buf, CF_BUFSIZE, "%s%s", tz_prefix[tz], DAY_TEXT[i]); EvalContextClassRemove(ctx, NULL, buf); } /* Day */ for( i = 1; i < 32; i++ ) { snprintf(buf, CF_BUFSIZE, "%sDay%d", tz_prefix[tz], i); EvalContextClassRemove(ctx, NULL, buf); } /* Shift */ for( i = 0; i < 4; i++ ) { snprintf(buf, CF_BUFSIZE, "%s%s", tz_prefix[tz], SHIFT_TEXT[i]); EvalContextClassRemove(ctx, NULL, buf); } /* Hour */ for( i = 0; i < 24; i++ ) { snprintf(buf, CF_BUFSIZE, "%sHr%02d", tz_prefix[tz], i); EvalContextClassRemove(ctx, NULL, buf); snprintf(buf, CF_BUFSIZE, "%sHr%d", tz_prefix[tz], i); EvalContextClassRemove(ctx, NULL, buf); } /* Quarter */ for( i = 1; i <= 4; i++ ) { snprintf(buf, CF_BUFSIZE, "%sQ%d", tz_prefix[tz], i); EvalContextClassRemove(ctx, NULL, buf); for( j = 0; j < 24; j++ ) { snprintf(buf, CF_BUFSIZE, "%sHr%02d_Q%d", tz_prefix[tz], j, i); EvalContextClassRemove(ctx, NULL, buf); } } /* Minute */ for( i = 0; i < 60; i++ ) { snprintf(buf, CF_BUFSIZE, "%sMin%02d", tz_prefix[tz], i); EvalContextClassRemove(ctx, NULL, buf); } for( i = 0; i < 60; i += 5 ) { snprintf(buf, CF_BUFSIZE, "%sMin%02d_%02d", tz_prefix[tz], i, (i + 5) % 60); EvalContextClassRemove(ctx, NULL, buf); } } } static void AddTimeClass(EvalContext *ctx, time_t time) { // The first element is the local timezone const char* tz_prefix[2] = { "", "GMT_" }; const char* tz_function[2] = { "localtime_r", "gmtime_r" }; struct tm tz_parsed_time[2]; const struct tm* tz_tm[2] = { localtime_r(&time, &(tz_parsed_time[0])), gmtime_r(&time, &(tz_parsed_time[1])) }; for (int tz = 0; tz < 2; tz++) { char buf[CF_BUFSIZE]; int day_text_index, quarter, interval_start, interval_end; if (tz_tm[tz] == NULL) { Log(LOG_LEVEL_ERR, "Unable to parse passed time. (%s: %s)", tz_function[tz], GetErrorStr()); return; } /* Lifecycle */ snprintf(buf, CF_BUFSIZE, "%sLcycle_%d", tz_prefix[tz], ((tz_parsed_time[tz].tm_year + 1900) % 3)); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Year */ snprintf(buf, CF_BUFSIZE, "%sYr%04d", tz_prefix[tz], tz_parsed_time[tz].tm_year + 1900); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Month */ snprintf(buf, CF_BUFSIZE, "%s%s", tz_prefix[tz], MONTH_TEXT[tz_parsed_time[tz].tm_mon]); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Day of week */ /* Monday is 1 in tm_wday, 0 in DAY_TEXT Tuesday is 2 in tm_wday, 1 in DAY_TEXT ... Sunday is 0 in tm_wday, 6 in DAY_TEXT */ day_text_index = (tz_parsed_time[tz].tm_wday + 6) % 7; snprintf(buf, CF_BUFSIZE, "%s%s", tz_prefix[tz], DAY_TEXT[day_text_index]); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Day */ snprintf(buf, CF_BUFSIZE, "%sDay%d", tz_prefix[tz], tz_parsed_time[tz].tm_mday); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Shift */ snprintf(buf, CF_BUFSIZE, "%s%s", tz_prefix[tz], SHIFT_TEXT[tz_parsed_time[tz].tm_hour / 6]); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Hour */ snprintf(buf, CF_BUFSIZE, "%sHr%02d", tz_prefix[tz], tz_parsed_time[tz].tm_hour); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); snprintf(buf, CF_BUFSIZE, "%sHr%d", tz_prefix[tz], tz_parsed_time[tz].tm_hour); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Quarter */ quarter = tz_parsed_time[tz].tm_min / 15 + 1; snprintf(buf, CF_BUFSIZE, "%sQ%d", tz_prefix[tz], quarter); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); snprintf(buf, CF_BUFSIZE, "%sHr%02d_Q%d", tz_prefix[tz], tz_parsed_time[tz].tm_hour, quarter); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); /* Minute */ snprintf(buf, CF_BUFSIZE, "%sMin%02d", tz_prefix[tz], tz_parsed_time[tz].tm_min); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); interval_start = (tz_parsed_time[tz].tm_min / 5) * 5; interval_end = (interval_start + 5) % 60; snprintf(buf, CF_BUFSIZE, "%sMin%02d_%02d", tz_prefix[tz], interval_start, interval_end); EvalContextClassPutHard(ctx, buf, "time_based,source=agent"); } } void UpdateTimeClasses(EvalContext *ctx, time_t t) { RemoveTimeClass(ctx, t); AddTimeClass(ctx, t); } cfengine-3.6.2/m4/0000775000175100017510000000000012413020721013326 5ustar00a10038a1003800000000000000cfengine-3.6.2/m4/cf3_platforms.m40000664000175100017510000000212312411001073016325 0ustar00a10038a1003800000000000000# # OS kernels conditionals. Don't use those unless it is really needed (if code # depends on the *kernel* feature, and even then -- some kernel features are # shared by different kernels). # # Good example: use LINUX to select code which uses inotify and netlink sockets. # Bad example: use LINUX to select code which parses output of coreutils' ps(1). # AM_CONDITIONAL([LINUX], [test -n "`echo ${target_os} | grep linux`"]) AM_CONDITIONAL([MACOSX], [test -n "`echo ${target_os} | grep darwin`"]) AM_CONDITIONAL([SOLARIS], [test -n "`(echo ${target_os} | egrep 'solaris|sunos')`"]) AM_CONDITIONAL([NT], [test -n "`(echo ${target_os} | egrep 'mingw|cygwin')`"]) AM_CONDITIONAL([CYGWIN], [test -n "`(echo ${target_os} | egrep 'cygwin')`"]) AM_CONDITIONAL([AIX], [test -n "`(echo ${target_os} | grep aix)`"]) AM_CONDITIONAL([HPUX], [test -n "`(echo ${target_os} | egrep 'hpux|hp-ux')`"]) AM_CONDITIONAL([FREEBSD], [test -n "`(echo ${target_os} | grep freebsd)`"]) AM_CONDITIONAL([NETBSD], [test -n "`(echo ${target_os} | grep netbsd)`"]) AM_CONDITIONAL([XNU], [test -n "`(echo ${target_os} | grep darwin)`"]) cfengine-3.6.2/m4/cf3_with_library.m40000664000175100017510000000400312411001073017014 0ustar00a10038a1003800000000000000# CF3_WITH_LIBRARY(library-name, checks) # -------------------------------------- # # This function popluates CFLAGS, CPPFLAGS and LDFLAGS from the # --with-$library=PATH and runs a second argument with those options. # # After execution flags are returned to previous state, but available in # ${LIBRARY}_{CFLAGS,LDFLAGS}. Path is available in ${LIBRARY}_PATH. # # Libraries added to LIBS are available as ${LIBRARY}_LIBS afterwards. # AC_DEFUN([CF3_WITH_LIBRARY], [ m4_define([ULN],m4_toupper($1)) # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_[$1]" != xyes && test "x$with_[$1]" != xcheck && test "x$with_[$1]" != x; then test -z "$ULN[]_PATH" && ULN[]_PATH="$with_[$1]" if test "x$with_[$1]" != x/usr && test "x$with_[$1]" != x/; then test -z "$ULN[]_CFLAGS" && ULN[]_CFLAGS="" test -z "$ULN[]_CPPFLAGS" && ULN[]_CPPFLAGS="-I$with_[$1]/include" test -z "$ULN[]_LDFLAGS" && ULN[]_LDFLAGS="-L$with_[$1]/lib" fi else ULN[]_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $ULN[]_CFLAGS" CPPFLAGS="$CPPFLAGS $ULN[]_CPPFLAGS" LDFLAGS="$LDFLAGS $ULN[]_LDFLAGS" # # Run checks passed as argument # $2 # # Pick up any libraries added by tests # test -z "$ULN[]_LIBS" && ULN[]_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_[$1]" != xyes && test "x$with_[$1]" != xcheck; then if test "x$with_[$1]" != x/usr && test "x$with_[$1]" != x/; then ULN[]_LDFLAGS="$ULN[]_LDFLAGS -R$with_[$1]/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" AC_SUBST(ULN[]_PATH) AC_SUBST(ULN[]_CPPFLAGS) AC_SUBST(ULN[]_CFLAGS) AC_SUBST(ULN[]_LDFLAGS) AC_SUBST(ULN[]_LIBS) ]) cfengine-3.6.2/m4/cf3_path_root_prog.m40000664000175100017510000000153712411001073017354 0ustar00a10038a1003800000000000000# CF3_PATH_ROOT_PROG(variable, program, value-if-not-found, path = $PATH) # -------------------------------------- # # This function has almost the same semantics as the AC_PATH_PROG # function. The difference is that this will detect tools that are # runnable by root, but not by the current user. These tools are # typically used not by the build, but by CFEngine itself, after # it is installed. # AC_DEFUN([CF3_PATH_ROOT_PROG], [ found=0 AS_IF([test "x$4" = "x"], [ path=$PATH ], [ path=$4 ]) AS_ECHO_N(["checking for $2... "]) for i in $(echo $path | sed -e 's/:/ /g'); do AS_IF([test -e $i/$2 && ls -ld $i/$2 | grep ['^[^ ][^ ][^ ][xs][^ ][^ ][^ ][^ ][^ ][^ ]'] > /dev/null], [ $1=$i/$2 found=1 break ]) done AS_IF([test "$found" = "1"], [ AS_ECHO(["$][$1"]) ], [ AS_ECHO([no]) $1=$3 ]) ]) cfengine-3.6.2/m4/strndup.m40000664000175100017510000000304212400110676015273 0ustar00a10038a1003800000000000000# strndup.m4 serial 21 dnl Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([cf3_FUNC_STRNDUP], [ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles AC_CHECK_DECLS([strndup]) AC_REPLACE_FUNCS([strndup]) if test $ac_cv_have_decl_strndup = no; then HAVE_DECL_STRNDUP=0 fi if test $ac_cv_func_strndup = yes; then HAVE_STRNDUP=1 # AIX 5.3 has a function that tries to copy the entire range specified # by n, instead of just the length of src. AC_CACHE_CHECK([for working strndup], [cf3_cv_func_strndup_works], [AC_RUN_IFELSE([ AC_LANG_PROGRAM([[#include #include ]], [[ #if !HAVE_DECL_STRNDUP extern #ifdef __cplusplus "C" #endif char *strndup (const char *, size_t); #endif char *s; // Will crash if strndup tries to traverse all 2GB. s = strndup ("string", 2000000000); return 0;]])], [cf3_cv_func_strndup_works=yes], [cf3_cv_func_strndup_works=no], [ changequote(,)dnl case $host_os in aix | aix[3-6]*) cf3_cv_func_strndup_works="guessing no";; *) cf3_cv_func_strndup_works="guessing yes";; esac changequote([,])dnl ])]) case $cf3_cv_func_strndup_works in *no) AC_LIBOBJ([strndup]) ;; esac else HAVE_STRNDUP=0 fi ]) cfengine-3.6.2/m4/ltsugar.m40000644000175100017510000001042412403654557015273 0ustar00a10038a1003800000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file 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. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) cfengine-3.6.2/m4/cf3_check_proper_func.m40000664000175100017510000000316112411001073020000 0ustar00a10038a1003800000000000000dnl dnl Arguments: dnl $1 - function name dnl $2 - headers (to compile $3) dnl $3 - body for compilation dnl $4 - function invocation dnl dnl This macro checks that the function (argument 1) is defined, dnl and that the code piece (arguments 2, 3, like in AC_LANG_PROGRAM) can be dnl compiled. dnl dnl If the code compiles successfully, it defines HAVE_$1_PROPER macro. dnl dnl If the code fails, it adds '$4' to $post_macros variable. dnl If you want rpl_$1.c to be compiled as a replacement, call dnl CF3_REPLACE_PROPER_FUNC with the same function name. dnl dnl ** How to use ** dnl dnl CF3_CHECK_PROPER_FUNC(function, [#include ], [void function(FILE *);], [#define function rpl_function]) dnl CF3_REPLACE_PROPER_FUNC(function) dnl dnl Then in libutils/platform.h: dnl dnl #if !HAVE_FUNCTION_PROPER dnl void rpl_function(FILE *); dnl #endif dnl dnl And libcompat/rpl_function.c: dnl dnl #include "platform.h" dnl dnl void rpl_function(FILE *) { ... } dnl AC_DEFUN([CF3_CHECK_PROPER_FUNC], [ AC_CHECK_FUNC([$1], [], [AC_MSG_ERROR([Unable to find function $1])]) AC_CACHE_CHECK([whether $1 is properly declared], [hw_cv_func_$1_proper], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([$2],[$3])], [hw_cv_func_$1_proper=yes], [hw_cv_func_$1_proper=no])]) AC_SUBST([hw_cv_func_$1_proper]) AS_IF([test "$hw_cv_func_$1_proper" = yes], [AC_DEFINE([HAVE_$1_PROPER], [1], [Define to 1 if you have properly defined `$1' function])], [post_macros="$post_macros $4"]) ]) AC_DEFUN([CF3_REPLACE_PROPER_FUNC], [ AS_IF([test "$hw_cv_func_$1_proper" = "no"], [AC_LIBOBJ(rpl_$1)] ) ]) cfengine-3.6.2/m4/ltoptions.m40000644000175100017510000003007312403654557015647 0ustar00a10038a1003800000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file 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. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) cfengine-3.6.2/m4/acinclude.m40000664000175100017510000001705612236160673015546 0ustar00a10038a1003800000000000000dnl From http://ac-archive.sourceforge.net/ac-archive/acx_pthread.html AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt -mthreads pthread --thread-safe pthread-config pthreadGC2" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD m4_ifdef([AC_PROG_MKDIR_P], [ dnl For automake-1.9.6 && autoconf < 2.62: Ensure MKDIR_P is AC_SUBSTed. m4_define([AC_PROG_MKDIR_P], m4_defn([AC_PROG_MKDIR_P])[ AC_SUBST([MKDIR_P])])], [ dnl For autoconf < 2.60: Backport of AC_PROG_MKDIR_P. AC_DEFUN([AC_PROG_MKDIR_P], [AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake MKDIR_P='$(mkdir_p)' AC_SUBST([MKDIR_P])])]) cfengine-3.6.2/m4/ltversion.m40000644000175100017510000000126212403654557015637 0ustar00a10038a1003800000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file 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. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) cfengine-3.6.2/m4/cf3_gcc_flags.m40000664000175100017510000000374312411001073016237 0ustar00a10038a1003800000000000000dnl #################################################################### dnl Set GCC CFLAGS only if using GCC. dnl #################################################################### AC_MSG_CHECKING(for HP-UX aC) AC_PREPROC_IFELSE([AC_LANG_SOURCE([[ #if defined __HP_cc #This is HP-UX ANSI C #endif ]])], [AC_MSG_RESULT(no)],[AC_MSG_RESULT(yes) CFLAGS="$CFLAGS -Agcc" CPPFLAGS="$CPPFLAGS -Agcc" HP_UX_AC=yes]) AC_MSG_CHECKING(for GCC specific compile flags) if test x"$GCC" = "xyes" && test x"$HP_UX_AC" != x"yes"; then CFLAGS="$CFLAGS -g -Wall" CPPFLAGS="$CPPFLAGS -std=gnu99" AC_MSG_RESULT(yes) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-pointer-sign" AC_MSG_CHECKING(for -Wno-pointer-sign) AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main() {}])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) CFLAGS="$save_CFLAGS"]) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror=implicit-function-declaration" AC_MSG_CHECKING(for -Werror=implicit-function-declaration) AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main() {}])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) CFLAGS="$save_CFLAGS"]) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wunused-parameter" AC_MSG_CHECKING(for -Wunused-parameter) AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main() {}])], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) CFLAGS="$save_CFLAGS"]) dnl Clang does not like 'const const' construct arising from dnl expansion of TYPED_SET_DECLARE macro dnl dnl This check is relying on explicit compilator detection due to dnl GCC irregularities checking for -Wno-* command-line options dnl (command line is not fully checked until actual warning occurs) AC_MSG_CHECKING(for -Wno-duplicate-decl-specifier) AC_COMPILE_IFELSE([AC_LANG_SOURCE([#ifndef __clang__ # error Not a clang #endif int main() {}])], [AC_MSG_RESULT(yes) CFLAGS="$save_CFLAGS -Wno-duplicate-decl-specifier"], [AC_MSG_RESULT(no)]) else AC_MSG_RESULT(no) fi cfengine-3.6.2/m4/libtool.m40000644000175100017510000106011112403654557015255 0ustar00a10038a1003800000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file 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. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS cfengine-3.6.2/m4/lt~obsolete.m40000644000175100017510000001375612403654557016177 0ustar00a10038a1003800000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file 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. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) cfengine-3.6.2/m4/adl_recursive_eval.m40000664000175100017510000000116712236160673017451 0ustar00a10038a1003800000000000000dnl adl_RECURSIVE_EVAL(VALUE, RESULT) dnl ================================= dnl Interpolate the VALUE in loop until it doesn't change, dnl and set the result to $RESULT. dnl WARNING: It's easy to get an infinite loop with some unsane input. AC_DEFUN([adl_RECURSIVE_EVAL], [_lcl_receval="$1" $2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do _lcl_receval_old="[$]_lcl_receval" eval _lcl_receval="\"[$]_lcl_receval\"" done echo "[$]_lcl_receval")`]) cfengine-3.6.2/m4/old-autoconf.m40000664000175100017510000001260712236160673016206 0ustar00a10038a1003800000000000000AC_DEFUN([AC_TYPE_LONG_DOUBLE], [ AC_CACHE_CHECK([for long double], [ac_cv_type_long_double], [if test "$GCC" = yes; then ac_cv_type_long_double=yes else AC_COMPILE_IFELSE( [AC_LANG_BOOL_COMPILE_TRY( [[/* The Stardent Vistra knows sizeof (long double), but does not support it. */ long double foo = 0.0L;]], [[/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ sizeof (double) <= sizeof (long double)]])], [ac_cv_type_long_double=yes], [ac_cv_type_long_double=no]) fi]) if test $ac_cv_type_long_double = yes; then AC_DEFINE([HAVE_LONG_DOUBLE], 1, [Define to 1 if the system has the type `long double'.]) fi ]) AC_DEFUN([AC_TYPE_LONG_LONG_INT], [ AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], [AC_LINK_IFELSE( [_AC_TYPE_LONG_LONG_SNIPPET], [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. dnl If cross compiling, assume the bug isn't important, since dnl nobody cross compiles for this platform as far as we know. AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[@%:@include @%:@ifndef LLONG_MAX @%:@ define HALF \ (1LL << (sizeof (long long int) * CHAR_BIT - 2)) @%:@ define LLONG_MAX (HALF - 1 + HALF) @%:@endif]], [[long long int n = 1; int i; for (i = 0; ; i++) { long long int m = n << i; if (m >> i != n) return 1; if (LLONG_MAX / 2 < m) break; } return 0;]])], [ac_cv_type_long_long_int=yes], [ac_cv_type_long_long_int=no], [ac_cv_type_long_long_int=yes])], [ac_cv_type_long_long_int=no])]) if test $ac_cv_type_long_long_int = yes; then AC_DEFINE([HAVE_LONG_LONG_INT], 1, [Define to 1 if the system has the type `long long int'.]) fi ]) AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], [ AC_CACHE_CHECK([for unsigned long long int], [ac_cv_type_unsigned_long_long_int], [AC_LINK_IFELSE( [_AC_TYPE_LONG_LONG_SNIPPET], [ac_cv_type_unsigned_long_long_int=yes], [ac_cv_type_unsigned_long_long_int=no])]) if test $ac_cv_type_unsigned_long_long_int = yes; then AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, [Define to 1 if the system has the type `unsigned long long int'.]) fi ]) AC_DEFUN([AC_TYPE_INTMAX_T], [ AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) AC_CHECK_TYPE([intmax_t], [AC_DEFINE([HAVE_INTMAX_T], 1, [Define to 1 if the system has the type `intmax_t'.])], [test $ac_cv_type_long_long_int = yes \ && ac_type='long long int' \ || ac_type='long int' AC_DEFINE_UNQUOTED([intmax_t], [$ac_type], [Define to the widest signed integer type if and do not define.])]) ]) AC_DEFUN([AC_TYPE_UINTMAX_T], [ AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) AC_CHECK_TYPE([uintmax_t], [AC_DEFINE([HAVE_UINTMAX_T], 1, [Define to 1 if the system has the type `uintmax_t'.])], [test $ac_cv_type_unsigned_long_long_int = yes \ && ac_type='unsigned long long int' \ || ac_type='unsigned long int' AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type], [Define to the widest unsigned integer type if and do not define.])]) ]) AC_DEFUN([AC_TYPE_UINTPTR_T], [ AC_CHECK_TYPE([uintptr_t], [AC_DEFINE([HAVE_UINTPTR_T], 1, [Define to 1 if the system has the type `uintptr_t'.])], [for ac_type in 'unsigned int' 'unsigned long int' \ 'unsigned long long int'; do AC_COMPILE_IFELSE( [AC_LANG_BOOL_COMPILE_TRY( [AC_INCLUDES_DEFAULT], [[sizeof (void *) <= sizeof ($ac_type)]])], [AC_DEFINE_UNQUOTED([uintptr_t], [$ac_type], [Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it.]) ac_type=]) test -z "$ac_type" && break done]) ]) AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], [ AC_LANG_PROGRAM( [[/* For now, do not test the preprocessor; as of 2007 there are too many implementations with broken preprocessors. Perhaps this can be revisited in 2012. In the meantime, code should not expect #if to work with literals wider than 32 bits. */ /* Test literals. */ long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; unsigned long long int ull = 18446744073709551615ULL; /* Test constant expressions. */ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63;]], [[/* Test availability of runtime routines for shift and division. */ long long int llmax = 9223372036854775807ll; unsigned long long int ullmax = 18446744073709551615ull; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ullmax / ull) | (ullmax % ull));]]) ]) cfengine-3.6.2/m4/snprintf.m40000664000175100017510000002237612400110676015452 0ustar00a10038a1003800000000000000# $Id: snprintf.m4,v 1.1.1.1 2008/01/06 03:24:00 holger Exp $ # Copyright (c) 2008 Holger Weiss . # # This code may freely be used, modified and/or redistributed for any purpose. # It would be nice if additions and fixes to this file (including trivial code # cleanups) would be sent back in order to let me include them in the version # available at . However, this is # not a requirement for using or redistributing (possibly modified) versions of # this file, nor is leaving this notice intact mandatory. # HW_HEADER_STDARG_H # ------------------ # Define HAVE_STDARG_H to 1 if is available. AC_DEFUN([HW_HEADER_STDARG_H], [ AC_CHECK_HEADERS([stdarg.h]) ])# HW_HEADER_STDARG_H # HW_HEADER_VARARGS_H # ------------------- # Define HAVE_VARARGS_H to 1 if is available. AC_DEFUN([HW_HEADER_VARARGS_H], [ AC_CHECK_HEADERS([varargs.h]) ])# HW_HEADER_VARARGS_H # HW_FUNC_VA_COPY # --------------- # Set $hw_cv_func_va_copy to "yes" or "no". Define HAVE_VA_COPY to 1 if # $hw_cv_func_va_copy is set to "yes". Note that it's "unspecified whether # va_copy and va_end are macros or identifiers declared with external linkage." # (C99: 7.15.1, 1) Therefore, the presence of va_copy(3) cannot simply "be # tested with #ifdef", as suggested by the Autoconf manual (5.5.1). AC_DEFUN([HW_FUNC_VA_COPY], [ AC_REQUIRE([HW_HEADER_STDARG_H])dnl Our check evaluates HAVE_STDARG_H. AC_REQUIRE([HW_HEADER_VARARGS_H])dnl Our check evaluates HAVE_VARARGS_H. AC_CACHE_CHECK([for va_copy], [hw_cv_func_va_copy], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#if HAVE_STDARG_H #include #elif HAVE_VARARGS_H #include #endif]], [[va_list ap, aq; va_copy(aq, ap);]])], [hw_cv_func_va_copy=yes], [hw_cv_func_va_copy=no], [hw_cv_func_va_copy=no])]) AS_IF([test "$hw_cv_func_va_copy" = yes], [AC_DEFINE([HAVE_VA_COPY], [1], [Define to 1 if you have the `va_copy' function or macro.])]) ])# HW_FUNC_VA_COPY # HW_FUNC___VA_COPY # ----------------- # Set $hw_cv_func___va_copy to "yes" or "no". Define HAVE___VA_COPY to 1 if # $hw_cv_func___va_copy is set to "yes". AC_DEFUN([HW_FUNC___VA_COPY], [ AC_REQUIRE([HW_HEADER_STDARG_H])dnl Our check evaluates HAVE_STDARG_H. AC_REQUIRE([HW_HEADER_VARARGS_H])dnl Our check evaluates HAVE_VARARGS_H. AC_CACHE_CHECK([for __va_copy], [hw_cv_func___va_copy], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#if HAVE_STDARG_H #include #elif HAVE_VARARGS_H #include #endif]], [[va_list ap, aq; __va_copy(aq, ap);]])], [hw_cv_func___va_copy=yes], [hw_cv_func___va_copy=no], [hw_cv_func___va_copy=no])]) AS_IF([test "$hw_cv_func___va_copy" = yes], [AC_DEFINE([HAVE___VA_COPY], [1], [Define to 1 if you have the `__va_copy' function or macro.])]) ])# HW_FUNC___VA_COPY # HW_FUNC_VSNPRINTF # ----------------- # Set $hw_cv_func_vsnprintf and $hw_cv_func_vsnprintf_c99 to "yes" or "no", # respectively. Define HAVE_VSNPRINTF to 1 only if $hw_cv_func_vsnprintf_c99 # is set to "yes". Otherwise, define vsnprintf to rpl_vsnprintf and make sure # the replacement function will be built. AC_DEFUN([HW_FUNC_VSNPRINTF], [ AC_REQUIRE([HW_HEADER_STDARG_H])dnl Our check evaluates HAVE_STDARG_H. dnl The folowing checks are not *required* to HAVE_VSNPRINTF, but they dnl should be checked (and pass!) for the test in snprintf.c to pass. AC_CHECK_HEADERS([inttypes.h locale.h stddef.h stdint.h]) AC_CHECK_MEMBERS([struct lconv.decimal_point, struct lconv.thousands_sep], [], [], [#include ]) AC_TYPE_LONG_DOUBLE AC_TYPE_LONG_LONG_INT AC_TYPE_UNSIGNED_LONG_LONG_INT AC_TYPE_SIZE_T AC_TYPE_INTMAX_T AC_TYPE_UINTMAX_T AC_TYPE_UINTPTR_T AC_CHECK_TYPES([ptrdiff_t]) AC_CHECK_FUNCS([localeconv]) AC_CHECK_FUNC([vsnprintf], [hw_cv_func_vsnprintf=yes], [hw_cv_func_vsnprintf=no]) AS_IF([test "$hw_cv_func_vsnprintf" = yes], [AC_CACHE_CHECK([whether vsnprintf is C99 compliant], [hw_cv_func_vsnprintf_c99], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#if HAVE_STDARG_H #include #endif #include static int testprintf(char *buf, size_t size, const char *format, ...) { int result; va_list ap; va_start(ap, format); result = vsnprintf(buf, size, format, ap); va_end(ap); return result; }]], [[char buf[43]; if (testprintf(buf, 4, "The answer is %27.2g.", 42.0) != 42 || testprintf(buf, 0, "No, it's %32zu.", (size_t)42) != 42 || buf[0] != 'T' || buf[3] != '\0' || testprintf(NULL, 0, "") != 0 || /* POSSIBLE SEGFAULT ON NON-C99 LIBCs!!! */ testprintf(NULL, 0, "Some actual %18s formatting.\nblah %d.\n", "42", 1) != 51) return 1;]])], [hw_cv_func_vsnprintf_c99=yes], [hw_cv_func_vsnprintf_c99=no], [hw_cv_func_vsnprintf_c99=no])])], [hw_cv_func_snprintf_c99=no]) AS_IF( [test "$hw_cv_func_vsnprintf_c99" = yes], [AC_DEFINE([HAVE_VSNPRINTF], [1], [Define to 1 if you have a C99 compliant `vsnprintf' function.])], [ AC_DEFINE([vsnprintf], [rpl_vsnprintf], [Define to rpl_vsnprintf if the replacement function should be used.]) AC_DEFINE([vprintf], [rpl_vprintf], [Define to rpl_vprintf if the replacement function should be used.]) AC_DEFINE([vfprintf], [rpl_vfprintf], [Define to rpl_vfprintf if the replacement function should be used.]) _HW_FUNC_XPRINTF_REPLACE ]) ])# HW_FUNC_VSNPRINTF # HW_FUNC_SNPRINTF # ---------------- # Set $hw_cv_func_snprintf and $hw_cv_func_snprintf_c99 to "yes" or "no", # respectively. Define HAVE_SNPRINTF to 1 only if $hw_cv_func_snprintf_c99 # is set to "yes". Otherwise, define snprintf to rpl_snprintf and make sure # the replacement function will be built. AC_DEFUN([HW_FUNC_SNPRINTF], [ AC_REQUIRE([HW_FUNC_VSNPRINTF])dnl Our snprintf(3) calls vsnprintf(3). AC_CHECK_FUNC([snprintf], [hw_cv_func_snprintf=yes], [hw_cv_func_snprintf=no]) AS_IF([test "$hw_cv_func_snprintf" = yes], [AC_CACHE_CHECK([whether snprintf is C99 compliant], [hw_cv_func_snprintf_c99], [AC_RUN_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[char buf[43]; if (snprintf(buf, 4, "The answer is %27.2g.", 42.0) != 42 || snprintf(buf, 0, "No, it's %32zu.", (size_t)42) != 42 || buf[0] != 'T' || buf[3] != '\0' || snprintf(NULL, 0, "") != 0 || /* POSSIBLE SEGFAULT ON NON-C99 LIBCs!!! */ snprintf(NULL, 0, "Some actual %18s formatting.\nblah %d.\n", "42", 1) != 51) return 1;]])], [hw_cv_func_snprintf_c99=yes], [hw_cv_func_snprintf_c99=no], [hw_cv_func_snprintf_c99=no])])], [hw_cv_func_snprintf_c99=no]) AS_IF( [test "$hw_cv_func_snprintf_c99" = yes], [AC_DEFINE([HAVE_SNPRINTF], [1], [Define to 1 if you have a C99 compliant `snprintf' function.])], [ AC_DEFINE([snprintf], [rpl_snprintf], [Define to rpl_snprintf if the replacement function should be used.]) AC_DEFINE([printf], [rpl_printf], [Define to rpl_printf if the replacement function should be used.]) AC_DEFINE([fprintf], [rpl_fprintf], [Define to rpl_fprintf if the replacement function should be used.]) _HW_FUNC_XPRINTF_REPLACE ]) ])# HW_FUNC_SNPRINTF # HW_FUNC_VASPRINTF # ----------------- # Set $hw_cv_func_vasprintf to "yes" or "no". Define HAVE_VASPRINTF to 1 if # $hw_cv_func_vasprintf is set to "yes". Otherwise, define vasprintf to # rpl_vasprintf and make sure the replacement function will be built. AC_DEFUN([HW_FUNC_VASPRINTF], [ AC_REQUIRE([HW_FUNC_VSNPRINTF])dnl Our vasprintf(3) calls vsnprintf(3). AC_CHECK_FUNCS([vasprintf], [hw_cv_func_vasprintf=yes], [hw_cv_func_vasprintf=no]) AS_IF([test "$hw_cv_func_vasprintf" = no], [AC_DEFINE([vasprintf], [rpl_vasprintf], [Define to rpl_vasprintf if the replacement function should be used.]) AC_CHECK_HEADERS([stdlib.h]) HW_FUNC_VA_COPY AS_IF([test "$hw_cv_func_va_copy" = no], [HW_FUNC___VA_COPY]) _HW_FUNC_XPRINTF_REPLACE]) ])# HW_FUNC_VASPRINTF # HW_FUNC_ASPRINTF # ---------------- # Set $hw_cv_func_asprintf to "yes" or "no". Define HAVE_ASPRINTF to 1 if # $hw_cv_func_asprintf is set to "yes". Otherwise, define asprintf to # rpl_asprintf and make sure the replacement function will be built. AC_DEFUN([HW_FUNC_ASPRINTF], [ AC_REQUIRE([HW_FUNC_VASPRINTF])dnl Our asprintf(3) calls vasprintf(3). AC_CHECK_FUNCS([asprintf], [hw_cv_func_asprintf=yes], [hw_cv_func_asprintf=no]) AS_IF([test "$hw_cv_func_asprintf" = no], [AC_DEFINE([asprintf], [rpl_asprintf], [Define to rpl_asprintf if the replacement function should be used.]) _HW_FUNC_XPRINTF_REPLACE]) ])# HW_FUNC_ASPRINTF # _HW_FUNC_XPRINTF_REPLACE # ------------------------ # Arrange for building snprintf.c. Must be called if one or more of the # functions provided by snprintf.c are needed. AC_DEFUN([_HW_FUNC_XPRINTF_REPLACE], [ AC_C_CONST HW_HEADER_STDARG_H AC_LIBOBJ([snprintf]) ])# _HW_FUNC_XPRINTF_REPLACE dnl vim: set joinspaces textwidth=80: cfengine-3.6.2/test-driver0000755000175100017510000001027712403654567015235 0ustar00a10038a1003800000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2013 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then estatus=1 fi case $estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: cfengine-3.6.2/install-sh0000755000175100017510000003325512403654565015042 0ustar00a10038a1003800000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: cfengine-3.6.2/aclocal.m40000664000175100017510000012704112412324462014663 0ustar00a10038a1003800000000000000# generated automatically by aclocal 1.14.1 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file 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. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file 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. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.14' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.14.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.14.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file 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. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file 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. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file 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. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file 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 macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file 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. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Copyright (C) 1998-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_LEX # ----------- # Autoconf leaves LEX=: if lex or flex can't be found. Change that to a # "missing" invocation, for better error output. AC_DEFUN([AM_PROG_LEX], [AC_PREREQ([2.50])dnl AC_REQUIRE([AM_MISSING_HAS_RUN])dnl AC_REQUIRE([AC_PROG_LEX])dnl if test "$LEX" = :; then LEX=${am_missing_run}flex fi]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file 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. # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file 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. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file 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. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file 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. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file 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. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file 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. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file 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. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/acinclude.m4]) m4_include([m4/adl_recursive_eval.m4]) m4_include([m4/cf3_check_proper_func.m4]) m4_include([m4/cf3_path_root_prog.m4]) m4_include([m4/cf3_with_library.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/old-autoconf.m4]) m4_include([m4/snprintf.m4]) m4_include([m4/strndup.m4]) cfengine-3.6.2/Makefile.in0000664000175100017510000010270512412324463015071 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ DIST_COMMON = README.md Makefile.am Makefile.in configure AUTHORS \ aclocal.m4 ChangeLog INSTALL config.guess config.sub depcomp \ install-sh ltmain.sh missing ylwrap m4/acinclude.m4 \ m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ m4/lt~obsolete.m4 m4/cf3_with_library.m4 m4/snprintf.m4 \ m4/old-autoconf.m4 m4/adl_recursive_eval.m4 m4/strndup.m4 \ m4/cf3_check_proper_func.m4 m4/cf3_platforms.m4 \ m4/cf3_gcc_flags.m4 m4/cf3_path_root_prog.m4 configure.ac \ autogen.sh configure_flags.env.in subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = configure_flags.env CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(docsdir)" DATA = $(docs_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ AUTOMAKE_OPTIONS = foreign MAKEFLAGS = $(if $(filter-out 0,$(V)),,--no-print-directory --quiet) LCOV_FLAGS = $(if $(filter-out 0,$(V)),,-q) SUBDIRS = libcompat libutils libcfnet libenv libpromises \ cf-agent cf-execd cf-key cf-monitord \ cf-promises cf-runagent cf-serverd cf-upgrade ext examples \ tests DIST_SUBDIRS = libcompat libutils libcfnet libenv libpromises cf-agent cf-execd \ cf-key cf-monitord cf-promises cf-runagent cf-serverd cf-upgrade ext \ examples tests EXTRA_DIST = ChangeLog INSTALL README.md LICENSE docsdir = $(docdir) docs_DATA = README.md ChangeLog # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \ configure install-sh missing mkinstalldirs depcomp ylwrap \ ltmain.sh mdate-sh # # Pass proper flags to aclocal to pick up Libtool macros # ACLOCAL_AMFLAGS = -I m4 ################################################################################ # Identical to what is in libpromises/Makefile.am. # This is because there is a circular dependency libcfnet <-> libpromises # so we need to generate it before everything else. ################################################################################ BUILT_SOURCES = \ $(srcdir)/libpromises/enterprise_extension.c \ $(srcdir)/libpromises/enterprise_extension.h ENTERPRISE_EXTENSION_GENERATE = $(SED) -f $(srcdir)/libpromises/enterprise_extension.sed $< > $@ ENTERPRISE_EXTENSION_MAKE = @if test -z "$(V)"; then echo " SED " $@; else echo "$(ENTERPRISE_EXTENSION_GENERATE)"; fi; $(ENTERPRISE_EXTENSION_GENERATE) # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = cfengine-lcov-base.info cfengine-lcov.info \ $(BUILT_SOURCES) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): configure_flags.env: $(top_builddir)/config.status $(srcdir)/configure_flags.env.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-docsDATA: $(docs_DATA) @$(NORMAL_INSTALL) @list='$(docs_DATA)'; test -n "$(docsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docsdir)" || exit $$?; \ done uninstall-docsDATA: @$(NORMAL_UNINSTALL) @list='$(docs_DATA)'; test -n "$(docsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docsdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(docsdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) 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 "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-data-local install-docsDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-docsDATA .MAKE: $(am__recursive_targets) all check install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-data-local install-docsDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-docsDATA install-data-local: $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/inputs $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/modules $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/outputs $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/ppkeys # # Code coverage # clean-coverage: find -L $(srcdir) -name '*.gcda' -delete run-coverage: -$(MAKE) check -k collect-coverage: $(LCOV) $(LCOV_FLAGS) --capture --initial --directory . --output-file cfengine-lcov-base.info $(LCOV) $(LCOV_FLAGS) --capture --directory . --output-file cfengine-lcov.info --test-name CFENGINE --no-checksum --compat-libtool $(LCOV) $(LCOV_FLAGS) -a cfengine-lcov-base.info -a cfengine-lcov.info --output-file cfengine-lcov.info $(LCOV) $(LCOV_FLAGS) --remove cfengine-lcov.info '/usr/include/*' --output-file cfengine-lcov.info LANG=C $(LCOV_GENHTML) $(LCOV_FLAGS) --prefix . --output-directory coverage-html --title "CFEngine Code Coverage" --legend --show-details cfengine-lcov.info @echo @echo " Code coverage information: file://"`pwd`"/coverage-html/index.html" @echo coverage: clean-coverage run-coverage collect-coverage $(srcdir)/libpromises/enterprise_extension.c: libpromises/extensions_template.c libpromises/enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) $(srcdir)/libpromises/enterprise_extension.h: libpromises/extensions_template.h libpromises/enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) # 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: cfengine-3.6.2/libcompat/0000775000175100017510000000000012413020721014760 5ustar00a10038a1003800000000000000cfengine-3.6.2/libcompat/round.c0000664000175100017510000000274312243421446016273 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_ROUND double round(double x); #endif double round(double x) { if (x >= 0.0) { double y = floor(x); if (x - y >= 0.5) { return y + 1.0; } else { return y; } } else { double y = ceil(x); if (y - x >= 0.5) { return y - 1.0; } else { return y; } } } cfengine-3.6.2/libcompat/strstr.c0000664000175100017510000000262012243421446016477 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_STRSTR char *strstr(const char *haystack, const char *needle); #endif char *strstr(const char *haystack, const char *needle) { size_t needlelen = strlen(needle); for (const char *sp = haystack; *sp; sp++) { if (strncmp(sp, needle, needlelen) == 0) { return (char *) sp; } } return NULL; } cfengine-3.6.2/libcompat/localtime_r.c0000664000175100017510000000276012243421446017435 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_LOCALTIME_R struct tm *localtime_r(const time_t *timep, struct tm *result); #endif #if defined(__MINGW32__) /* On Windows, localtime buffer is thread-specific, so using it in place of the reentrant version is safe */ struct tm *localtime_r(const time_t *timep, struct tm *result) { struct tm *ret = localtime(timep); if (ret) { memcpy(result, ret, sizeof(struct tm)); } return ret; } #endif cfengine-3.6.2/libcompat/getloadavg.c0000644000175100017510000006245612316547775017305 0ustar00a10038a1003800000000000000/* Get the system load averages. Copyright (C) 1985, 86, 87, 88, 89, 91, 92, 93, 1994, 1995, 1997 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Compile-time symbols that this file uses: HAVE_PSTAT_GETDYNAMIC Define this if your system has the pstat_getdynamic function. I think it is unique to HPUX9. The best way to get the definition is through the AC_FUNC_GETLOADAVG macro that comes with autoconf 2.13 or newer. If that isn't an option, then just put AC_CHECK_FUNCS(pstat_getdynamic) in your configure.in file. FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. KERNEL_FILE Pathname of the kernel to nlist. LDAV_CVT() Scale the load average from the kernel. Returns a double. LDAV_SYMBOL Name of kernel symbol giving load average. LOAD_AVE_TYPE Type of the load average array in the kernel. Must be defined unless one of apollo, DGUX, NeXT, or UMAX is defined; or we have libkstat; otherwise, no load average is available. NLIST_STRUCT Include nlist.h, not a.out.h, and the nlist n_name element is a pointer, not an array. NLIST_NAME_UNION struct nlist has an n_un member, not n_name. LINUX_LDAV_FILE [__linux__]: File containing load averages. Specific system predefines this file uses, aside from setting default values if not emacs: apollo BSD Real BSD, not just BSD-like. convex DGUX eunice UNIX emulator under VMS. hpux __MSDOS__ No-op for MSDOS. NeXT sgi sequent Sequent Dynix 3.x.x (BSD) _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV) sony_news NEWS-OS (works at least for 4.1C) UMAX UMAX4_3 VMS WINDOWS32 No-op for Windows95/NT. __linux__ Linux: assumes /proc filesystem mounted. Support from Michael K. Johnson. __NetBSD__ NetBSD: assumes /kern filesystem mounted. In addition, to avoid nesting many #ifdefs, we internally set LDAV_DONE to indicate that the load average has been computed. We also #define LDAV_PRIVILEGED if a program will require special installation to be able to call getloadavg. */ /* This should always be first. */ # include #ifdef HAVE_NLIST_H /* What autoconf defines. */ # undef NLIST_STRUCT # define NLIST_STRUCT #endif #include /* Both the Emacs and non-Emacs sections want this. Some configuration files' definitions for the LOAD_AVE_CVT macro (like sparc.h's) use macros like FSCALE, defined here. */ #if defined (unix) || defined (__unix) # include #endif /* Exclude all the code except the test program at the end if the system has its own `getloadavg' function. The declaration of `errno' is needed by the test program as well as the function itself, so it comes first. */ #include #ifndef errno extern int errno; #endif #ifndef HAVE_GETLOADAVG /* The existing Emacs configuration files define a macro called LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and returns the load average multiplied by 100. What we actually want is a macro called LDAV_CVT, which returns the load average as an unmultiplied double. For backwards compatibility, we'll define LDAV_CVT in terms of LOAD_AVE_CVT, but future machine config files should just define LDAV_CVT directly. */ # if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT) # define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0) # endif # if !defined (BSD) && defined (ultrix) /* Ultrix behaves like BSD on Vaxen. */ # define BSD # endif # ifdef NeXT /* NeXT in the 2.{0,1,2} releases defines BSD in , which conflicts with the definition understood in this file, that this really is BSD. */ # undef BSD /* NeXT defines FSCALE in . However, we take FSCALE being defined to mean that the nlist method should be used, which is not true. */ # undef FSCALE # endif /* Same issues as for NeXT apply to the HURD-based GNU system. */ # ifdef __GNU__ # undef BSD # undef FSCALE # endif /* __GNU__ */ /* Set values that are different from the defaults, which are set a little farther down with #ifndef. */ /* Some shorthands. */ # if defined (HPUX) && !defined (hpux) # define hpux # endif # if defined (__hpux) && !defined (hpux) # define hpux # endif # if defined (__sun) && !defined (sun) # define sun # endif # if defined(hp300) && !defined(hpux) # define MORE_BSD # endif # if defined(ultrix) && defined(mips) # define decstation # endif # if defined (__SVR4) && !defined (SVR4) # define SVR4 # endif # if (defined(sun) && defined(SVR4)) || defined (SOLARIS2) # define SUNOS_5 # endif # if defined (__osf__) && (defined (__alpha) || defined (__alpha__)) # define OSF_ALPHA # include # include # include # include # endif # if defined (__osf__) && (defined (mips) || defined (__mips__)) # define OSF_MIPS # include # endif /* UTek's /bin/cc on the 4300 has no architecture specific cpp define by default, but _MACH_IND_SYS_TYPES is defined in . Combine that with a couple of other things and we'll have a unique match. */ # if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES) # define tek4300 /* Define by emacs, but not by other users. */ # endif /* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */ # ifndef LOAD_AVE_TYPE # ifdef MORE_BSD # define LOAD_AVE_TYPE long # endif # ifdef sun # define LOAD_AVE_TYPE long # endif # ifdef decstation # define LOAD_AVE_TYPE long # endif # ifdef _SEQUENT_ # define LOAD_AVE_TYPE long # endif # ifdef sgi # define LOAD_AVE_TYPE long # endif # ifdef SVR4 # define LOAD_AVE_TYPE long # endif # ifdef sony_news # define LOAD_AVE_TYPE long # endif # ifdef sequent # define LOAD_AVE_TYPE long # endif # ifdef OSF_ALPHA # define LOAD_AVE_TYPE long # endif # if defined (ardent) && defined (titan) # define LOAD_AVE_TYPE long # endif # ifdef tek4300 # define LOAD_AVE_TYPE long # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ # define LOAD_AVE_TYPE long # endif # ifdef _AIX # define LOAD_AVE_TYPE long # endif # ifdef convex # define LOAD_AVE_TYPE double # ifndef LDAV_CVT # define LDAV_CVT(n) (n) # endif # endif # endif /* No LOAD_AVE_TYPE. */ # ifdef OSF_ALPHA /* defines an incorrect value for FSCALE on Alpha OSF/1, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 1024.0 # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ /* defines an incorrect value for FSCALE on an Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 100.0 # endif # ifndef FSCALE /* SunOS and some others define FSCALE in sys/param.h. */ # ifdef MORE_BSD # define FSCALE 2048.0 # endif # if defined(MIPS) || defined(SVR4) || defined(decstation) # define FSCALE 256 # endif # if defined (sgi) || defined (sequent) /* Sometimes both MIPS and sgi are defined, so FSCALE was just defined above under #ifdef MIPS. But we want the sgi value. */ # undef FSCALE # define FSCALE 1000.0 # endif # if defined (ardent) && defined (titan) # define FSCALE 65536.0 # endif # ifdef tek4300 # define FSCALE 100.0 # endif # ifdef _AIX # define FSCALE 65536.0 # endif # endif /* Not FSCALE. */ # if !defined (LDAV_CVT) && defined (FSCALE) # define LDAV_CVT(n) (((double) (n)) / FSCALE) # endif # if defined(sgi) || (defined(mips) && !defined(BSD)) # define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31)) # endif # if !defined (KERNEL_FILE) && defined (sequent) # define KERNEL_FILE "/dynix" # endif # if !defined (KERNEL_FILE) && defined (hpux) # define KERNEL_FILE "/hp-ux" # endif # if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan))) # define KERNEL_FILE "/unix" # endif # if !defined (LDAV_SYMBOL) && defined (alliant) # define LDAV_SYMBOL "_Loadavg" # endif # if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX)) # define LDAV_SYMBOL "avenrun" # endif # ifdef HAVE_UNISTD_H # include # endif # include /* LOAD_AVE_TYPE should only get defined if we're going to use the nlist method. */ # if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) # define LOAD_AVE_TYPE double # endif # ifdef LOAD_AVE_TYPE # ifndef VMS # ifndef __linux__ # ifndef NLIST_STRUCT # include # else /* NLIST_STRUCT */ # include # endif /* NLIST_STRUCT */ # ifdef SUNOS_5 # include //# include # include # endif # if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) # include # endif # ifndef KERNEL_FILE # define KERNEL_FILE "/vmunix" # endif /* KERNEL_FILE */ # ifndef LDAV_SYMBOL # define LDAV_SYMBOL "_avenrun" # endif /* LDAV_SYMBOL */ # endif /* __linux__ */ # else /* VMS */ # ifndef eunice # include # include # else /* eunice */ # include # endif /* eunice */ # endif /* VMS */ # ifndef LDAV_CVT # define LDAV_CVT(n) ((double) (n)) # endif /* !LDAV_CVT */ # endif /* LOAD_AVE_TYPE */ # if defined(__GNU__) && !defined (NeXT) /* Note that NeXT Openstep defines __GNU__ even though it should not. */ /* GNU system acts much like NeXT, for load average purposes, but not exactly. */ # define NeXT # define host_self mach_host_self # endif # ifdef NeXT # ifdef HAVE_MACH_MACH_H # include # else # include # endif # endif /* NeXT */ # ifdef sgi # include # endif /* sgi */ # ifdef UMAX # include # include # include # include # include # ifdef UMAX_43 # include # include # include # include # include # else /* Not UMAX_43. */ # include # include # include # include # include # include # endif /* Not UMAX_43. */ # endif /* UMAX */ # ifdef DGUX # include # endif # if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION) # include # else # include # endif /* Avoid static vars inside a function since in HPUX they dump as pure. */ # ifdef NeXT static processor_set_t default_set; static int getloadavg_initialized; # endif /* NeXT */ # ifdef UMAX static unsigned int cpus = 0; static unsigned int samples; # endif /* UMAX */ # ifdef DGUX static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */ # endif /* DGUX */ #if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE) /* File descriptor open to /dev/kmem or VMS load ave driver. */ static int channel; /* Nonzero iff channel is valid. */ static int getloadavg_initialized; /* Offset in kmem to seek to read load average, or 0 means invalid. */ static long offset; #if !defined(VMS) && !defined(sgi) && !defined(__linux__) static struct nlist nl[2]; #endif /* Not VMS or sgi */ #ifdef SUNOS_5 static kvm_t *kd; #endif /* SUNOS_5 */ #endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */ /* Put the 1 minute, 5 minute and 15 minute load averages into the first NELEM elements of LOADAVG. Return the number written (never more than 3, but may be less than NELEM), or -1 if an error occurred. */ int getloadavg (double loadavg[], int nelem); int getloadavg (loadavg, nelem) double loadavg[]; int nelem; { int elem = 0; /* Return value. */ # ifdef NO_GET_LOAD_AVG # define LDAV_DONE /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; elem = -1; # endif # if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT) /* Use libkstat because we don't have to be root. */ # define LDAV_DONE kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; kc = kstat_open (); if (kc == 0) return -1; ksp = kstat_lookup (kc, "unix", 0, "system_misc"); if (ksp == 0 ) return -1; if (kstat_read (kc, ksp, 0) == -1) return -1; kn = kstat_data_lookup (ksp, "avenrun_1min"); if (kn == 0) { /* Return -1 if no load average information is available. */ nelem = 0; elem = -1; } if (nelem >= 1) loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 2) { kn = kstat_data_lookup (ksp, "avenrun_5min"); if (kn != 0) { loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 3) { kn = kstat_data_lookup (ksp, "avenrun_15min"); if (kn != 0) loadavg[elem++] = (double) kn->value.ul/FSCALE; } } } kstat_close (kc); # endif /* HAVE_LIBKSTAT */ # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) /* Use pstat_getdynamic() because we don't have to be root. */ # define LDAV_DONE # undef LOAD_AVE_TYPE struct pst_dynamic dyn_info; if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0) return -1; if (nelem > 0) loadavg[elem++] = dyn_info.psd_avg_1_min; if (nelem > 1) loadavg[elem++] = dyn_info.psd_avg_5_min; if (nelem > 2) loadavg[elem++] = dyn_info.psd_avg_15_min; # endif /* hpux && HAVE_PSTAT_GETDYNAMIC */ # if !defined (LDAV_DONE) && defined (__linux__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef LINUX_LDAV_FILE # define LINUX_LDAV_FILE "/proc/loadavg" # endif char ldavgbuf[40]; double load_ave[3]; int fd, count; fd = open (LINUX_LDAV_FILE, O_RDONLY); if (fd == -1) return -1; count = read (fd, ldavgbuf, 40); (void) close (fd); if (count <= 0) return -1; count = sscanf (ldavgbuf, "%lf %lf %lf", &load_ave[0], &load_ave[1], &load_ave[2]); if (count < 1) return -1; for (elem = 0; elem < nelem && elem < count; elem++) loadavg[elem] = load_ave[elem]; return elem; # endif /* __linux__ */ # if !defined (LDAV_DONE) && defined (__NetBSD__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef NETBSD_LDAV_FILE # define NETBSD_LDAV_FILE "/kern/loadavg" # endif unsigned long int load_ave[3], scale; int count; FILE *fp; fp = fopen (NETBSD_LDAV_FILE, "r"); if (fp == NULL) return -1; count = fscanf (fp, "%lu %lu %lu %lu\n", &load_ave[0], &load_ave[1], &load_ave[2], &scale); (void) fclose (fp); if (count != 4) return -1; for (elem = 0; elem < nelem; elem++) loadavg[elem] = (double) load_ave[elem] / (double) scale; return elem; # endif /* __NetBSD__ */ # if !defined (LDAV_DONE) && defined (NeXT) # define LDAV_DONE /* The NeXT code was adapted from iscreen 3.2. */ host_t host; struct processor_set_basic_info info; unsigned info_count; /* We only know how to get the 1-minute average for this system, so even if the caller asks for more than 1, we only return 1. */ if (!getloadavg_initialized) { if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS) getloadavg_initialized = 1; } if (getloadavg_initialized) { info_count = PROCESSOR_SET_BASIC_INFO_COUNT; if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t) &info, &info_count) != KERN_SUCCESS) getloadavg_initialized = 0; else { if (nelem > 0) loadavg[elem++] = (double) info.load_average / LOAD_SCALE; } } if (!getloadavg_initialized) return -1; # endif /* NeXT */ # if !defined (LDAV_DONE) && defined (UMAX) # define LDAV_DONE /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not have a /dev/kmem. Information about the workings of the running kernel can be gathered with inq_stats system calls. We only know how to get the 1-minute average for this system. */ struct proc_summary proc_sum_data; struct stat_descr proc_info; double load; register unsigned int i, j; if (cpus == 0) { register unsigned int c, i; struct cpu_config conf; struct stat_descr desc; desc.sd_next = 0; desc.sd_subsys = SUBSYS_CPU; desc.sd_type = CPUTYPE_CONFIG; desc.sd_addr = (char *) &conf; desc.sd_size = sizeof conf; if (inq_stats (1, &desc)) return -1; c = 0; for (i = 0; i < conf.config_maxclass; ++i) { struct class_stats stats; memset(&stats, 0, sizeof stats); desc.sd_type = CPUTYPE_CLASS; desc.sd_objid = i; desc.sd_addr = (char *) &stats; desc.sd_size = sizeof stats; if (inq_stats (1, &desc)) return -1; c += stats.class_numcpus; } cpus = c; samples = cpus < 2 ? 3 : (2 * cpus / 3); } proc_info.sd_next = 0; proc_info.sd_subsys = SUBSYS_PROC; proc_info.sd_type = PROCTYPE_SUMMARY; proc_info.sd_addr = (char *) &proc_sum_data; proc_info.sd_size = sizeof (struct proc_summary); proc_info.sd_sizeused = 0; if (inq_stats (1, &proc_info) != 0) return -1; load = proc_sum_data.ps_nrunnable; j = 0; for (i = samples - 1; i > 0; --i) { load += proc_sum_data.ps_nrun[j]; if (j++ == PS_NRUNSIZE) j = 0; } if (nelem > 0) loadavg[elem++] = load / samples / cpus; # endif /* UMAX */ # if !defined (LDAV_DONE) && defined (DGUX) # define LDAV_DONE /* This call can return -1 for an error, but with good args it's not supposed to fail. The first argument is for no apparent reason of type `long int *'. */ dg_sys_info ((long int *) &load_info, DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); if (nelem > 0) loadavg[elem++] = load_info.one_minute; if (nelem > 1) loadavg[elem++] = load_info.five_minute; if (nelem > 2) loadavg[elem++] = load_info.fifteen_minute; # endif /* DGUX */ # if !defined (LDAV_DONE) && defined (apollo) # define LDAV_DONE /* Apollo code from lisch@mentorg.com (Ray Lischner). This system call is not documented. The load average is obtained as three long integers, for the load average over the past minute, five minutes, and fifteen minutes. Each value is a scaled integer, with 16 bits of integer part and 16 bits of fraction part. I'm not sure which operating system first supported this system call, but I know that SR10.2 supports it. */ extern void proc1_$get_loadav (); unsigned long load_ave[3]; proc1_$get_loadav (load_ave); if (nelem > 0) loadavg[elem++] = load_ave[0] / 65536.0; if (nelem > 1) loadavg[elem++] = load_ave[1] / 65536.0; if (nelem > 2) loadavg[elem++] = load_ave[2] / 65536.0; # endif /* apollo */ # if !defined (LDAV_DONE) && defined (OSF_MIPS) # define LDAV_DONE struct tbl_loadavg load_ave; table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); loadavg[elem++] = (load_ave.tl_lscale == 0 ? load_ave.tl_avenrun.d[0] : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale)); # endif /* OSF_MIPS */ # if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32)) # define LDAV_DONE /* A faithful emulation is going to have to be saved for a rainy day. */ for ( ; elem < nelem; elem++) { loadavg[elem] = 0.0; } # endif /* __MSDOS__ || WINDOWS32 */ # if !defined (LDAV_DONE) && defined (OSF_ALPHA) # define LDAV_DONE struct tbl_loadavg load_ave; table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); for (elem = 0; elem < nelem; elem++) loadavg[elem] = (load_ave.tl_lscale == 0 ? load_ave.tl_avenrun.d[elem] : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale)); # endif /* OSF_ALPHA */ # if !defined (LDAV_DONE) && defined (VMS) /* VMS specific code -- read from the Load Ave driver. */ LOAD_AVE_TYPE load_ave[3]; static int getloadavg_initialized = 0; # ifdef eunice struct { int dsc$w_length; char *dsc$a_pointer; } descriptor; # endif /* Ensure that there is a channel open to the load ave device. */ if (!getloadavg_initialized) { /* Attempt to open the channel. */ # ifdef eunice descriptor.dsc$w_length = 18; descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE"; # else $DESCRIPTOR (descriptor, "LAV0:"); # endif if (sys$assign (&descriptor, &channel, 0, 0) & 1) getloadavg_initialized = 1; } /* Read the load average vector. */ if (getloadavg_initialized && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0, load_ave, 12, 0, 0, 0, 0) & 1)) { sys$dassgn (channel); getloadavg_initialized = 0; } if (!getloadavg_initialized) return -1; # endif /* VMS */ # if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS) /* UNIX-specific code -- read the average from /dev/kmem. */ # define LDAV_PRIVILEGED /* This code requires special installation. */ LOAD_AVE_TYPE load_ave[3]; /* Get the address of LDAV_SYMBOL. */ if (offset == 0) { # ifndef sgi # ifndef NLIST_STRUCT strcpy (nl[0].n_name, LDAV_SYMBOL); strcpy (nl[1].n_name, ""); # else /* NLIST_STRUCT */ # ifdef NLIST_NAME_UNION nl[0].n_un.n_name = LDAV_SYMBOL; nl[1].n_un.n_name = 0; # else /* not NLIST_NAME_UNION */ nl[0].n_name = LDAV_SYMBOL; nl[1].n_name = 0; # endif /* not NLIST_NAME_UNION */ # endif /* NLIST_STRUCT */ # ifndef SUNOS_5 if ( # if !(defined (_AIX) && !defined (ps2)) nlist (KERNEL_FILE, nl) # else /* _AIX */ knlist (nl, 1, sizeof (nl[0])) # endif >= 0) /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */ { # ifdef FIXUP_KERNEL_SYMBOL_ADDR FIXUP_KERNEL_SYMBOL_ADDR (nl); # endif offset = nl[0].n_value; } # endif /* !SUNOS_5 */ # else /* sgi */ int ldav_off; ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); if (ldav_off != -1) offset = (long) ldav_off & 0x7fffffff; # endif /* sgi */ } /* Make sure we have /dev/kmem open. */ if (!getloadavg_initialized) { # ifndef SUNOS_5 channel = open ("/dev/kmem", 0); if (channel >= 0) { /* Set the channel to close on exec, so it does not litter any child's descriptor table. */ # ifdef F_SETFD # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif (void) fcntl (channel, F_SETFD, FD_CLOEXEC); # endif getloadavg_initialized = 1; } # else /* SUNOS_5 */ /* We pass 0 for the kernel, corefile, and swapfile names to use the currently running kernel. */ kd = kvm_open (0, 0, 0, O_RDONLY, 0); if (kd != 0) { /* nlist the currently running kernel. */ kvm_nlist (kd, nl); offset = nl[0].n_value; getloadavg_initialized = 1; } # endif /* SUNOS_5 */ } /* If we can, get the load average values. */ if (offset && getloadavg_initialized) { /* Try to read the load. */ # ifndef SUNOS_5 if (lseek (channel, offset, 0) == -1L || read (channel, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { close (channel); getloadavg_initialized = 0; } # else /* SUNOS_5 */ if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { kvm_close (kd); getloadavg_initialized = 0; } # endif /* SUNOS_5 */ } if (offset == 0 || !getloadavg_initialized) return -1; # endif /* LOAD_AVE_TYPE and not VMS */ # if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */ if (nelem > 0) loadavg[elem++] = LDAV_CVT (load_ave[0]); if (nelem > 1) loadavg[elem++] = LDAV_CVT (load_ave[1]); if (nelem > 2) loadavg[elem++] = LDAV_CVT (load_ave[2]); # define LDAV_DONE # endif /* !LDAV_DONE && LOAD_AVE_TYPE */ # ifdef LDAV_DONE return elem; # else /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; return -1; # endif } #endif /* ! HAVE_GETLOADAVG */ #ifdef TEST int main (argc, argv) int argc; char **argv; { int naptime = 0; if (argc > 1) naptime = atoi (argv[1]); while (1) { double avg[3]; int loads; errno = 0; /* Don't be misled if it doesn't set errno. */ loads = getloadavg (avg, 3); if (loads == -1) { perror ("Error getting load average"); exit (1); } if (loads > 0) printf ("1-minute: %f ", avg[0]); if (loads > 1) printf ("5-minute: %f ", avg[1]); if (loads > 2) printf ("15-minute: %f ", avg[2]); if (loads > 0) putchar ('\n'); if (naptime == 0) break; sleep (naptime); } exit (0); } #endif /* TEST */ cfengine-3.6.2/libcompat/getaddrinfo.c0000664000175100017510000002503312243421446017427 0ustar00a10038a1003800000000000000/* PostgreSQL Database Management System (formerly known as Postgres, then as Postgres95) Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group Portions Copyright (c) 1994, The Regents of the University of California Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ /*------------------------------------------------------------------------- * * getaddrinfo.c * Support getaddrinfo() on platforms that don't have it. * * We also supply getnameinfo() here, assuming that the platform will have * it if and only if it has getaddrinfo(). If this proves false on some * platform, we'll need to split this file and provide a separate configure * test for getnameinfo(). * * Copyright (c) 2003-2007, PostgreSQL Global Development Group * * Copyright (C) 2007 Jeremy Allison. * Modified to return multiple IPv4 addresses for Samba. * *------------------------------------------------------------------------- */ #include #ifndef SMB_MALLOC #define SMB_MALLOC(s) malloc(s) #endif #ifndef SMB_STRDUP #define SMB_STRDUP(s) strdup(s) #endif #ifndef HOST_NAME_MAX #define HOST_NAME_MAX 255 #endif static int check_hostent_err(struct hostent *hp) { #ifndef INET6 extern int h_errno; #endif if (!hp) { switch (h_errno) { case HOST_NOT_FOUND: case NO_DATA: return EAI_NONAME; case TRY_AGAIN: return EAI_AGAIN; case NO_RECOVERY: default: return EAI_FAIL; } } if (!hp->h_name || hp->h_addrtype != AF_INET) { return EAI_FAIL; } return 0; } static char *canon_name_from_hostent(struct hostent *hp, int *perr) { char *ret = NULL; *perr = check_hostent_err(hp); if (*perr) { return NULL; } ret = SMB_STRDUP(hp->h_name); if (!ret) { *perr = EAI_MEMORY; } return ret; } static char *get_my_canon_name(int *perr) { char name[HOST_NAME_MAX+1]; if (gethostname(name, HOST_NAME_MAX) == -1) { *perr = EAI_FAIL; return NULL; } /* Ensure null termination. */ name[HOST_NAME_MAX] = '\0'; return canon_name_from_hostent(gethostbyname(name), perr); } static char *get_canon_name_from_addr(struct in_addr ip, int *perr) { return canon_name_from_hostent( gethostbyaddr((void *)&ip, sizeof ip, AF_INET), perr); } static struct addrinfo *alloc_entry(const struct addrinfo *hints, struct in_addr ip, unsigned short port) { struct sockaddr_in *psin = NULL; struct addrinfo *ai = SMB_MALLOC(sizeof(*ai)); if (!ai) { return NULL; } memset(ai, '\0', sizeof(*ai)); psin = SMB_MALLOC(sizeof(*psin)); if (!psin) { free(ai); return NULL; } memset(psin, '\0', sizeof(*psin)); psin->sin_family = AF_INET; psin->sin_port = htons(port); psin->sin_addr = ip; ai->ai_flags = 0; ai->ai_family = AF_INET; ai->ai_socktype = hints->ai_socktype; ai->ai_protocol = hints->ai_protocol; ai->ai_addrlen = sizeof(*psin); ai->ai_addr = (struct sockaddr *) psin; ai->ai_canonname = NULL; ai->ai_next = NULL; return ai; } /* * get address info for a single ipv4 address. * * Bugs: - servname can only be a number, not text. */ static int getaddr_info_single_addr(const char *service, uint32_t addr, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo *ai = NULL; struct in_addr ip; unsigned short port = 0; if (service) { port = (unsigned short)atoi(service); } ip.s_addr = htonl(addr); ai = alloc_entry(hints, ip, port); if (!ai) { return EAI_MEMORY; } /* If we're asked for the canonical name, * make sure it returns correctly. */ if (!(hints->ai_flags & AI_NUMERICSERV) && hints->ai_flags & AI_CANONNAME) { int err; if (addr == INADDR_LOOPBACK || addr == INADDR_ANY) { ai->ai_canonname = get_my_canon_name(&err); } else { ai->ai_canonname = get_canon_name_from_addr(ip,&err); } if (ai->ai_canonname == NULL) { freeaddrinfo(ai); return err; } } *res = ai; return 0; } /* * get address info for multiple ipv4 addresses. * * Bugs: - servname can only be a number, not text. */ static int getaddr_info_name(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo *listp = NULL, *prevp = NULL; char **pptr = NULL; int err; struct hostent *hp = NULL; unsigned short port = 0; if (service) { port = (unsigned short)atoi(service); } hp = gethostbyname(node); err = check_hostent_err(hp); if (err) { return err; } for(pptr = hp->h_addr_list; *pptr; pptr++) { struct in_addr ip = *(struct in_addr *)*pptr; struct addrinfo *ai = alloc_entry(hints, ip, port); if (!ai) { freeaddrinfo(listp); return EAI_MEMORY; } if (!listp) { listp = ai; prevp = ai; ai->ai_canonname = SMB_STRDUP(hp->h_name); if (!ai->ai_canonname) { freeaddrinfo(listp); return EAI_MEMORY; } } else { prevp->ai_next = ai; prevp = ai; } } *res = listp; return 0; } /* * get address info for ipv4 sockets. * * Bugs: - servname can only be a number, not text. */ int getaddrinfo(const char *node, const char *service, const struct addrinfo * hintp, struct addrinfo ** res) { struct addrinfo hints; /* Setup the hints struct. */ if (hintp == NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; } else { memcpy(&hints, hintp, sizeof(hints)); } if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) { return EAI_FAMILY; } if (hints.ai_socktype == 0) { hints.ai_socktype = SOCK_STREAM; } if (!node && !service) { return EAI_NONAME; } if (node) { if (node[0] == '\0') { return getaddr_info_single_addr(service, INADDR_ANY, &hints, res); } else if (hints.ai_flags & AI_NUMERICHOST) { struct in_addr ip; if (inet_pton(AF_INET, node, &ip) <= 0) return EAI_FAIL; return getaddr_info_single_addr(service, ntohl(ip.s_addr), &hints, res); } else { return getaddr_info_name(node, service, &hints, res); } } else if (hints.ai_flags & AI_PASSIVE) { return getaddr_info_single_addr(service, INADDR_ANY, &hints, res); } return getaddr_info_single_addr(service, INADDR_LOOPBACK, &hints, res); } void freeaddrinfo(struct addrinfo *res) { struct addrinfo *next = NULL; for (;res; res = next) { next = res->ai_next; if (res->ai_canonname) { free(res->ai_canonname); } if (res->ai_addr) { free(res->ai_addr); } free(res); } } const char *gai_strerror(int errcode) { #ifdef HAVE_HSTRERROR int hcode; switch (errcode) { case EAI_NONAME: hcode = HOST_NOT_FOUND; break; case EAI_AGAIN: hcode = TRY_AGAIN; break; case EAI_FAIL: default: hcode = NO_RECOVERY; break; } return hstrerror(hcode); #else /* !HAVE_HSTRERROR */ switch (errcode) { case EAI_NONAME: return "Unknown host"; case EAI_AGAIN: return "Host name lookup failure"; #ifdef EAI_BADFLAGS case EAI_BADFLAGS: return "Invalid argument"; #endif #ifdef EAI_FAMILY case EAI_FAMILY: return "Address family not supported"; #endif #ifdef EAI_MEMORY case EAI_MEMORY: return "Not enough memory"; #endif #ifdef EAI_NODATA case EAI_NODATA: return "No host data of that type was found"; #endif #ifdef EAI_SERVICE case EAI_SERVICE: return "Class type not found"; #endif #ifdef EAI_SOCKTYPE case EAI_SOCKTYPE: return "Socket type not supported"; #endif default: return "Unknown server error"; } #endif /* HAVE_HSTRERROR */ } static int gethostnameinfo(const struct sockaddr *sa, char *node, size_t nodelen, int flags) { int ret = -1; char *p = NULL; if (!(flags & NI_NUMERICHOST)) { struct hostent *hp = gethostbyaddr( (void *)&((struct sockaddr_in *)sa)->sin_addr, sizeof (struct in_addr), sa->sa_family); ret = check_hostent_err(hp); if (ret == 0) { /* Name looked up successfully. */ ret = snprintf(node, nodelen, "%s", hp->h_name); if (ret < 0 || (size_t)ret >= nodelen) { return EAI_MEMORY; } if (flags & NI_NOFQDN) { p = strchr(node,'.'); if (p) { *p = '\0'; } } return 0; } if (flags & NI_NAMEREQD) { /* If we require a name and didn't get one, * automatically fail. */ return ret; } /* Otherwise just fall into the numeric host code... */ } p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr); ret = snprintf(node, nodelen, "%s", p); if (ret < 0 || (size_t)ret >= nodelen) { return EAI_MEMORY; } return 0; } static int getservicenameinfo(const struct sockaddr *sa, char *service, size_t servicelen, int flags) { int ret = -1; int port = ntohs(((struct sockaddr_in *)sa)->sin_port); if (!(flags & NI_NUMERICSERV)) { struct servent *se = getservbyport( port, (flags & NI_DGRAM) ? "udp" : "tcp"); if (se && se->s_name) { /* Service name looked up successfully. */ ret = snprintf(service, servicelen, "%s", se->s_name); if (ret < 0 || (size_t)ret >= servicelen) { return EAI_MEMORY; } return 0; } /* Otherwise just fall into the numeric service code... */ } ret = snprintf(service, servicelen, "%d", port); if (ret < 0 || (size_t)ret >= servicelen) { return EAI_MEMORY; } return 0; } /* * Convert an ipv4 address to a hostname. * * Bugs: - No IPv6 support. */ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags) { /* Invalid arguments. */ if (sa == NULL || (node == NULL && service == NULL)) { return EAI_FAIL; } if (sa->sa_family != AF_INET) { return EAI_FAIL; } if (salen < (socklen_t)sizeof (struct sockaddr_in)) { return EAI_FAIL; } if (node) { int ret = gethostnameinfo(sa, node, nodelen, flags); if (ret) return ret; } if (service) { return getservicenameinfo(sa, service, servicelen, flags); } return 0; } cfengine-3.6.2/libcompat/mkdtemp.c0000664000175100017510000000310412243421446016575 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #define MAXTRY 999999 char *mkdtemp(char *template) { char *xxx = strrstr(template, "XXXXXX"); if (xxx == NULL || strcmp(xxx, "XXXXXX") != 0) { errno = EINVAL; return NULL; } for (int i = 0; i <= MAXTRY; ++i) { snprintf(xxx, 7, "%06d", i); int fd = mkdir(template, S_IRUSR | S_IWUSR | S_IXUSR); if (fd >= 0) { close(fd); return template; } if (errno != EEXIST) { return NULL; } } errno = EEXIST; return NULL; } cfengine-3.6.2/libcompat/generic_at.h0000644000175100017510000000213712316547775017263 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef __MINGW32__ int generic_at_function(int dirfd, int (*func)(void *data), void (*cleanup)(void *data), void *data); #endif cfengine-3.6.2/libcompat/strcasecmp.c0000664000175100017510000000312512243421446017303 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #if !HAVE_DECL_STRCASECMP int strcasecmp(const char *s1, const char *s2); #endif int strcasecmp(const char *s1, const char *s2) { for (;;) { if (*s1 == '\0' && *s2 == '\0') { break; } if (*s1 == '\0') { return -1; } if (*s2 == '\0') { return 1; } if (tolower(*s1) < tolower(*s2)) { return -1; } if (tolower(*s1) > tolower(*s2)) { return 1; } s1++; s2++; } return 0; } cfengine-3.6.2/libcompat/strlcpy.c0000664000175100017510000000320212236160673016637 0ustar00a10038a1003800000000000000/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include size_t strlcpy(char *dst, const char *src, size_t siz); /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0) { while (--n != 0) { if ((*d++ = *s++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } cfengine-3.6.2/libcompat/pthread_sigmask.c0000664000175100017510000000256312243421446020311 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #define _POSIX #include #include #include #if !HAVE_DECL_PTHREAD_SIGMASK int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset); #endif /* * Stub implementation. Previously pthread_sigmask was just #ifdef'ed out. */ int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset) { return 0; } cfengine-3.6.2/libcompat/memrchr.c0000644000175100017510000000256112316547775016614 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include /* size_t */ void *memrchr(const void *s, int c, size_t n) { unsigned char *s_end = (unsigned char *) s + n - 1; while (n > 0) { if ((*s_end) == (unsigned char) c) { return s_end; } s_end--; n--; } return NULL; } cfengine-3.6.2/libcompat/rpl_ctime.c0000664000175100017510000000227112243421446017116 0ustar00a10038a1003800000000000000/* Copyright (C) Cfengine AS This file is part of Cfengine 3 - written and maintained by Cfengine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of Cfengine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include char *cf_strtimestamp_local(const time_t time, char *buf); char *rpl_ctime(const time_t *timep) { static char buf[26]; return cf_strtimestamp_local(*timep, buf); } cfengine-3.6.2/libcompat/openat.c0000644000175100017510000000374312316547775016450 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #ifndef __MINGW32__ typedef struct { const char *pathname; int flags; mode_t mode; int fd; } openat_data; static int openat_inner(void *generic_data) { openat_data *data = generic_data; data->fd = open(data->pathname, data->flags, data->mode); return data->fd; } static void cleanup(void *generic_data) { openat_data *data = generic_data; if (data->fd >= 0) { close(data->fd); } } int openat(int dirfd, const char *pathname, int flags, ...) { openat_data data; data.pathname = pathname; data.flags = flags; if (flags & O_CREAT) { va_list ap; va_start(ap, flags); data.mode = va_arg(ap, int); va_end(ap); } else { data.mode = 0; } data.fd = -1; return generic_at_function(dirfd, &openat_inner, &cleanup, &data); } #endif // !__MINGW32__ cfengine-3.6.2/libcompat/fchownat.c0000644000175100017510000000361512316547775016771 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #ifndef __MINGW32__ typedef struct { const char *pathname; uid_t owner; gid_t group; int flags; } fchownat_data; static int fchownat_inner(void *generic_data) { fchownat_data *data = generic_data; if (data->flags & AT_SYMLINK_NOFOLLOW) { return lchown(data->pathname, data->owner, data->group); } else { return chown(data->pathname, data->owner, data->group); } } static void cleanup(ARG_UNUSED void *generic_data) { } int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) { fchownat_data data; data.pathname = pathname; data.owner = owner; data.group = group; data.flags = flags; return generic_at_function(dirfd, &fchownat_inner, &cleanup, &data); } #endif // !__MINGW32__ cfengine-3.6.2/libcompat/inet_pton.c0000664000175100017510000001207612243421446017143 0ustar00a10038a1003800000000000000/* * Copyright (C) 1996-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #if defined(_WIN32) && !defined(EAFNOSUPPORT) #define EAFNOSUPPORT WSAEAFNOSUPPORT #endif #define NS_INT16SZ 2 #define NS_INADDRSZ 4 #define NS_IN6ADDRSZ 16 /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static int inet_pton4(const char *src, unsigned char *dst); #ifdef INET6 static int inet_pton6(const char *src, unsigned char *dst); #endif /* int * inet_pton(af, src, dst) * convert from presentation format (which usually means ASCII printable) * to network format (which is usually some kind of binary format). * return: * 1 if the address was valid for the specified address family * 0 if the address wasn't valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) * author: * Paul Vixie, 1996. */ int inet_pton(int af, const char *src, void *dst) { switch (af) { case AF_INET: return (inet_pton4(src, dst)); #ifdef INET6 case AF_INET6: return (inet_pton6(src, dst)); #endif default: errno = EAFNOSUPPORT; return (-1); } /* NOTREACHED */ } /* int * inet_pton4(src, dst) * like inet_aton() but without all the hexadecimal and shorthand. * return: * 1 if `src' is a valid dotted quad, else 0. * notice: * does not touch `dst' unless it's returning 1. * author: * Paul Vixie, 1996. */ static int inet_pton4(src, dst) const char *src; unsigned char *dst; { static const char digits[] = "0123456789"; int saw_digit, octets, ch; unsigned char tmp[NS_INADDRSZ], *tp; saw_digit = 0; octets = 0; *(tp = tmp) = 0; while ((ch = *src++) != '\0') { const char *pch; if ((pch = strchr(digits, ch)) != NULL) { unsigned int new = *tp * 10 + (pch - digits); if (new > 255) return (0); *tp = new; if (! saw_digit) { if (++octets > 4) return (0); saw_digit = 1; } } else if (ch == '.' && saw_digit) { if (octets == 4) return (0); *++tp = 0; saw_digit = 0; } else return (0); } if (octets < 4) return (0); memcpy(dst, tmp, NS_INADDRSZ); return (1); } /* int * inet_pton6(src, dst) * convert presentation level address to network order binary form. * return: * 1 if `src' is a valid [RFC1884 2.2] address, else 0. * notice: * (1) does not touch `dst' unless it's returning 1. * (2) :: in a full address is silently ignored. * credit: * inspired by Mark Andrews. * author: * Paul Vixie, 1996. */ #ifdef INET6 static int inet_pton6(src, dst) const char *src; unsigned char *dst; { static const char xdigits_l[] = "0123456789abcdef", xdigits_u[] = "0123456789ABCDEF"; unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; const char *xdigits, *curtok; int ch, saw_xdigit; unsigned int val; memset((tp = tmp), '\0', NS_IN6ADDRSZ); endp = tp + NS_IN6ADDRSZ; colonp = NULL; /* Leading :: requires some special handling. */ if (*src == ':') if (*++src != ':') return (0); curtok = src; saw_xdigit = 0; val = 0; while ((ch = *src++) != '\0') { const char *pch; if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) pch = strchr((xdigits = xdigits_u), ch); if (pch != NULL) { val <<= 4; val |= (pch - xdigits); if (val > 0xffff) return (0); saw_xdigit = 1; continue; } if (ch == ':') { curtok = src; if (!saw_xdigit) { if (colonp) return (0); colonp = tp; continue; } if (tp + NS_INT16SZ > endp) return (0); *tp++ = (unsigned char) (val >> 8) & 0xff; *tp++ = (unsigned char) val & 0xff; saw_xdigit = 0; val = 0; continue; } if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) { tp += NS_INADDRSZ; saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ } return (0); } if (saw_xdigit) { if (tp + NS_INT16SZ > endp) return (0); *tp++ = (unsigned char) (val >> 8) & 0xff; *tp++ = (unsigned char) val & 0xff; } if (colonp != NULL) { /* * Since some memmove()'s erroneously fail to handle * overlapping regions, we'll do the shift by hand. */ const int n = tp - colonp; int i; for (i = 1; i <= n; i++) { endp[- i] = colonp[n - i]; colonp[n - i] = 0; } tp = endp; } if (tp != endp) return (0); memcpy(dst, tmp, NS_IN6ADDRSZ); return (1); } #endif cfengine-3.6.2/libcompat/log2.c0000644000175100017510000000204712316547775016021 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include double log2(double x) { return log(x) / log(2); } cfengine-3.6.2/libcompat/getopt.c0000644000175100017510000005066212316547775016466 0ustar00a10038a1003800000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #endif /* GNU C library. */ char *getenv(const char *name); /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #include #define my_index strchr /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ static const char * _getopt_initialize (optstring) const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind = 1; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0) optstring = _getopt_initialize (optstring); if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if (nameend - nextchar == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, "%s: option `%s' requires an argument\n", argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf (stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); else fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); } optopt = c; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit(EXIT_SUCCESS); } #endif /* TEST */ cfengine-3.6.2/libcompat/strnlen.c0000664000175100017510000000226612236160673016635 0ustar00a10038a1003800000000000000/* $OpenBSD: strnlen.c,v 1.3 2010/06/02 12:58:12 millert Exp $ */ /* * Copyright (c) 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_STRNLEN size_t strnlen(const char *str, size_t maxlen); #endif size_t strnlen(const char *str, size_t maxlen) { const char *cp; for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--) ; return (size_t)(cp - str); } cfengine-3.6.2/libcompat/strerror.c0000664000175100017510000000233512243421446017023 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_STRERROR char *strerror(int err); #endif char *strerror(int err) { static char buffer[20]; snprintf(buffer, 20, "Error number %d\n", err); return buffer; } cfengine-3.6.2/libcompat/getopt1.c0000644000175100017510000001047312316547775016543 0ustar00a10038a1003800000000000000/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #else char *getenv (); #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == EOF) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit(EXIT_SUCCESS); } #endif /* TEST */ cfengine-3.6.2/libcompat/nanosleep.c0000664000175100017510000000262112243421446017123 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* * NB! Does not calculate "remaining time" */ #ifdef HAVE_CONFIG_H # include #endif #ifdef __MINGW32__ # include # include int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { if (rmtp) { rmtp->tv_sec = 0; rmtp->tv_nsec = 0; } DWORD timeout = rqtp->tv_sec * 1000L + (rqtp->tv_nsec + 999999) / 1000000; Sleep(timeout); return 0; } #endif cfengine-3.6.2/libcompat/strsignal.c0000664000175100017510000000251512243421446017147 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_SNPRINTF int rpl_snprintf(char *, size_t, const char *, ...); #endif #if !HAVE_DECL_STRSIGNAL char *strsignal(int sig); #endif #include static char SIGNAL_TEXT[16]; char *strsignal(int sig) { snprintf(SIGNAL_TEXT, 16, "Signal #%d", sig); return SIGNAL_TEXT; } cfengine-3.6.2/libcompat/pthread_attr_setstacksize.c0000664000175100017510000000236712243421446022423 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_PTHREAD_ATTR_SETSTACKSIZE int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); # endif int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { return 0; } cfengine-3.6.2/libcompat/strlcat.c0000664000175100017510000000337512236160673016626 0ustar00a10038a1003800000000000000/* $OpenBSD: strlcat.c,v 1.12 2005/03/30 20:13:52 otto Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include size_t strlcat(char *dst, const char *src, size_t siz); /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } cfengine-3.6.2/libcompat/memmem.c0000644000175100017510000000323612332665147016424 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include /* size_t */ void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { const char *start; /* Just to avoid casts. */ const char *h = haystack; const char *n = needle; for (start = h; start < h + haystacklen; start++) { size_t len = 0; while (len < needlelen && start + len < h + haystacklen && start[len] == n[len]) { len++; } if (len == needlelen) { return (void *) start; } } return NULL; } cfengine-3.6.2/libcompat/generic_at.c0000664000175100017510000001055312411001073017225 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #ifndef __MINGW32__ /* * Implements a generic interface to implement the POSIX-2008 *at * functions (openat, fstatat, fchownat, etc.). */ /* * This function uses fchdir() to preserve integrity when querying * a file from a directory descriptor. It's ugly but it's the only way * to be secure. * Using fchdir() in *at functions means that we can potentially * conflict with chdir()/fchdir() being used elsewhere. For this to be * safe, the program must fulfill at least one of the following * criteria: * 1. Be single threaded. * 2. Not use chdir() anywhere else but here. * 3. Do all file operations (including chdir) in one thread. * 4. Use the CHDIR_LOCK in this file. * Currently, cf-agent fulfills criterion 1. All the others fulfill * criterion 2. */ // To prevent several threads from stepping on each other's toes // when using fchdir(). static pthread_mutex_t CHDIR_LOCK = PTHREAD_MUTEX_INITIALIZER; /** * Generic *at function. * @param dirfd File descriptor pointing to directory to do lookup in. * AT_FDCWD constant means to look in current directory. * @param func Function to call while in the directory. * @param cleanup Function to call if we need to clean up because of a failed call. * @param data Private data for the supplied functions. */ int generic_at_function(int dirfd, int (*func)(void *data), void (*cleanup)(void *data), void *data) { int cwd; int mutex_err; int saved_errno; int fchdir_ret; mutex_err = pthread_mutex_lock(&CHDIR_LOCK); if (mutex_err) { UnexpectedError("Error when locking CHDIR_LOCK. Should never happen. (pthread_mutex_lock: '%s')", GetErrorStrFromCode(mutex_err)); } if (dirfd != AT_FDCWD) { cwd = open(".", O_RDONLY); if (cwd < 0) { mutex_err = pthread_mutex_unlock(&CHDIR_LOCK); if (mutex_err) { UnexpectedError("Error when unlocking CHDIR_LOCK. Should never happen. (pthread_mutex_unlock: '%s')", GetErrorStrFromCode(mutex_err)); } return -1; } if (fchdir(dirfd) < 0) { close(cwd); mutex_err = pthread_mutex_unlock(&CHDIR_LOCK); if (mutex_err) { UnexpectedError("Error when unlocking CHDIR_LOCK. Should never happen. (pthread_mutex_unlock: '%s')", GetErrorStrFromCode(mutex_err)); } return -1; } } int result = func(data); saved_errno = errno; if (dirfd != AT_FDCWD) { fchdir_ret = fchdir(cwd); close(cwd); } mutex_err = pthread_mutex_unlock(&CHDIR_LOCK); if (mutex_err) { UnexpectedError("Error when unlocking CHDIR_LOCK. Should never happen. (pthread_mutex_unlock: '%s')", GetErrorStrFromCode(mutex_err)); } if (dirfd != AT_FDCWD) { if (fchdir_ret < 0) { cleanup(data); Log(LOG_LEVEL_WARNING, "Could not return to original working directory in '%s'. " "Things may not behave as expected. (fchdir: '%s')", __FUNCTION__, GetErrorStr()); return -1; } } errno = saved_errno; return result; } #endif // !__MINGW32__ cfengine-3.6.2/libcompat/snprintf.c0000664000175100017510000015347312400110676017011 0ustar00a10038a1003800000000000000/* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */ /* * Copyright (c) 1995 Patrick Powell. * * This code is based on code written by Patrick Powell . * It may be used for any purpose as long as this notice remains intact on all * source code distributions. */ /* * Copyright (c) 2008 Holger Weiss. * * This version of the code is maintained by Holger Weiss . * My changes to the code may freely be used, modified and/or redistributed for * any purpose. It would be nice if additions and fixes to this file (including * trivial code cleanups) would be sent back in order to let me include them in * the version available at . * However, this is not a requirement for using or redistributing (possibly * modified) versions of this file, nor is leaving this notice intact mandatory. */ /* * History * * 2014-04-03 Dimitrios Apostolou : * * snprintf.c: Provided replacement functions for [v][f]printf(). * snprintf.m4: Always check for locale.h and other header files * so that the tests in this file run correctly. * snprintf.m4: _HW_FUNC_XPRINTF_REPLACE was being skipped when configure * was being re-run with cache enabled (-C). Now * AC_LIBOBJ(snprintf) might be called multiple times but * shouldn't matter. * * 2008-01-20 Holger Weiss for C99-snprintf 1.1: * * Fixed the detection of infinite floating point values on IRIX (and * possibly other systems) and applied another few minor cleanups. * * 2008-01-06 Holger Weiss for C99-snprintf 1.0: * * Added a lot of new features, fixed many bugs, and incorporated various * improvements done by Andrew Tridgell , Russ Allbery * , Hrvoje Niksic , Damien Miller * , and others for the Samba, INN, Wget, and OpenSSH * projects. The additions include: support the "e", "E", "g", "G", and * "F" conversion specifiers (and use conversion style "f" or "F" for the * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j", * "t", and "z" length modifiers; support the "#" flag and the (non-C99) * "'" flag; use localeconv(3) (if available) to get both the current * locale's decimal point character and the separator between groups of * digits; fix the handling of various corner cases of field width and * precision specifications; fix various floating point conversion bugs; * handle infinite and NaN floating point values; don't attempt to write to * the output buffer (which may be NULL) if a size of zero was specified; * check for integer overflow of the field width, precision, and return * values and during the floating point conversion; use the OUTCHAR() macro * instead of a function for better performance; provide asprintf(3) and * vasprintf(3) functions; add new test cases. The replacement functions * have been renamed to use an "rpl_" prefix, the function calls in the * main project (and in this file) must be redefined accordingly for each * replacement function which is needed (by using Autoconf or other means). * Various other minor improvements have been applied and the coding style * was cleaned up for consistency. * * 2007-07-23 Holger Weiss for Mutt 1.5.13: * * C99 compliant snprintf(3) and vsnprintf(3) functions return the number * of characters that would have been written to a sufficiently sized * buffer (excluding the '\0'). The original code simply returned the * length of the resulting output string, so that's been fixed. * * 1998-03-05 Michael Elkins for Mutt 0.90.8: * * The original code assumed that both snprintf(3) and vsnprintf(3) were * missing. Some systems only have snprintf(3) but not vsnprintf(3), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * 1998-01-27 Thomas Roessler for Mutt 0.89i: * * The PGP code was using unsigned hexadecimal formats. Unfortunately, * unsigned formats simply didn't work. * * 1997-10-22 Brandon Long for Mutt 0.87.1: * * Ok, added some minimal floating point support, which means this probably * requires libm on most operating systems. Don't yet support the exponent * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just * wasn't being exercised in ways which showed it, so that's been fixed. * Also, formatted the code to Mutt conventions, and removed dead code left * over from the original. Also, there is now a builtin-test, run with: * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf * * 2996-09-15 Brandon Long for Mutt 0.43: * * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything from the * normal C string format, at least as far as I can tell from the Solaris * 2.5 printf(3S) man page. */ /* * ToDo * * - Add wide character support. * - Add support for "%a" and "%A" conversions. * - Create test routines which predefine the expected results. Our test cases * usually expose bugs in system implementations rather than in ours :-) */ /* * Usage * * 1) The following preprocessor macros should be defined to 1 if the feature or * file in question is available on the target system (by using Autoconf or * other means), though basic functionality should be available as long as * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly: * * HAVE_VSNPRINTF * HAVE_SNPRINTF * HAVE_VASPRINTF * HAVE_ASPRINTF * HAVE_STDARG_H * HAVE_STDDEF_H * HAVE_STDINT_H * HAVE_STDLIB_H * HAVE_INTTYPES_H * HAVE_LOCALE_H * HAVE_LOCALECONV * HAVE_LCONV_DECIMAL_POINT * HAVE_LCONV_THOUSANDS_SEP * HAVE_LONG_DOUBLE * HAVE_LONG_LONG_INT * HAVE_UNSIGNED_LONG_LONG_INT * HAVE_INTMAX_T * HAVE_UINTMAX_T * HAVE_UINTPTR_T * HAVE_PTRDIFF_T * HAVE_VA_COPY * HAVE___VA_COPY * * 2) The calls to the functions which should be replaced must be redefined * throughout the project files (by using Autoconf or other means): * * #define vsnprintf rpl_vsnprintf * #define snprintf rpl_snprintf * #define vasprintf rpl_vasprintf * #define asprintf rpl_asprintf * * 3) The required replacement functions should be declared in some header file * included throughout the project files: * * #if HAVE_CONFIG_H * #include * #endif * #if HAVE_STDARG_H * #include * #if !HAVE_VSNPRINTF * int rpl_vsnprintf(char *, size_t, const char *, va_list); * #endif * #if !HAVE_SNPRINTF * int rpl_snprintf(char *, size_t, const char *, ...); * #endif * #if !HAVE_VASPRINTF * int rpl_vasprintf(char **, const char *, va_list); * #endif * #if !HAVE_ASPRINTF * int rpl_asprintf(char **, const char *, ...); * #endif * #endif * * Autoconf macros for handling step 1 and step 2 are available at * . */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #if TEST_SNPRINTF #include /* For pow(3), NAN, and INFINITY. */ #include /* For strcmp(3). */ #if defined(__NetBSD__) || \ defined(__FreeBSD__) || \ defined(__OpenBSD__) || \ defined(__NeXT__) || \ defined(__bsd__) #define OS_BSD 1 #elif defined(sgi) || defined(__sgi) #ifndef __c99 #define __c99 /* Force C99 mode to get included on IRIX 6.5.30. */ #endif /* !defined(__c99) */ #define OS_IRIX 1 #define OS_SYSV 1 #elif defined(__svr4__) #define OS_SYSV 1 #elif defined(__linux__) #define OS_LINUX 1 #endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */ #if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */ #ifdef HAVE_SNPRINTF #undef HAVE_SNPRINTF #endif /* defined(HAVE_SNPRINTF) */ #ifdef HAVE_VSNPRINTF #undef HAVE_VSNPRINTF #endif /* defined(HAVE_VSNPRINTF) */ #ifdef HAVE_ASPRINTF #undef HAVE_ASPRINTF #endif /* defined(HAVE_ASPRINTF) */ #ifdef HAVE_VASPRINTF #undef HAVE_VASPRINTF #endif /* defined(HAVE_VASPRINTF) */ #ifdef snprintf #undef snprintf #endif /* defined(snprintf) */ #ifdef vsnprintf #undef vsnprintf #endif /* defined(vsnprintf) */ #ifdef asprintf #undef asprintf #endif /* defined(asprintf) */ #ifdef vasprintf #undef vasprintf #endif /* defined(vasprintf) */ #else /* By default, we assume a modern system for testing. */ #ifndef HAVE_STDARG_H #define HAVE_STDARG_H 1 #endif /* HAVE_STDARG_H */ #ifndef HAVE_STDDEF_H #define HAVE_STDDEF_H 1 #endif /* HAVE_STDDEF_H */ #ifndef HAVE_STDINT_H #define HAVE_STDINT_H 1 #endif /* HAVE_STDINT_H */ #ifndef HAVE_STDLIB_H #define HAVE_STDLIB_H 1 #endif /* HAVE_STDLIB_H */ #ifndef HAVE_INTTYPES_H #define HAVE_INTTYPES_H 1 #endif /* HAVE_INTTYPES_H */ #ifndef HAVE_LOCALE_H #define HAVE_LOCALE_H 1 #endif /* HAVE_LOCALE_H */ #ifndef HAVE_LOCALECONV #define HAVE_LOCALECONV 1 #endif /* !defined(HAVE_LOCALECONV) */ #ifndef HAVE_LCONV_DECIMAL_POINT #define HAVE_LCONV_DECIMAL_POINT 1 #endif /* HAVE_LCONV_DECIMAL_POINT */ #ifndef HAVE_LCONV_THOUSANDS_SEP #define HAVE_LCONV_THOUSANDS_SEP 1 #endif /* HAVE_LCONV_THOUSANDS_SEP */ #ifndef HAVE_LONG_DOUBLE #define HAVE_LONG_DOUBLE 1 #endif /* !defined(HAVE_LONG_DOUBLE) */ #ifndef HAVE_LONG_LONG_INT #define HAVE_LONG_LONG_INT 1 #endif /* !defined(HAVE_LONG_LONG_INT) */ #ifndef HAVE_UNSIGNED_LONG_LONG_INT #define HAVE_UNSIGNED_LONG_LONG_INT 1 #endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */ #ifndef HAVE_INTMAX_T #define HAVE_INTMAX_T 1 #endif /* !defined(HAVE_INTMAX_T) */ #ifndef HAVE_UINTMAX_T #define HAVE_UINTMAX_T 1 #endif /* !defined(HAVE_UINTMAX_T) */ #ifndef HAVE_UINTPTR_T #define HAVE_UINTPTR_T 1 #endif /* !defined(HAVE_UINTPTR_T) */ #ifndef HAVE_PTRDIFF_T #define HAVE_PTRDIFF_T 1 #endif /* !defined(HAVE_PTRDIFF_T) */ #ifndef HAVE_VA_COPY #define HAVE_VA_COPY 1 #endif /* !defined(HAVE_VA_COPY) */ #ifndef HAVE___VA_COPY #define HAVE___VA_COPY 1 #endif /* !defined(HAVE___VA_COPY) */ #endif /* HAVE_CONFIG_H */ #define snprintf rpl_snprintf #define vsnprintf rpl_vsnprintf #define asprintf rpl_asprintf #define vasprintf rpl_vasprintf #endif /* TEST_SNPRINTF */ #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF #include /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */ #ifdef VA_START #undef VA_START #endif /* defined(VA_START) */ #ifdef VA_SHIFT #undef VA_SHIFT #endif /* defined(VA_SHIFT) */ #if HAVE_STDARG_H #include #define VA_START(ap, last) va_start(ap, last) #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ #else /* Assume is available. */ #include #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */ #define VA_SHIFT(ap, value, type) value = va_arg(ap, type) #endif /* HAVE_STDARG_H */ #if !HAVE_VASPRINTF #if HAVE_STDLIB_H #include /* For malloc(3). */ #endif /* HAVE_STDLIB_H */ #ifdef VA_COPY #undef VA_COPY #endif /* defined(VA_COPY) */ #ifdef VA_END_COPY #undef VA_END_COPY #endif /* defined(VA_END_COPY) */ #if HAVE_VA_COPY #define VA_COPY(dest, src) va_copy(dest, src) #define VA_END_COPY(ap) va_end(ap) #elif HAVE___VA_COPY #define VA_COPY(dest, src) __va_copy(dest, src) #define VA_END_COPY(ap) va_end(ap) #else #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list)) #define VA_END_COPY(ap) /* No-op. */ #define NEED_MYMEMCPY 1 static void *mymemcpy(void *, void *, size_t); #endif /* HAVE_VA_COPY */ #endif /* !HAVE_VASPRINTF */ #if !HAVE_VSNPRINTF #include /* For ERANGE and errno. */ #include /* For *_MAX. */ #if HAVE_INTTYPES_H #include /* For intmax_t (if not defined in ). */ #endif /* HAVE_INTTYPES_H */ #if HAVE_LOCALE_H #include /* For localeconv(3). */ #endif /* HAVE_LOCALE_H */ #if HAVE_STDDEF_H #include /* For ptrdiff_t. */ #endif /* HAVE_STDDEF_H */ #if HAVE_STDINT_H #include /* For intmax_t. */ #endif /* HAVE_STDINT_H */ /* Support for unsigned long long int. We may also need ULLONG_MAX. */ #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ #ifdef UINT_MAX #define ULONG_MAX UINT_MAX #else #define ULONG_MAX INT_MAX #endif /* defined(UINT_MAX) */ #endif /* !defined(ULONG_MAX) */ #ifdef ULLONG #undef ULLONG #endif /* defined(ULLONG) */ #if HAVE_UNSIGNED_LONG_LONG_INT #define ULLONG unsigned long long int #ifndef ULLONG_MAX #define ULLONG_MAX ULONG_MAX #endif /* !defined(ULLONG_MAX) */ #else #define ULLONG unsigned long int #ifdef ULLONG_MAX #undef ULLONG_MAX #endif /* defined(ULLONG_MAX) */ #define ULLONG_MAX ULONG_MAX #endif /* HAVE_LONG_LONG_INT */ /* Support for uintmax_t. We also need UINTMAX_MAX. */ #ifdef UINTMAX_T #undef UINTMAX_T #endif /* defined(UINTMAX_T) */ #if HAVE_UINTMAX_T || defined(uintmax_t) #define UINTMAX_T uintmax_t #ifndef UINTMAX_MAX #define UINTMAX_MAX ULLONG_MAX #endif /* !defined(UINTMAX_MAX) */ #else #define UINTMAX_T ULLONG #ifdef UINTMAX_MAX #undef UINTMAX_MAX #endif /* defined(UINTMAX_MAX) */ #define UINTMAX_MAX ULLONG_MAX #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ /* Support for long double. */ #ifndef LDOUBLE #if HAVE_LONG_DOUBLE #define LDOUBLE long double #else #define LDOUBLE double #endif /* HAVE_LONG_DOUBLE */ #endif /* !defined(LDOUBLE) */ /* Support for long long int. */ #ifndef LLONG #if HAVE_LONG_LONG_INT #define LLONG long long int #else #define LLONG long int #endif /* HAVE_LONG_LONG_INT */ #endif /* !defined(LLONG) */ /* Support for intmax_t. */ #ifndef INTMAX_T #if HAVE_INTMAX_T || defined(intmax_t) #define INTMAX_T intmax_t #else #define INTMAX_T LLONG #endif /* HAVE_INTMAX_T || defined(intmax_t) */ #endif /* !defined(INTMAX_T) */ /* Support for uintptr_t. */ #ifndef UINTPTR_T #if HAVE_UINTPTR_T || defined(uintptr_t) #define UINTPTR_T uintptr_t #else #define UINTPTR_T unsigned long int #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ #endif /* !defined(UINTPTR_T) */ /* Support for ptrdiff_t. */ #ifndef PTRDIFF_T #if HAVE_PTRDIFF_T || defined(ptrdiff_t) #define PTRDIFF_T ptrdiff_t #else #define PTRDIFF_T long int #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ #endif /* !defined(PTRDIFF_T) */ /* * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an * unsigned type if necessary. This should work just fine in practice. */ #ifndef UPTRDIFF_T #define UPTRDIFF_T PTRDIFF_T #endif /* !defined(UPTRDIFF_T) */ /* * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). * However, we'll simply use size_t and convert it to a signed type if * necessary. This should work just fine in practice. */ #ifndef SSIZE_T #define SSIZE_T size_t #endif /* !defined(SSIZE_T) */ /* Either ERANGE or E2BIG should be available everywhere. */ #ifndef ERANGE #define ERANGE E2BIG #endif /* !defined(ERANGE) */ #ifndef EOVERFLOW #define EOVERFLOW ERANGE #endif /* !defined(EOVERFLOW) */ /* * Buffer size to hold the octal string representation of UINT128_MAX without * nul-termination ("3777777777777777777777777777777777777777777"). */ #ifdef MAX_CONVERT_LENGTH #undef MAX_CONVERT_LENGTH #endif /* defined(MAX_CONVERT_LENGTH) */ #define MAX_CONVERT_LENGTH 43 /* Format read states. */ #define PRINT_S_DEFAULT 0 #define PRINT_S_FLAGS 1 #define PRINT_S_WIDTH 2 #define PRINT_S_DOT 3 #define PRINT_S_PRECISION 4 #define PRINT_S_MOD 5 #define PRINT_S_CONV 6 /* Format flags. */ #define PRINT_F_MINUS (1 << 0) #define PRINT_F_PLUS (1 << 1) #define PRINT_F_SPACE (1 << 2) #define PRINT_F_NUM (1 << 3) #define PRINT_F_ZERO (1 << 4) #define PRINT_F_QUOTE (1 << 5) #define PRINT_F_UP (1 << 6) #define PRINT_F_UNSIGNED (1 << 7) #define PRINT_F_TYPE_G (1 << 8) #define PRINT_F_TYPE_E (1 << 9) /* Conversion flags. */ #define PRINT_C_CHAR 1 #define PRINT_C_SHORT 2 #define PRINT_C_LONG 3 #define PRINT_C_LLONG 4 #define PRINT_C_LDOUBLE 5 #define PRINT_C_SIZE 6 #define PRINT_C_PTRDIFF 7 #define PRINT_C_INTMAX 8 #ifndef MAX #define MAX(x, y) ((x >= y) ? x : y) #endif /* !defined(MAX) */ #ifndef CHARTOINT #define CHARTOINT(ch) (ch - '0') #endif /* !defined(CHARTOINT) */ #ifndef ISDIGIT #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') #endif /* !defined(ISDIGIT) */ #ifndef ISNAN #define ISNAN(x) (x != x) #endif /* !defined(ISNAN) */ #ifndef ISINF #define ISINF(x) (x != 0.0 && x + x == x) #endif /* !defined(ISINF) */ #ifdef OUTCHAR #undef OUTCHAR #endif /* defined(OUTCHAR) */ #define OUTCHAR(str, len, size, ch) \ do { \ if (len + 1 < size) \ str[len] = ch; \ (len)++; \ } while (/* CONSTCOND */ 0) static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); static void printsep(char *, size_t *, size_t); static int getnumsep(int); static int getexponent(LDOUBLE); static int convert(UINTMAX_T, char *, size_t, int, int); static UINTMAX_T cast(LDOUBLE); static UINTMAX_T myround(LDOUBLE); static LDOUBLE mypow10(int); /*extern int errno;*/ int rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) { LDOUBLE fvalue; INTMAX_T value; unsigned char cvalue; const char *strvalue; INTMAX_T *intmaxptr; PTRDIFF_T *ptrdiffptr; SSIZE_T *sizeptr; LLONG *llongptr; long int *longptr; int *intptr; short int *shortptr; signed char *charptr; size_t len = 0; int overflow = 0; int base = 0; int cflags = 0; int flags = 0; int width = 0; int precision = -1; int state = PRINT_S_DEFAULT; char ch = *format++; /* * C99 says: "If `n' is zero, nothing is written, and `s' may be a null * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer * even if a size larger than zero was specified. At least NetBSD's * snprintf(3) does the same, as well as other versions of this file. * (Though some of these versions will write to a non-NULL buffer even * if a size of zero was specified, which violates the standard.) */ if (str == NULL && size != 0) size = 0; while (ch != '\0') switch (state) { case PRINT_S_DEFAULT: if (ch == '%') state = PRINT_S_FLAGS; else OUTCHAR(str, len, size, ch); ch = *format++; break; case PRINT_S_FLAGS: switch (ch) { case '-': flags |= PRINT_F_MINUS; ch = *format++; break; case '+': flags |= PRINT_F_PLUS; ch = *format++; break; case ' ': flags |= PRINT_F_SPACE; ch = *format++; break; case '#': flags |= PRINT_F_NUM; ch = *format++; break; case '0': flags |= PRINT_F_ZERO; ch = *format++; break; case '\'': /* SUSv2 flag (not in C99). */ flags |= PRINT_F_QUOTE; ch = *format++; break; default: state = PRINT_S_WIDTH; break; } break; case PRINT_S_WIDTH: if (ISDIGIT(ch)) { ch = CHARTOINT(ch); if (width > (INT_MAX - ch) / 10) { overflow = 1; goto out; } width = 10 * width + ch; ch = *format++; } else if (ch == '*') { /* * C99 says: "A negative field width argument is * taken as a `-' flag followed by a positive * field width." (7.19.6.1, 5) */ if ((width = va_arg(args, int)) < 0) { flags |= PRINT_F_MINUS; width = -width; } ch = *format++; state = PRINT_S_DOT; } else state = PRINT_S_DOT; break; case PRINT_S_DOT: if (ch == '.') { state = PRINT_S_PRECISION; ch = *format++; } else state = PRINT_S_MOD; break; case PRINT_S_PRECISION: if (precision == -1) precision = 0; if (ISDIGIT(ch)) { ch = CHARTOINT(ch); if (precision > (INT_MAX - ch) / 10) { overflow = 1; goto out; } precision = 10 * precision + ch; ch = *format++; } else if (ch == '*') { /* * C99 says: "A negative precision argument is * taken as if the precision were omitted." * (7.19.6.1, 5) */ if ((precision = va_arg(args, int)) < 0) precision = -1; ch = *format++; state = PRINT_S_MOD; } else state = PRINT_S_MOD; break; case PRINT_S_MOD: switch (ch) { case 'h': ch = *format++; if (ch == 'h') { /* It's a char. */ ch = *format++; cflags = PRINT_C_CHAR; } else cflags = PRINT_C_SHORT; break; case 'l': ch = *format++; if (ch == 'l') { /* It's a long long. */ ch = *format++; cflags = PRINT_C_LLONG; } else cflags = PRINT_C_LONG; break; case 'L': cflags = PRINT_C_LDOUBLE; ch = *format++; break; case 'j': cflags = PRINT_C_INTMAX; ch = *format++; break; case 't': cflags = PRINT_C_PTRDIFF; ch = *format++; break; case 'z': cflags = PRINT_C_SIZE; ch = *format++; break; } state = PRINT_S_CONV; break; case PRINT_S_CONV: switch (ch) { case 'd': /* FALLTHROUGH */ case 'i': switch (cflags) { case PRINT_C_CHAR: value = (signed char)va_arg(args, int); break; case PRINT_C_SHORT: value = (short int)va_arg(args, int); break; case PRINT_C_LONG: value = va_arg(args, long int); break; case PRINT_C_LLONG: value = va_arg(args, LLONG); break; case PRINT_C_SIZE: value = va_arg(args, SSIZE_T); break; case PRINT_C_INTMAX: value = va_arg(args, INTMAX_T); break; case PRINT_C_PTRDIFF: value = va_arg(args, PTRDIFF_T); break; default: value = va_arg(args, int); break; } fmtint(str, &len, size, value, 10, width, precision, flags); break; case 'X': flags |= PRINT_F_UP; /* FALLTHROUGH */ case 'x': base = 16; /* FALLTHROUGH */ case 'o': if (base == 0) base = 8; /* FALLTHROUGH */ case 'u': if (base == 0) base = 10; flags |= PRINT_F_UNSIGNED; switch (cflags) { case PRINT_C_CHAR: value = (unsigned char)va_arg(args, unsigned int); break; case PRINT_C_SHORT: value = (unsigned short int)va_arg(args, unsigned int); break; case PRINT_C_LONG: value = va_arg(args, unsigned long int); break; case PRINT_C_LLONG: value = va_arg(args, ULLONG); break; case PRINT_C_SIZE: value = va_arg(args, size_t); break; case PRINT_C_INTMAX: value = va_arg(args, UINTMAX_T); break; case PRINT_C_PTRDIFF: value = va_arg(args, UPTRDIFF_T); break; default: value = va_arg(args, unsigned int); break; } fmtint(str, &len, size, value, base, width, precision, flags); break; case 'A': /* Not yet supported, we'll use "%F". */ /* FALLTHROUGH */ case 'F': flags |= PRINT_F_UP; case 'a': /* Not yet supported, we'll use "%f". */ /* FALLTHROUGH */ case 'f': if (cflags == PRINT_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow); if (overflow) goto out; break; case 'E': flags |= PRINT_F_UP; /* FALLTHROUGH */ case 'e': flags |= PRINT_F_TYPE_E; if (cflags == PRINT_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow); if (overflow) goto out; break; case 'G': flags |= PRINT_F_UP; /* FALLTHROUGH */ case 'g': flags |= PRINT_F_TYPE_G; if (cflags == PRINT_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else fvalue = va_arg(args, double); /* * If the precision is zero, it is treated as * one (cf. C99: 7.19.6.1, 8). */ if (precision == 0) precision = 1; fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow); if (overflow) goto out; break; case 'c': cvalue = va_arg(args, int); OUTCHAR(str, len, size, cvalue); break; case 's': strvalue = va_arg(args, char *); fmtstr(str, &len, size, strvalue, width, precision, flags); break; case 'p': /* * C99 says: "The value of the pointer is * converted to a sequence of printing * characters, in an implementation-defined * manner." (C99: 7.19.6.1, 8) */ if ((strvalue = va_arg(args, void *)) == NULL) /* * We use the glibc format. BSD prints * "0x0", SysV "0". */ fmtstr(str, &len, size, "(nil)", width, -1, flags); else { /* * We use the BSD/glibc format. SysV * omits the "0x" prefix (which we emit * using the PRINT_F_NUM flag). */ flags |= PRINT_F_NUM; flags |= PRINT_F_UNSIGNED; fmtint(str, &len, size, (UINTPTR_T)strvalue, 16, width, precision, flags); } break; case 'n': switch (cflags) { case PRINT_C_CHAR: charptr = va_arg(args, signed char *); *charptr = len; break; case PRINT_C_SHORT: shortptr = va_arg(args, short int *); *shortptr = len; break; case PRINT_C_LONG: longptr = va_arg(args, long int *); *longptr = len; break; case PRINT_C_LLONG: llongptr = va_arg(args, LLONG *); *llongptr = len; break; case PRINT_C_SIZE: /* * C99 says that with the "z" length * modifier, "a following `n' conversion * specifier applies to a pointer to a * signed integer type corresponding to * size_t argument." (7.19.6.1, 7) */ sizeptr = va_arg(args, SSIZE_T *); *sizeptr = len; break; case PRINT_C_INTMAX: intmaxptr = va_arg(args, INTMAX_T *); *intmaxptr = len; break; case PRINT_C_PTRDIFF: ptrdiffptr = va_arg(args, PTRDIFF_T *); *ptrdiffptr = len; break; default: intptr = va_arg(args, int *); *intptr = len; break; } break; case '%': /* Print a "%" character verbatim. */ OUTCHAR(str, len, size, ch); break; default: /* Skip other characters. */ break; } ch = *format++; state = PRINT_S_DEFAULT; base = cflags = flags = width = 0; precision = -1; break; } out: if (len < size) str[len] = '\0'; else if (size > 0) str[size - 1] = '\0'; if (overflow || len >= INT_MAX) { errno = overflow ? EOVERFLOW : ERANGE; return -1; } return (int)len; } static void fmtstr(char *str, size_t *len, size_t size, const char *value, int width, int precision, int flags) { int padlen, strln; /* Amount to pad. */ int noprecision = (precision == -1); if (value == NULL) /* We're forgiving. */ value = "(null)"; /* If a precision was specified, don't read the string past it. */ for (strln = 0; value[strln] != '\0' && (noprecision || strln < precision); strln++) continue; if ((padlen = width - strln) < 0) padlen = 0; if (flags & PRINT_F_MINUS) /* Left justify. */ padlen = -padlen; while (padlen > 0) { /* Leading spaces. */ OUTCHAR(str, *len, size, ' '); padlen--; } while (*value != '\0' && (noprecision || precision-- > 0)) { OUTCHAR(str, *len, size, *value); value++; } while (padlen < 0) { /* Trailing spaces. */ OUTCHAR(str, *len, size, ' '); padlen++; } } static void fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, int precision, int flags) { UINTMAX_T uvalue; char iconvert[MAX_CONVERT_LENGTH]; char sign = 0; char hexprefix = 0; int spadlen = 0; /* Amount to space pad. */ int zpadlen = 0; /* Amount to zero pad. */ int pos; int separators = (flags & PRINT_F_QUOTE); int noprecision = (precision == -1); if (flags & PRINT_F_UNSIGNED) uvalue = value; else { uvalue = (value >= 0) ? value : -value; if (value < 0) sign = '-'; else if (flags & PRINT_F_PLUS) /* Do a sign. */ sign = '+'; else if (flags & PRINT_F_SPACE) sign = ' '; } pos = convert(uvalue, iconvert, sizeof(iconvert), base, flags & PRINT_F_UP); if (flags & PRINT_F_NUM && uvalue != 0) { /* * C99 says: "The result is converted to an `alternative form'. * For `o' conversion, it increases the precision, if and only * if necessary, to force the first digit of the result to be a * zero (if the value and precision are both 0, a single 0 is * printed). For `x' (or `X') conversion, a nonzero result has * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) */ switch (base) { case 8: if (precision <= pos) precision = pos + 1; break; case 16: hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; break; } } if (separators) /* Get the number of group separators we'll print. */ separators = getnumsep(pos); zpadlen = precision - pos - separators; spadlen = width /* Minimum field width. */ - separators /* Number of separators. */ - MAX(precision, pos) /* Number of integer digits. */ - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; /* * C99 says: "If the `0' and `-' flags both appear, the `0' flag is * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) */ if (flags & PRINT_F_MINUS) /* Left justify. */ spadlen = -spadlen; else if (flags & PRINT_F_ZERO && noprecision) { zpadlen += spadlen; spadlen = 0; } while (spadlen > 0) { /* Leading spaces. */ OUTCHAR(str, *len, size, ' '); spadlen--; } if (sign != 0) /* Sign. */ OUTCHAR(str, *len, size, sign); if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ OUTCHAR(str, *len, size, '0'); OUTCHAR(str, *len, size, hexprefix); } while (zpadlen > 0) { /* Leading zeros. */ OUTCHAR(str, *len, size, '0'); zpadlen--; } while (pos > 0) { /* The actual digits. */ pos--; OUTCHAR(str, *len, size, iconvert[pos]); if (separators > 0 && pos > 0 && pos % 3 == 0) printsep(str, len, size); } while (spadlen < 0) { /* Trailing spaces. */ OUTCHAR(str, *len, size, ' '); spadlen++; } } static void fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, int precision, int flags, int *overflow) { LDOUBLE ufvalue; UINTMAX_T intpart; UINTMAX_T fracpart; UINTMAX_T mask; const char *infnan = NULL; char iconvert[MAX_CONVERT_LENGTH]; char fconvert[MAX_CONVERT_LENGTH]; char econvert[4]; /* "e-12" (without nul-termination). */ char esign = 0; char sign = 0; int leadfraczeros = 0; int exponent = 0; int emitpoint = 0; int omitzeros = 0; int omitcount = 0; int padlen = 0; int epos = 0; int fpos = 0; int ipos = 0; int separators = (flags & PRINT_F_QUOTE); int estyle = (flags & PRINT_F_TYPE_E); #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT struct lconv *lc = localeconv(); #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ /* * AIX' man page says the default is 0, but C99 and at least Solaris' * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX * defaults to 6. */ if (precision == -1) precision = 6; if (fvalue < 0.0) sign = '-'; else if (flags & PRINT_F_PLUS) /* Do a sign. */ sign = '+'; else if (flags & PRINT_F_SPACE) sign = ' '; if (ISNAN(fvalue)) infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; else if (ISINF(fvalue)) infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; if (infnan != NULL) { if (sign != 0) iconvert[ipos++] = sign; while (*infnan != '\0') iconvert[ipos++] = *infnan++; fmtstr(str, len, size, iconvert, width, ipos, flags); return; } /* "%e" (or "%E") or "%g" (or "%G") conversion. */ if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { if (flags & PRINT_F_TYPE_G) { /* * For "%g" (and "%G") conversions, the precision * specifies the number of significant digits, which * includes the digits in the integer part. The * conversion will or will not be using "e-style" (like * "%e" or "%E" conversions) depending on the precision * and on the exponent. However, the exponent can be * affected by rounding the converted value, so we'll * leave this decision for later. Until then, we'll * assume that we're going to do an "e-style" conversion * (in order to get the exponent calculated). For * "e-style", the precision must be decremented by one. */ precision--; /* * For "%g" (and "%G") conversions, trailing zeros are * removed from the fractional portion of the result * unless the "#" flag was specified. */ if (!(flags & PRINT_F_NUM)) omitzeros = 1; } exponent = getexponent(fvalue); estyle = 1; } again: /* * Sorry, we only support 9, 19, or 38 digits (that is, the number of * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value * minus one) past the decimal point due to our conversion method. */ switch (sizeof(UINTMAX_T)) { case 16: if (precision > 38) precision = 38; break; case 8: if (precision > 19) precision = 19; break; default: if (precision > 9) precision = 9; break; } ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; if (estyle) /* We want exactly one integer digit. */ ufvalue /= mypow10(exponent); if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { *overflow = 1; return; } /* * Factor of ten with the number of digits needed for the fractional * part. For example, if the precision is 3, the mask will be 1000. */ mask = mypow10(precision); /* * We "cheat" by converting the fractional part to integer by * multiplying by a factor of ten. */ if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { /* * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 * (because precision = 3). Now, myround(1000 * 0.99962) will * return 1000. So, the integer part must be incremented by one * and the fractional part must be set to zero. */ intpart++; fracpart = 0; if (estyle && intpart == 10) { /* * The value was rounded up to ten, but we only want one * integer digit if using "e-style". So, the integer * part must be set to one and the exponent must be * incremented by one. */ intpart = 1; exponent++; } } /* * Now that we know the real exponent, we can check whether or not to * use "e-style" for "%g" (and "%G") conversions. If we don't need * "e-style", the precision must be adjusted and the integer and * fractional parts must be recalculated from the original value. * * C99 says: "Let P equal the precision if nonzero, 6 if the precision * is omitted, or 1 if the precision is zero. Then, if a conversion * with style `E' would have an exponent of X: * * - if P > X >= -4, the conversion is with style `f' (or `F') and * precision P - (X + 1). * * - otherwise, the conversion is with style `e' (or `E') and precision * P - 1." (7.19.6.1, 8) * * Note that we had decremented the precision by one. */ if (flags & PRINT_F_TYPE_G && estyle && precision + 1 > exponent && exponent >= -4) { precision -= exponent; estyle = 0; goto again; } if (estyle) { if (exponent < 0) { exponent = -exponent; esign = '-'; } else esign = '+'; /* * Convert the exponent. The sizeof(econvert) is 4. So, the * econvert buffer can hold e.g. "e+99" and "e-99". We don't * support an exponent which contains more than two digits. * Therefore, the following stores are safe. */ epos = convert(exponent, econvert, 2, 10, 0); /* * C99 says: "The exponent always contains at least two digits, * and only as many more digits as necessary to represent the * exponent." (7.19.6.1, 8) */ if (epos == 1) econvert[epos++] = '0'; econvert[epos++] = esign; econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; } /* Convert the integer part and the fractional part. */ ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); leadfraczeros = precision - fpos; if (omitzeros) { if (fpos > 0) /* Omit trailing fractional part zeros. */ while (omitcount < fpos && fconvert[omitcount] == '0') omitcount++; else { /* The fractional part is zero, omit it completely. */ omitcount = precision; leadfraczeros = 0; } precision -= omitcount; } /* * Print a decimal point if either the fractional part is non-zero * and/or the "#" flag was specified. */ if (precision > 0 || flags & PRINT_F_NUM) emitpoint = 1; if (separators) /* Get the number of group separators we'll print. */ separators = getnumsep(ipos); padlen = width /* Minimum field width. */ - ipos /* Number of integer digits. */ - epos /* Number of exponent characters. */ - precision /* Number of fractional digits. */ - separators /* Number of group separators. */ - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ if (padlen < 0) padlen = 0; /* * C99 says: "If the `0' and `-' flags both appear, the `0' flag is * ignored." (7.19.6.1, 6) */ if (flags & PRINT_F_MINUS) /* Left justifty. */ padlen = -padlen; else if (flags & PRINT_F_ZERO && padlen > 0) { if (sign != 0) { /* Sign. */ OUTCHAR(str, *len, size, sign); sign = 0; } while (padlen > 0) { /* Leading zeros. */ OUTCHAR(str, *len, size, '0'); padlen--; } } while (padlen > 0) { /* Leading spaces. */ OUTCHAR(str, *len, size, ' '); padlen--; } if (sign != 0) /* Sign. */ OUTCHAR(str, *len, size, sign); while (ipos > 0) { /* Integer part. */ ipos--; OUTCHAR(str, *len, size, iconvert[ipos]); if (separators > 0 && ipos > 0 && ipos % 3 == 0) printsep(str, len, size); } if (emitpoint) { /* Decimal point. */ #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT if (lc->decimal_point != NULL && *lc->decimal_point != '\0') OUTCHAR(str, *len, size, *lc->decimal_point); else /* We'll always print some decimal point character. */ #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */ OUTCHAR(str, *len, size, '.'); } while (leadfraczeros > 0) { /* Leading fractional part zeros. */ OUTCHAR(str, *len, size, '0'); leadfraczeros--; } while (fpos > omitcount) { /* The remaining fractional part. */ fpos--; OUTCHAR(str, *len, size, fconvert[fpos]); } while (epos > 0) { /* Exponent. */ epos--; OUTCHAR(str, *len, size, econvert[epos]); } while (padlen < 0) { /* Trailing spaces. */ OUTCHAR(str, *len, size, ' '); padlen++; } } static void printsep(char *str, size_t *len, size_t size) { #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP struct lconv *lc = localeconv(); int i; if (lc->thousands_sep != NULL) for (i = 0; lc->thousands_sep[i] != '\0'; i++) OUTCHAR(str, *len, size, lc->thousands_sep[i]); else #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ OUTCHAR(str, *len, size, ','); } static int getnumsep(int digits) { int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP int strln; struct lconv *lc = localeconv(); /* We support an arbitrary separator length (including zero). */ if (lc->thousands_sep != NULL) { for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++) continue; separators *= strln; } #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */ return separators; } static int getexponent(LDOUBLE value) { LDOUBLE tmp = (value >= 0.0) ? value : -value; int exponent = 0; /* * We check for 99 > exponent > -99 in order to work around possible * endless loops which could happen (at least) in the second loop (at * least) if we're called with an infinite value. However, we checked * for infinity before calling this function using our ISINF() macro, so * this might be somewhat paranoid. */ while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) tmp *= 10; while (tmp >= 10.0 && ++exponent < 99) tmp /= 10; return exponent; } static int convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) { const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; size_t pos = 0; /* We return an unterminated buffer with the digits in reverse order. */ do { buf[pos++] = digits[value % base]; value /= base; } while (value != 0 && pos < size); return (int)pos; } static UINTMAX_T cast(LDOUBLE value) { UINTMAX_T result; /* * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), * it may be increased to the nearest higher representable value for the * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE * value although converting the latter to UINTMAX_T would overflow. */ if (value >= UINTMAX_MAX) return UINTMAX_MAX; result = value; /* * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates * the standard). Sigh. */ return (result <= value) ? result : result - 1; } static UINTMAX_T myround(LDOUBLE value) { UINTMAX_T intpart = cast(value); return ((value -= intpart) < 0.5) ? intpart : intpart + 1; } static LDOUBLE mypow10(int exponent) { LDOUBLE result = 1; while (exponent > 0) { result *= 10; exponent--; } while (exponent < 0) { result /= 10; exponent++; } return result; } #endif /* !HAVE_VSNPRINTF */ #if !HAVE_VASPRINTF #if NEED_MYMEMCPY void * mymemcpy(void *dst, void *src, size_t len) { const char *from = src; char *to = dst; /* No need for optimization, we use this only to replace va_copy(3). */ while (len-- > 0) *to++ = *from++; return dst; } #endif /* NEED_MYMEMCPY */ int rpl_vasprintf(char **ret, const char *format, va_list ap) { size_t size; int len; va_list aq; VA_COPY(aq, ap); len = vsnprintf(NULL, 0, format, aq); VA_END_COPY(aq); if (len < 0 || (*ret = malloc(size = len + 1)) == NULL) return -1; return vsnprintf(*ret, size, format, ap); } #endif /* !HAVE_VASPRINTF */ #if !HAVE_SNPRINTF #if HAVE_STDARG_H int rpl_snprintf(char *str, size_t size, const char *format, ...) #else int rpl_snprintf(va_alist) va_dcl #endif /* HAVE_STDARG_H */ { #if !HAVE_STDARG_H char *str; size_t size; char *format; #endif /* HAVE_STDARG_H */ va_list ap; int len; VA_START(ap, format); VA_SHIFT(ap, str, char *); VA_SHIFT(ap, size, size_t); VA_SHIFT(ap, format, const char *); len = vsnprintf(str, size, format, ap); va_end(ap); return len; } #endif /* !HAVE_SNPRINTF */ #if !HAVE_ASPRINTF #if HAVE_STDARG_H int rpl_asprintf(char **ret, const char *format, ...) #else int rpl_asprintf(va_alist) va_dcl #endif /* HAVE_STDARG_H */ { #if !HAVE_STDARG_H char **ret; char *format; #endif /* HAVE_STDARG_H */ va_list ap; int len; VA_START(ap, format); VA_SHIFT(ap, ret, char **); VA_SHIFT(ap, format, const char *); len = vasprintf(ret, format, ap); va_end(ap); return len; } #endif /* !HAVE_ASPRINTF */ /* If [v]snprintf() does not exist or is not C99 compatible, then we assume * that [v]printf() and [v]fprintf() need to be provided as well. */ #if !HAVE_VSNPRINTF int rpl_vfprintf(FILE *stream, const char *format, va_list ap) { va_list ap2; char staticbuf[1024]; char *buf = staticbuf; /* Try to write to staticbuf. */ va_copy(ap2, ap); int len = vsnprintf(staticbuf, sizeof(staticbuf), format, ap2); va_end(ap2); /* Was the output truncated? */ if (len >= sizeof(staticbuf)) { size_t buf_size = len + 1; buf = malloc(buf_size); if (buf == NULL) { return -1; } /* Write to the allocated buffer. */ va_copy(ap2, ap); len = vsnprintf(buf, buf_size, format, ap2); va_end(ap2); /* Truncated again! Should never happen! */ if (len >= buf_size) { len = -1; } } /* Finally write to the stream. */ if (len > 0) { len = fwrite(buf, 1, len, stream); } if (buf != staticbuf) { free(buf); } return len; } int rpl_vprintf(const char *format, va_list ap) { va_list ap2; va_copy(ap2, ap); int len = vfprintf(stdout, format, ap); va_end(ap2); return len; } #endif #if !HAVE_SNPRINTF int rpl_fprintf(FILE *stream, const char *format, ...) { va_list ap; int len; va_start(ap, format); len = vfprintf(stream, format, ap); va_end(ap); return len; } int rpl_printf(const char *format, ...) { va_list ap; va_start(ap, format); int len = vprintf(format, ap); va_end(ap); return len; } #endif #else /* Dummy declaration to avoid empty translation unit warnings. */ int main(void); #endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */ #if TEST_SNPRINTF /* sprintf() is marked as deprecated in CFEngine, but here we use it on * purpose to compare this snprintf() implementation to the system's * implementation. So avoid emitting the warning. */ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" static int snprintf_rigorous_test(void) { const char *float_fmt[] = { /* "%E" and "%e" formats. */ #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX "%.16e", "%22.16e", "%022.16e", "%-22.16e", "%#+'022.16e", #endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */ "foo|%#+0123.9E|bar", "%-123.9e", "%123.9e", "%+23.9e", "%+05.8e", "%-05.8e", "%05.8e", "%+5.8e", "%-5.8e", "% 5.8e", "%5.8e", "%+4.9e", #if !OS_LINUX /* glibc sometimes gets these wrong. */ "%+#010.0e", "%#10.1e", "%10.5e", "% 10.5e", "%5.0e", "%5.e", "%#5.0e", "%#5.e", "%3.2e", "%3.1e", "%-1.5e", "%1.5e", "%01.3e", "%1.e", "%.1e", "%#.0e", "%+.0e", "% .0e", "%.0e", "%#.e", "%+.e", "% .e", "%.e", "%4e", "%e", "%E", #endif /* !OS_LINUX */ /* "%F" and "%f" formats. */ #if !OS_BSD && !OS_IRIX "% '022f", "%+'022f", "%-'22f", "%'22f", #if HAVE_LONG_LONG_INT "%.16f", "%22.16f", "%022.16f", "%-22.16f", "%#+'022.16f", #endif /* HAVE_LONG_LONG_INT */ #endif /* !OS_BSD && !OS_IRIX */ "foo|%#+0123.9F|bar", "%-123.9f", "%123.9f", "%+23.9f", "%+#010.0f", "%#10.1f", "%10.5f", "% 10.5f", "%+05.8f", "%-05.8f", "%05.8f", "%+5.8f", "%-5.8f", "% 5.8f", "%5.8f", "%5.0f", "%5.f", "%#5.0f", "%#5.f", "%+4.9f", "%3.2f", "%3.1f", "%-1.5f", "%1.5f", "%01.3f", "%1.f", "%.1f", "%#.0f", "%+.0f", "% .0f", "%.0f", "%#.f", "%+.f", "% .f", "%.f", "%4f", "%f", "%F", /* "%G" and "%g" formats. */ #if !OS_BSD && !OS_IRIX && !OS_LINUX "% '022g", "%+'022g", "%-'22g", "%'22g", #if HAVE_LONG_LONG_INT "%.16g", "%22.16g", "%022.16g", "%-22.16g", "%#+'022.16g", #endif /* HAVE_LONG_LONG_INT */ #endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */ "foo|%#+0123.9G|bar", "%-123.9g", "%123.9g", "%+23.9g", "%+05.8g", "%-05.8g", "%05.8g", "%+5.8g", "%-5.8g", "% 5.8g", "%5.8g", "%+4.9g", #if !OS_LINUX /* glibc sometimes gets these wrong. */ "%+#010.0g", "%#10.1g", "%10.5g", "% 10.5g", "%5.0g", "%5.g", "%#5.0g", "%#5.g", "%3.2g", "%3.1g", "%-1.5g", "%1.5g", "%01.3g", "%1.g", "%.1g", "%#.0g", "%+.0g", "% .0g", "%.0g", "%#.g", "%+.g", "% .g", "%.g", "%4g", "%g", "%G", #endif /* !OS_LINUX */ NULL }; double float_val[] = { -4.136, -134.52, -5.04030201, -3410.01234, -999999.999999, -913450.29876, -913450.2, -91345.2, -9134.2, -913.2, -91.2, -9.2, -9.9, 4.136, 134.52, 5.04030201, 3410.01234, 999999.999999, 913450.29876, 913450.2, 91345.2, 9134.2, 913.2, 91.2, 9.2, 9.9, 9.96, 9.996, 9.9996, 9.99996, 9.999996, 9.9999996, 9.99999996, 0.99999996, 0.99999999, 0.09999999, 0.00999999, 0.00099999, 0.00009999, 0.00000999, 0.00000099, 0.00000009, 0.00000001, 0.0000001, 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1.0, 1.5, -1.5, -1.0, -0.1, #if !OS_BSD /* BSD sometimes gets these wrong. */ #ifdef INFINITY INFINITY, -INFINITY, #endif /* defined(INFINITY) */ #ifdef NAN NAN, #endif /* defined(NAN) */ #endif /* !OS_BSD */ 0 }; const char *long_fmt[] = { "foo|%0123ld|bar", #if !OS_IRIX "% '0123ld", "%+'0123ld", "%-'123ld", "%'123ld", #endif /* !OS_IRiX */ "%123.9ld", "% 123.9ld", "%+123.9ld", "%-123.9ld", "%0123ld", "% 0123ld", "%+0123ld", "%-0123ld", "%10.5ld", "% 10.5ld", "%+10.5ld", "%-10.5ld", "%010ld", "% 010ld", "%+010ld", "%-010ld", "%4.2ld", "% 4.2ld", "%+4.2ld", "%-4.2ld", "%04ld", "% 04ld", "%+04ld", "%-04ld", "%5.5ld", "%+22.33ld", "%01.3ld", "%1.5ld", "%-1.5ld", "%44ld", "%4ld", "%4.0ld", "%4.ld", "%.44ld", "%.4ld", "%.0ld", "%.ld", "%ld", NULL }; long int long_val[] = { #ifdef LONG_MAX LONG_MAX, #endif /* LONG_MAX */ #ifdef LONG_MIN LONG_MIN, #endif /* LONG_MIN */ -91340, 91340, 341, 134, 0203, -1, 1, 0 }; const char *ulong_fmt[] = { /* "%u" formats. */ "foo|%0123lu|bar", #if !OS_IRIX "% '0123lu", "%+'0123lu", "%-'123lu", "%'123lu", #endif /* !OS_IRiX */ "%123.9lu", "% 123.9lu", "%+123.9lu", "%-123.9lu", "%0123lu", "% 0123lu", "%+0123lu", "%-0123lu", "%5.5lu", "%+22.33lu", "%01.3lu", "%1.5lu", "%-1.5lu", "%44lu", "%lu", /* "%o" formats. */ "foo|%#0123lo|bar", "%#123.9lo", "%# 123.9lo", "%#+123.9lo", "%#-123.9lo", "%#0123lo", "%# 0123lo", "%#+0123lo", "%#-0123lo", "%#5.5lo", "%#+22.33lo", "%#01.3lo", "%#1.5lo", "%#-1.5lo", "%#44lo", "%#lo", "%123.9lo", "% 123.9lo", "%+123.9lo", "%-123.9lo", "%0123lo", "% 0123lo", "%+0123lo", "%-0123lo", "%5.5lo", "%+22.33lo", "%01.3lo", "%1.5lo", "%-1.5lo", "%44lo", "%lo", /* "%X" and "%x" formats. */ "foo|%#0123lX|bar", "%#123.9lx", "%# 123.9lx", "%#+123.9lx", "%#-123.9lx", "%#0123lx", "%# 0123lx", "%#+0123lx", "%#-0123lx", "%#5.5lx", "%#+22.33lx", "%#01.3lx", "%#1.5lx", "%#-1.5lx", "%#44lx", "%#lx", "%#lX", "%123.9lx", "% 123.9lx", "%+123.9lx", "%-123.9lx", "%0123lx", "% 0123lx", "%+0123lx", "%-0123lx", "%5.5lx", "%+22.33lx", "%01.3lx", "%1.5lx", "%-1.5lx", "%44lx", "%lx", "%lX", NULL }; unsigned long int ulong_val[] = { #ifdef ULONG_MAX ULONG_MAX, #endif /* ULONG_MAX */ 91340, 341, 134, 0203, 1, 0 }; const char *llong_fmt[] = { "foo|%0123lld|bar", "%123.9lld", "% 123.9lld", "%+123.9lld", "%-123.9lld", "%0123lld", "% 0123lld", "%+0123lld", "%-0123lld", "%5.5lld", "%+22.33lld", "%01.3lld", "%1.5lld", "%-1.5lld", "%44lld", "%lld", NULL }; LLONG llong_val[] = { #ifdef LLONG_MAX LLONG_MAX, #endif /* LLONG_MAX */ #ifdef LLONG_MIN LLONG_MIN, #endif /* LLONG_MIN */ -91340, 91340, 341, 134, 0203, -1, 1, 0 }; const char *string_fmt[] = { "foo|%10.10s|bar", "%-10.10s", "%10.10s", "%10.5s", "%5.10s", "%10.1s", "%1.10s", "%10.0s", "%0.10s", "%-42.5s", "%2.s", "%.10s", "%.1s", "%.0s", "%.s", "%4s", "%s", NULL }; const char *string_val[] = { "Hello", "Hello, world!", "Sound check: One, two, three.", "This string is a little longer than the other strings.", "1", "", NULL }; #if !OS_SYSV /* SysV uses a different format than we do. */ const char *pointer_fmt[] = { "foo|%p|bar", "%42p", "%p", NULL }; const char *pointer_val[] = { *pointer_fmt, *string_fmt, *string_val, NULL }; #endif /* !OS_SYSV */ char buf1[1024], buf2[1024]; double value, digits = 9.123456789012345678901234567890123456789; int i, j, r1, r2, failed = 0, num = 0; /* * Use -DTEST_NILS in order to also test the conversion of nil values. Might * segfault on systems which don't support converting a NULL pointer with "%s" * and lets some test cases fail against BSD and glibc due to bugs in their * implementations. */ #ifndef TEST_NILS #define TEST_NILS 0 #elif TEST_NILS #undef TEST_NILS #define TEST_NILS 1 #endif /* !defined(TEST_NILS) */ #ifdef TEST #undef TEST #endif /* defined(TEST) */ #define TEST(fmt, val) \ do { \ for (i = 0; fmt[i] != NULL; i++) \ for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \ r1 = sprintf(buf1, fmt[i], val[j]); \ r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \ if (strcmp(buf1, buf2) != 0 || r1 != r2) { \ (void)printf("Results don't match, " \ "format string: %s\n" \ "\t sprintf(3): [%s] (%d)\n" \ "\tsnprintf(3): [%s] (%d)\n", \ fmt[i], buf1, r1, buf2, r2); \ failed++; \ } \ num++; \ } \ } while (/* CONSTCOND */ 0) #if HAVE_LOCALE_H (void)setlocale(LC_ALL, ""); #endif /* HAVE_LOCALE_H */ (void)puts("=== Testing our snprintf(3) against your system's sprintf(3). ===\n"); TEST(float_fmt, float_val); TEST(long_fmt, long_val); TEST(ulong_fmt, ulong_val); TEST(llong_fmt, llong_val); TEST(string_fmt, string_val); #if !OS_SYSV /* SysV uses a different format than we do. */ TEST(pointer_fmt, pointer_val); #endif /* !OS_SYSV */ (void)printf("Result: %d out of %d tests failed.\n", failed, num); (void)fputs("Checking how many digits we support: ", stdout); for (i = 0; i < 100; i++) { value = pow(10, i) * digits; (void)sprintf(buf1, "%.1f", value); (void)snprintf(buf2, sizeof(buf2), "%.1f", value); if (strcmp(buf1, buf2) != 0) { (void)printf("apparently %d.\n", i); break; } } return (failed == 0) ? 0 : 1; } #endif /* TEST_SNPRINTF */ /* vim: set joinspaces textwidth=80: */ cfengine-3.6.2/libcompat/setlinebuf.c0000664000175100017510000000226612243421446017304 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_SETLINEBUF void setlinebuf(FILE *stream); #endif void setlinebuf(FILE *stream) { setvbuf(stream, (char *) NULL, _IOLBF, 0); } cfengine-3.6.2/libcompat/unsetenv.c0000664000175100017510000000465112243421446017013 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #if !HAVE_DECL_UNSETENV int unsetenv(const char *name); #endif /* Under MinGW putenv('var=') will remove variable from environment */ #ifdef __MINGW32__ int unsetenv(const char *name) { int retval; char *buf; if (name == NULL || *name == 0 || strchr(name, '=') != 0) { errno = EINVAL; return -1; } buf = malloc(strlen(name) + 2); if (!buf) { errno = ENOMEM; return -1; } sprintf(buf, "%s=", name); retval = putenv(buf); free(buf); return retval; } #endif /* * Under SVR4 (Solaris 8/9, HP-UX 11.11) we need to manually update 'environ' * variable */ #if defined(__sun) || defined (__hpux) /* * Note: this function will leak memory as we don't know how to free data * previously used by environment variables. */ extern char **environ; int unsetenv(const char *name) { char **c; int len; if (name == NULL || *name == 0 || strchr(name, '=') != 0) { errno = EINVAL; return -1; } len = strlen(name); /* Find variable */ for (c = environ; *c; ++c) { if (strncmp(name, *c, len) == 0 && ((*c)[len] == '=' || (*c)[len] == 0)) { break; } } /* Shift remaining values */ for (; *c; ++c) { *c = *(c + 1); } return 0; } #endif cfengine-3.6.2/libcompat/Makefile.in0000664000175100017510000005741412412324464017052 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = libcompat DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am strcasestr.c \ gmtime_r.c nanosleep.c pthread_sigmask.c memrchr.c unsetenv.c \ strsep.c memdup.c strstr.c strrstr.c openat.c log2.c \ strcasecmp.c fstatat.c strncasecmp.c mkdtemp.c strerror.c \ rpl_ctime.c memmem.c fchownat.c drand48.c strlcat.c \ setlinebuf.c clock_gettime.c inet_ntop.c strndup.c snprintf.c \ strsignal.c getaddrinfo.c strnlen.c \ pthread_attr_setstacksize.c inet_pton.c round.c srand48.c \ strlcpy.c dirfd.c localtime_r.c getloadavg.c getline.c \ strdup.c $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcompat_la_DEPENDENCIES = $(LTLIBOBJS) am_libcompat_la_OBJECTS = generic_at.lo getopt.lo getopt1.lo libcompat_la_OBJECTS = $(am_libcompat_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcompat_la_SOURCES) DIST_SOURCES = $(libcompat_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcompat.la AM_CPPFLAGS = -I$(top_srcdir)/libutils # platform.h libcompat_la_LIBADD = $(LTLIBOBJS) libcompat_la_SOURCES = \ generic_at.c generic_at.h \ getopt.c \ getopt1.c EXTRA_DIST = \ getopt.h CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ 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) --foreign libcompat/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libcompat/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcompat.la: $(libcompat_la_OBJECTS) $(libcompat_la_DEPENDENCIES) $(EXTRA_libcompat_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcompat_la_OBJECTS) $(libcompat_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/clock_gettime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/dirfd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/drand48.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fchownat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/fstatat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getaddrinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/getloadavg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/gmtime_r.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/inet_ntop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/inet_pton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/localtime_r.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/log2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memdup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memmem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/memrchr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mkdtemp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/nanosleep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/openat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pthread_attr_setstacksize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pthread_sigmask.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/round.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/rpl_ctime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/setlinebuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/snprintf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/srand48.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strcasecmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strcasestr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strdup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strerror.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strlcat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strlcpy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strncasecmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strndup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strnlen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strrstr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strsep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strsignal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/strstr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/unsetenv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic_at.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf $(DEPDIR) ./$(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) ./$(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 TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am 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 tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/libcompat/strrstr.c0000664000175100017510000000375612236160673016700 0ustar00a10038a1003800000000000000/* Part of publib. Copyright (c) 1994-2006 Lars Wirzenius. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * strrstr.c -- find last occurence of string in another string * * Part of publib. See man page for more information. * "@(#)publib-strutil:$Id: strrstr.c,v 1.1.1.1 1994/02/03 17:25:29 liw Exp $" */ #include #include #if !HAVE_DECL_STRRSTR char *strrstr(const char *haystack, const char *needle); #endif char *strrstr(const char *str, const char *pat) { size_t len, patlen; const char *p; assert(str != NULL); assert(pat != NULL); len = strlen(str); patlen = strlen(pat); if (patlen > len) return NULL; for (p = str + (len - patlen); p > str; --p) if (*p == *pat && strncmp(p, pat, patlen) == 0) return (char *) p; return NULL; } cfengine-3.6.2/libcompat/Makefile.am0000664000175100017510000000046412411001073017015 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcompat.la AM_CPPFLAGS = -I$(top_srcdir)/libutils # platform.h libcompat_la_LIBADD = $(LTLIBOBJS) libcompat_la_SOURCES = \ generic_at.c generic_at.h \ getopt.c \ getopt1.c EXTRA_DIST = \ getopt.h CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ cfengine-3.6.2/libcompat/dirfd.c0000664000175100017510000000267412243421446016237 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #ifdef HAVE_DIRENT_H # include #endif #if !HAVE_DECL_DIRFD int dirfd(DIR *dirp); #endif /* Under Solaris, HP-UX and AIX dirfd(3) is just looking inside DIR structure */ #if defined(__sun) int dirfd(DIR *dirp) { return dirp->d_fd != -1 ? dirp->d_fd : ENOTSUP; } #elif defined(__hpux) || defined(_AIX) int dirfd(DIR *dirp) { return dirp->dd_fd != -1 ? dirp->dd_fd : ENOTSUP; } #endif cfengine-3.6.2/libcompat/drand48.c0000664000175100017510000000221712243421446016404 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_DRAND48 double drand48(void); #endif double drand48(void) { return (double) rand(); } cfengine-3.6.2/libcompat/gmtime_r.c0000664000175100017510000000274112243421446016745 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_GMTIME_R struct tm *gmtime_r(const time_t *timep, struct tm *result); #endif #if defined(__MINGW32__) /* On Windows, gmtime buffer is thread-specific, so using it in place of the reentrant version is safe */ struct tm *gmtime_r(const time_t *timep, struct tm *result) { struct tm *ret = gmtime(timep); if (ret) { memcpy(result, ret, sizeof(struct tm)); } return ret; } #endif cfengine-3.6.2/libcompat/inet_ntop.c0000664000175100017510000001164012243421446017137 0ustar00a10038a1003800000000000000/* * Copyright (C) 1996-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #if defined(_WIN32) && !defined(EAFNOSUPPORT) #define EAFNOSUPPORT WSAEAFNOSUPPORT #endif #define NS_INT16SZ 2 #define NS_IN6ADDRSZ 16 /* * WARNING: Don't even consider trying to compile this on a system where * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size); #ifdef AF_INET6 static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size); #endif /* char * * isc_net_ntop(af, src, dst, size) * convert a network format address to presentation format. * return: * pointer to presentation format address (`dst'), or NULL (see errno). * author: * Paul Vixie, 1996. */ const char * inet_ntop(int af, const void *src, char *dst, socklen_t size) { switch (af) { case AF_INET: return (inet_ntop4(src, dst, size)); #ifdef AF_INET6 case AF_INET6: return (inet_ntop6(src, dst, size)); #endif default: errno = EAFNOSUPPORT; return (NULL); } /* NOTREACHED */ } /* const char * * inet_ntop4(src, dst, size) * format an IPv4 address * return: * `dst' (as a const) * notes: * (1) uses no statics * (2) takes a unsigned char* not an in_addr as input * author: * Paul Vixie, 1996. */ static const char * inet_ntop4(const unsigned char *src, char *dst, size_t size) { static const char *fmt = "%u.%u.%u.%u"; char tmp[sizeof "255.255.255.255"]; size_t len; len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]); if (len >= size) { errno = ENOSPC; return (NULL); } memcpy(dst, tmp, len + 1); return (dst); } /* const char * * isc_inet_ntop6(src, dst, size) * convert IPv6 binary address into presentation (printable) format * author: * Paul Vixie, 1996. */ #ifdef AF_INET6 static const char * inet_ntop6(const unsigned char *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; struct { int base, len; } best, cur; unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ]; int i, inc; /* * Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ memset(words, '\0', sizeof words); for (i = 0; i < NS_IN6ADDRSZ; i++) words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); best.base = -1; cur.base = -1; for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else { if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } } if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; } if (best.base != -1 && best.len < 2) best.base = -1; /* * Format the result. */ tp = tmp; for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) *tp++ = ':'; continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) return (NULL); tp += strlen(tp); break; } inc = snprintf(tp, 5, "%x", words[i]); assert(inc < 5); tp += inc; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) *tp++ = ':'; *tp++ = '\0'; /* * Check for overflow, copy, and we're done. */ if ((size_t)(tp - tmp) > size) { errno = ENOSPC; return (NULL); } memcpy(dst, tmp, tp - tmp); return (dst); } #endif /* AF_INET6 */ cfengine-3.6.2/libcompat/memdup.c0000664000175100017510000000245612243421446016434 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_MEMDUP void *memdup(const void *data, size_t size); #endif void *memdup(const void *data, size_t size) { void *m = malloc(size); if (m == NULL) { return NULL; } memcpy(m, data, size); return m; } cfengine-3.6.2/libcompat/getopt.h0000664000175100017510000001106012236160673016447 0ustar00a10038a1003800000000000000/* Declarations for getopt. Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #define __GETOPT_H__ 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ cfengine-3.6.2/libcompat/strndup.c0000664000175100017510000000254012236160673016642 0ustar00a10038a1003800000000000000/* $OpenBSD: strndup.c,v 1.1 2010/05/18 22:24:55 tedu Exp $ */ /* * Copyright (c) 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #if !HAVE_DECL_STRNLEN size_t strnlen(const char *str, size_t maxlen); #endif #if !HAVE_DECL_STRNDUP char *strndup(const char *str, size_t n); #endif char * strndup(const char *str, size_t maxlen) { char *copy; size_t len; len = strnlen(str, maxlen); copy = malloc(len + 1); if (copy != NULL) { (void)memcpy(copy, str, len); copy[len] = '\0'; } return copy; } cfengine-3.6.2/libcompat/srand48.c0000664000175100017510000000222512243421446016422 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #if !HAVE_DECL_SRAND48 void srand48(long seed); #endif void srand48(long seed) { srand((unsigned) seed); } cfengine-3.6.2/libcompat/strdup.c0000644000175100017510000000247312316547775016502 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_STRDUP char *strdup(const char *str); #endif char *strdup(const char *str) { const long len = strlen(str) + 1; char *sp = malloc( len ); if (sp == NULL) { return NULL; } memcpy(sp, str, len); return sp; } cfengine-3.6.2/libcompat/strncasecmp.c0000664000175100017510000000315012243421446017457 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #if !HAVE_DECL_STRCASECMP int strncasecmp(const char *s1, const char *s2); #endif int strncasecmp(const char *s1, const char *s2, size_t n) { while (n-- > 0) { if (*s1 == '\0' && *s2 == '\0') { break; } if (*s1 == '\0') { return -1; } if (*s2 == '\0') { return 1; } if (tolower(*s1) < tolower(*s2)) { return -1; } if (tolower(*s1) > tolower(*s2)) { return 1; } s1++; s2++; } return 0; } cfengine-3.6.2/libcompat/strcasestr.c0000664000175100017510000000266412243421446017343 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_STRCASESTR char *strcasestr(const char *haystack, const char *needle); #endif char *strcasestr(const char *haystack, const char *needle) { size_t needlelen = strlen(needle); for (const char *sp = haystack; *sp; sp++) { if (strncasecmp(sp, needle, needlelen) == 0) { return (char *) sp; } } return NULL; } cfengine-3.6.2/libcompat/strsep.c0000664000175100017510000000502412236160673016463 0ustar00a10038a1003800000000000000/*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #if !HAVE_DECL_STRSEP char *strsep(char **stringp, const char *delim); #endif /* * Get next token from string *stringp, where tokens are possibly-empty * strings separated by characters from delim. * * Writes NULs into the string at *stringp to end tokens. * delim need not remain constant from call to call. * On return, *stringp points past the last NUL written (if there might * be further tokens), or is NULL (if there are definitely no more tokens). * * If *stringp is NULL, strsep returns NULL. */ char * strsep(char **stringp, const char *delim) { char *s; const char *spanp; int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); for (tok = s;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } cfengine-3.6.2/libcompat/clock_gettime.c0000664000175100017510000000225012243421446017746 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include int clock_gettime(ARG_UNUSED clockid_t clock_id, struct timespec *tp) { tp->tv_sec = time(NULL); tp->tv_nsec = 0; return 0; } cfengine-3.6.2/libcompat/fstatat.c0000644000175100017510000000347212316547775016627 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #ifndef __MINGW32__ typedef struct { const char *pathname; struct stat *buf; int flags; } fstatat_data; static int fstatat_inner(void *generic_data) { fstatat_data *data = generic_data; if (data->flags & AT_SYMLINK_NOFOLLOW) { return lstat(data->pathname, data->buf); } else { return stat(data->pathname, data->buf); } } static void cleanup(ARG_UNUSED void *generic_data) { } int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags) { fstatat_data data; data.pathname = pathname; data.buf = buf; data.flags = flags; return generic_at_function(dirfd, &fstatat_inner, &cleanup, &data); } #endif // !__MINGW32__ cfengine-3.6.2/libcompat/getline.c0000644000175100017510000000727612316547775016616 0ustar00a10038a1003800000000000000/* Implementations of the getdelim() and getline() functions from POSIX 2008, just in case your libc doesn't have them. getdelim() reads from a stream until a specified delimiter is encountered. getline() reads from a stream until a newline is encountered. See: http://pubs.opengroup.org/onlinepubs/9699919799/functions/getdelim.html NOTE: It is always the caller's responsibility to free the line buffer, even when an error occurs. Copyright (c) 2011 James E. Ingram Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #if !HAVE_DECL_GETLINE ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif #ifndef SSIZE_MAX #define SSIZE_MAX 32767 #endif #define _GETDELIM_GROWBY 4096 /* amount to grow line buffer by */ #define _GETDELIM_MINLEN 4 /* minimum line buffer size */ static ssize_t getdelim(char **restrict lineptr, size_t *restrict n, int delimiter, FILE *restrict stream) { char *buf, *pos; int c; ssize_t bytes; if (lineptr == NULL || n == NULL) { errno = EINVAL; return -1; } if (stream == NULL) { errno = EBADF; return -1; } /* resize (or allocate) the line buffer if necessary */ buf = *lineptr; if (buf == NULL || *n < _GETDELIM_MINLEN) { buf = realloc(*lineptr, _GETDELIM_GROWBY); if (buf == NULL) { /* ENOMEM */ return -1; } *n = _GETDELIM_GROWBY; *lineptr = buf; } /* read characters until delimiter is found, end of file is reached, or an error occurs. */ bytes = 0; pos = buf; while ((c = getc(stream)) != EOF) { if (bytes + 1 >= SSIZE_MAX) { errno = ERANGE; return -1; } bytes++; if (bytes >= *n - 1) { buf = realloc(*lineptr, *n + _GETDELIM_GROWBY); if (buf == NULL) { /* ENOMEM */ return -1; } *n += _GETDELIM_GROWBY; pos = buf + bytes - 1; *lineptr = buf; } *pos++ = (char) c; if (c == delimiter) { break; } } if (ferror(stream) || (feof(stream) && (bytes == 0))) { /* EOF, or an error from getc(). */ return -1; } *pos = '\0'; return bytes; } ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream) { return getdelim(lineptr, n, '\n', stream); } cfengine-3.6.2/cf-monitord/0000775000175100017510000000000012413020723015231 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-monitord/verify_measurements.c0000664000175100017510000000714312411001073021471 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include static bool CheckMeasureSanity(Measurement m, const Promise *pp); /*****************************************************************************/ PromiseResult VerifyMeasurementPromise(EvalContext *ctx, double *measurement, const Promise *pp) { PromiseBanner(pp); Attributes a = GetMeasurementAttributes(ctx, pp); if (!CheckMeasureSanity(a.measure, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Measurement promise is not valid"); return PROMISE_RESULT_INTERRUPTED; } return VerifyMeasurement(ctx, measurement, a, pp); } /*****************************************************************************/ static bool CheckMeasureSanity(Measurement m, const Promise *pp) { int retval = true; if (!IsAbsPath(pp->promiser)) { Log(LOG_LEVEL_ERR, "The promiser '%s' of a measurement was not an absolute path", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); retval = false; } if (m.data_type == CF_DATA_TYPE_NONE) { Log(LOG_LEVEL_ERR, "The promiser '%s' did not specify a data type", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); retval = false; } else { if ((m.history_type) && (strcmp(m.history_type, "weekly") == 0)) { switch (m.data_type) { case CF_DATA_TYPE_COUNTER: case CF_DATA_TYPE_STRING: case CF_DATA_TYPE_INT: case CF_DATA_TYPE_REAL: break; default: Log(LOG_LEVEL_ERR, "The promiser '%s' cannot have history type weekly as it is not a number", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); retval = false; break; } } } if ((m.select_line_matching) && (m.select_line_number != CF_NOINT)) { Log(LOG_LEVEL_ERR, "The promiser '%s' cannot select both a line by pattern and by number", pp->promiser); PromiseRef(LOG_LEVEL_ERR, pp); retval = false; } if (!m.extraction_regex) { Log(LOG_LEVEL_VERBOSE, "No extraction regex, so assuming whole line is the value"); } else { if ((!strchr(m.extraction_regex, '(')) && (!strchr(m.extraction_regex, ')'))) { Log(LOG_LEVEL_ERR, "The extraction_regex must contain a single backreference for the extraction"); retval = false; } } return retval; } cfengine-3.6.2/cf-monitord/mon_load.c0000644000175100017510000000323112316547775017211 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #ifdef HAVE_SYS_LOADAVG_H # include #else # define LOADAVG_5MIN 1 #endif /* Implementation */ #ifdef HAVE_GETLOADAVG void MonLoadGatherData(double *cf_this) { double load[LOADAVG_5MIN], sum = 0.0; int i, n; if ((n = getloadavg(load, LOADAVG_5MIN)) == -1) { cf_this[ob_loadavg] = 0.0; } for (i = 0; i < n; ++i) { sum += load[i]; } sum /= (double) n; cf_this[ob_loadavg] = sum; Log(LOG_LEVEL_VERBOSE, "Load Average = %.2lf", cf_this[ob_loadavg]); } #else void MonLoadGatherData(double *cf_this) { Log(LOG_LEVEL_DEBUG, "Average load data is not available."); } #endif cfengine-3.6.2/cf-monitord/mon_entropy.c0000644000175100017510000000640312316547775017776 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* Globals */ static Item *ENTROPIES = NULL; /* Implementation */ void MonEntropyClassesInit(void) { } /****************************************************************************/ void MonEntropyClassesReset(void) { ENTROPIES = NULL; /*? */ } /****************************************************************************/ /* * This function calculates entropy of items distribution. * * Let's define: * N = length of items list * q_i = items[i]->counter * p_i = q_i / sum_{i=1..N}(q_i) * -- normalized values, or probability of i-th class amongst all * * Entropy is * --- * - > q_i * ln(q_i) * --- i=0..N * E = ------------------------- * ln(N) * * Divisor is a uncertainity per digit, to normalize it to [0..1] we divide it * by ln(N). */ double MonEntropyCalculate(const Item *items) { double S = 0.0; double sum = 0.0; int numclasses = 0; const Item *i; for (i = items; i; i = i->next) { sum += i->counter; numclasses++; } if (numclasses < 2) { return 0.0; } for (i = items; i; i = i->next) { double q = ((double) i->counter) / sum; S -= q * log(q); } return S / log(numclasses); } /****************************************************************************/ void MonEntropyClassesSet(const char *service, const char *direction, double entropy) { char class[CF_MAXVARSIZE]; const char *class_type = "medium"; if (entropy > 0.9) { class_type = "high"; } if (entropy < 0.2) { class_type = "low"; } snprintf(class, CF_MAXVARSIZE, "entropy_%s_%s_%s", service, direction, class_type); AppendItem(&ENTROPIES, class, ""); } /****************************************************************************/ void MonEntropyPurgeUnused(char *name) { // Don't set setentropy is there is no corresponding class DeleteItemMatching(&ENTROPIES, name); } /****************************************************************************/ void MonEntropyClassesPublish(FILE *fp) { for (Item *ip = ENTROPIES; ip != NULL; ip = ip->next) { fprintf(fp, "%s\n", ip->name); } DeleteItemList(ENTROPIES); } cfengine-3.6.2/cf-monitord/mon_processes.c0000664000175100017510000000711712411001073020255 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include /* Prototypes */ #ifndef __MINGW32__ static bool GatherProcessUsers(Item **userList, int *userListSz, int *numRootProcs, int *numOtherProcs); #endif /* Implementation */ void MonProcessesGatherData(double *cf_this) { Item *userList = NULL; char vbuff[CF_BUFSIZE]; int numProcUsers = 0; int numRootProcs = 0; int numOtherProcs = 0; if (!GatherProcessUsers(&userList, &numProcUsers, &numRootProcs, &numOtherProcs)) { return; } cf_this[ob_users] += numProcUsers; cf_this[ob_rootprocs] += numRootProcs; cf_this[ob_otherprocs] += numOtherProcs; snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_users", CFWORKDIR); MapName(vbuff); RawSaveItemList(userList, vbuff, NewLineMode_Unix); DeleteItemList(userList); Log(LOG_LEVEL_VERBOSE, "(Users,root,other) = (%d,%d,%d)", (int) cf_this[ob_users], (int) cf_this[ob_rootprocs], (int) cf_this[ob_otherprocs]); } #ifndef __MINGW32__ static bool GatherProcessUsers(Item **userList, int *userListSz, int *numRootProcs, int *numOtherProcs) { FILE *pp; char pscomm[CF_BUFSIZE]; char user[CF_MAXVARSIZE]; snprintf(pscomm, CF_BUFSIZE, "%s %s", VPSCOMM[VSYSTEMHARDCLASS], VPSOPTS[VSYSTEMHARDCLASS]); if ((pp = cf_popen(pscomm, "r", true)) == NULL) { /* FIXME: no logging */ return false; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); /* Ignore first line -- header */ ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res <= 0) { /* FIXME: no logging */ cf_pclose(pp); free(vbuff); return false; } for (;;) { ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { /* FIXME: no logging */ cf_pclose(pp); free(vbuff); return false; } else { break; } } sscanf(vbuff, "%s", user); if (strcmp(user, "USER") == 0) { continue; } if (!IsItemIn(*userList, user)) { PrependItem(userList, user, NULL); (*userListSz)++; } if (strcmp(user, "root") == 0) { (*numRootProcs)++; } else { (*numOtherProcs)++; } } cf_pclose(pp); free(vbuff); return true; } #endif cfengine-3.6.2/cf-monitord/mon.h0000644000175100017510000000376712316547775016235 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MON_H #define CFENGINE_MON_H /* mon_entropy.c */ void MonEntropyClassesInit(void); void MonEntropyClassesReset(void); void MonEntropyClassesSet(const char *service, const char *direction, double entropy); void MonEntropyClassesPublish(FILE *fp); void MonEntropyPurgeUnused(char *name); double MonEntropyCalculate(const Item *items); /* mon_cpu.c */ void MonCPUGatherData(double *cf_this); /* mon_disk.c */ void MonDiskGatherData(double *cf_this); /* mon_load.c */ void MonLoadGatherData(double *cf_this); /* mon_network.c */ void MonNetworkInit(void); void MonNetworkGatherData(double *cf_this); /* mon_network_sniffer.c */ void MonNetworkSnifferInit(void); void MonNetworkSnifferOpen(void); void MonNetworkSnifferEnable(bool enable); void MonNetworkSnifferSniff(Item *ip_addresses, long iteration, double *cf_this); void MonNetworkSnifferGatherData(void); /* mon_processes.c */ void MonProcessesGatherData(double *cf_this); /* mon_temp.c */ void MonTempInit(void); void MonTempGatherData(double *cf_this); #endif cfengine-3.6.2/cf-monitord/mon_network.c0000664000175100017510000003152312411001073017736 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include /* Globals */ Item *ALL_INCOMING = NULL; Item *MON_UDP4 = NULL, *MON_UDP6 = NULL, *MON_TCP4 = NULL, *MON_TCP6 = NULL; /*******************************************************************/ /* Anomaly */ /*******************************************************************/ typedef struct { char *portnr; char *name; enum observables in; enum observables out; } Sock; static const Sock ECGSOCKS[ATTR] = /* extended to map old to new using enum */ { {"137", "netbiosns", ob_netbiosns_in, ob_netbiosns_out}, {"138", "netbiosdgm", ob_netbiosdgm_in, ob_netbiosdgm_out}, {"139", "netbiosssn", ob_netbiosssn_in, ob_netbiosssn_out}, {"445", "microsoft_ds", ob_microsoft_ds_in, ob_microsoft_ds_out}, {"5308", "cfengine", ob_cfengine_in, ob_cfengine_out}, {"2049", "nfsd", ob_nfsd_in, ob_nfsd_out}, {"25", "smtp", ob_smtp_in, ob_smtp_out}, {"80", "www", ob_www_in, ob_www_out}, {"8080", "www-alt", ob_www_alt_in, ob_www_alt_out}, {"21", "ftp", ob_ftp_in, ob_ftp_out}, {"22", "ssh", ob_ssh_in, ob_ssh_out}, {"443", "wwws", ob_wwws_in, ob_wwws_out}, {"143", "imap", ob_imap_in, ob_imap_out}, {"993", "imaps", ob_imaps_in, ob_imaps_out}, {"389", "ldap", ob_ldap_in, ob_ldap_out}, {"636", "ldaps", ob_ldaps_in, ob_ldaps_out}, {"27017", "mongo", ob_mongo_in, ob_mongo_out}, {"3306", "mysql", ob_mysql_in, ob_mysql_out}, {"5432", "postgresql", ob_postgresql_in, ob_postgresql_out}, {"631", "ipp", ob_ipp_in, ob_ipp_out}, }; static const char *const VNETSTAT[] = { [PLATFORM_CONTEXT_UNKNOWN] = "-", [PLATFORM_CONTEXT_OPENVZ] = "/bin/netstat -rn", /* virt_host_vz_vzps */ [PLATFORM_CONTEXT_HP] = "/usr/bin/netstat -rn", /* hpux */ [PLATFORM_CONTEXT_AIX] = "/usr/bin/netstat -rn", /* aix */ [PLATFORM_CONTEXT_LINUX] = "/bin/netstat -rn", /* linux */ [PLATFORM_CONTEXT_SOLARIS] = "/usr/bin/netstat -rn", /* solaris */ [PLATFORM_CONTEXT_SUN_SOLARIS] = "/usr/bin/netstat -rn", /* solaris */ [PLATFORM_CONTEXT_FREEBSD] = "/usr/bin/netstat -rn", /* freebsd */ [PLATFORM_CONTEXT_NETBSD] = "/usr/bin/netstat -rn", /* netbsd */ [PLATFORM_CONTEXT_CRAYOS] = "/usr/ucb/netstat -rn", /* cray */ [PLATFORM_CONTEXT_WINDOWS_NT] = "/cygdrive/c/WINNT/System32/netstat", /* CygWin */ [PLATFORM_CONTEXT_SYSTEMV] = "/usr/bin/netstat -rn", /* Unixware */ [PLATFORM_CONTEXT_OPENBSD] = "/usr/bin/netstat -rn", /* openbsd */ [PLATFORM_CONTEXT_CFSCO] = "/usr/bin/netstat -rn", /* sco */ [PLATFORM_CONTEXT_DARWIN] = "/usr/sbin/netstat -rn", /* darwin */ [PLATFORM_CONTEXT_QNX] = "/usr/bin/netstat -rn", /* qnx */ [PLATFORM_CONTEXT_DRAGONFLY] = "/usr/bin/netstat -rn", /* dragonfly */ [PLATFORM_CONTEXT_MINGW] = "mingw-invalid", /* mingw */ [PLATFORM_CONTEXT_VMWARE] = "/usr/bin/netstat", /* vmware */ [PLATFORM_CONTEXT_ANDROID] = "/system/xbin/netstat -rn", /* android */ }; /* Implementation */ void MonNetworkInit(void) { DeleteItemList(MON_TCP4); DeleteItemList(MON_TCP6); DeleteItemList(MON_UDP4); DeleteItemList(MON_UDP6); MON_UDP4 = MON_UDP6 = MON_TCP4 = MON_TCP6 = NULL; for (int i = 0; i < ATTR; i++) { char vbuff[CF_BUFSIZE]; snprintf(vbuff, sizeof(vbuff), "%s/state/cf_incoming.%s", CFWORKDIR, ECGSOCKS[i].name); MapName(vbuff); CreateEmptyFile(vbuff); snprintf(vbuff, sizeof(vbuff), "%s/state/cf_outgoing.%s", CFWORKDIR, ECGSOCKS[i].name); MapName(vbuff); CreateEmptyFile(vbuff); } } /******************************************************************************/ static void SetNetworkEntropyClasses(const char *service, const char *direction, const Item *list) { const Item *ip; Item *addresses = NULL; double entropy; for (ip = list; ip != NULL; ip = ip->next) { if (strlen(ip->name) > 0) { char local[CF_BUFSIZE]; char remote[CF_BUFSIZE]; char vbuff[CF_BUFSIZE]; char *sp; if (strncmp(ip->name, "tcp", 3) == 0) { sscanf(ip->name, "%*s %*s %*s %s %s", local, remote); /* linux-like */ } else { sscanf(ip->name, "%s %s", local, remote); /* solaris-like */ } strncpy(vbuff, remote, CF_BUFSIZE - 1); vbuff[CF_BUFSIZE-1] = '\0'; for (sp = vbuff + strlen(vbuff) - 1; isdigit((int) *sp) && (sp > vbuff); sp--) { } *sp = '\0'; if (!IsItemIn(addresses, vbuff)) { AppendItem(&addresses, vbuff, ""); } IncrementItemListCounter(addresses, vbuff); } } entropy = MonEntropyCalculate(addresses); MonEntropyClassesSet(service, direction, entropy); DeleteItemList(addresses); } /******************************************************************************/ void MonNetworkGatherData(double *cf_this) { FILE *pp; char local[CF_BUFSIZE], remote[CF_BUFSIZE], comm[CF_BUFSIZE]; Item *in[ATTR], *out[ATTR]; char *sp; int i; enum cf_netstat_type { cfn_new, cfn_old } type = cfn_new; enum cf_packet_type { cfn_udp4, cfn_udp6, cfn_tcp4, cfn_tcp6} packet = cfn_tcp4; for (i = 0; i < ATTR; i++) { in[i] = out[i] = NULL; } DeleteItemList(ALL_INCOMING); ALL_INCOMING = NULL; sscanf(VNETSTAT[VSYSTEMHARDCLASS], "%s", comm); strcat(comm, " -an"); if ((pp = cf_popen(comm, "r", true)) == NULL) { /* FIXME: no logging */ return; } size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); for (;;) { memset(local, 0, CF_BUFSIZE); memset(remote, 0, CF_BUFSIZE); size_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { /* FIXME: no logging */ cf_pclose(pp); free(vbuff); return; } else { break; } } if (strstr(vbuff, "UNIX")) { break; } if (!((strstr(vbuff, ":")) || (strstr(vbuff, ".")))) { continue; } /* Different formats here ... ugh.. pick a model */ // If this is old style, we look for chapter headings, e.g. "TCP: IPv4" if ((strncmp(vbuff,"UDP:",4) == 0) && (strstr(vbuff+4,"6"))) { packet = cfn_udp6; type = cfn_old; continue; } else if ((strncmp(vbuff,"TCP:",4) == 0) && (strstr(vbuff+4,"6"))) { packet = cfn_tcp6; type = cfn_old; continue; } else if ((strncmp(vbuff,"UDP:",4) == 0) && (strstr(vbuff+4,"4"))) { packet = cfn_udp4; type = cfn_old; continue; } else if ((strncmp(vbuff,"TCP:",4) == 0) && (strstr(vbuff+4,"4"))) { packet = cfn_tcp4; type = cfn_old; continue; } // Line by line state in modern/linux output if (strncmp(vbuff,"udp6",4) == 0) { packet = cfn_udp6; type = cfn_new; } else if (strncmp(vbuff,"tcp6",4) == 0) { packet = cfn_tcp6; type = cfn_new; } else if (strncmp(vbuff,"udp",3) == 0) { packet = cfn_udp4; type = cfn_new; } else if (strncmp(vbuff,"tcp",3) == 0) { packet = cfn_tcp4; type = cfn_new; } // End extract type switch (type) { case cfn_new: sscanf(vbuff, "%*s %*s %*s %s %s", local, remote); /* linux-like */ break; case cfn_old: sscanf(vbuff, "%s %s", local, remote); break; } if (strlen(local) == 0) { continue; } // Extract the port number from the end of the string for (sp = local + strlen(local); (*sp != '.') && (*sp != ':') && (sp > local); sp--) { } *sp = '\0'; // Separate address from port number sp++; char *localport = sp; if (strstr(vbuff, "LISTEN")) { // General bucket IdempPrependItem(&ALL_INCOMING, sp, NULL); // Categories the incoming ports by packet types switch (packet) { case cfn_udp4: IdempPrependItem(&MON_UDP4, sp, local); break; case cfn_udp6: IdempPrependItem(&MON_UDP6, sp, local); break; case cfn_tcp4: IdempPrependItem(&MON_TCP4, localport, local); break; case cfn_tcp6: IdempPrependItem(&MON_TCP6, localport, local); break; default: break; } } // Now look at outgoing for (sp = remote + strlen(remote) - 1; (sp >= remote) && (isdigit((int) *sp)); sp--) { } sp++; char *remoteport = sp; // Now look for the specific vital signs to count frequencies for (i = 0; i < ATTR; i++) { if (strcmp(localport, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].in]++; AppendItem(&in[i], vbuff, ""); } if (strcmp(remoteport, ECGSOCKS[i].portnr) == 0) { cf_this[ECGSOCKS[i].out]++; AppendItem(&out[i], vbuff, ""); } } } cf_pclose(pp); /* Now save the state for ShowState() the state is not smaller than the last or at least 40 minutes older. This mirrors the persistence of the maxima classes */ for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save incoming '%s'", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_incoming.%s", CFWORKDIR, ECGSOCKS[i].name); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(in[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", ECGSOCKS[i].name); DeleteItemList(in[i]); continue; } } SetNetworkEntropyClasses(CanonifyName(ECGSOCKS[i].name), "in", in[i]); RawSaveItemList(in[i], vbuff, NewLineMode_Unix); DeleteItemList(in[i]); Log(LOG_LEVEL_DEBUG, "Saved in netstat data in '%s'", vbuff); } for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save outgoing '%s'", ECGSOCKS[i].name); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_outgoing.%s", CFWORKDIR, ECGSOCKS[i].name); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(out[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", ECGSOCKS[i].name); DeleteItemList(out[i]); continue; } } SetNetworkEntropyClasses(CanonifyName(ECGSOCKS[i].name), "out", out[i]); RawSaveItemList(out[i], vbuff, NewLineMode_Unix); Log(LOG_LEVEL_DEBUG, "Saved out netstat data in '%s'", vbuff); DeleteItemList(out[i]); } free(vbuff); } cfengine-3.6.2/cf-monitord/Makefile.in0000664000175100017510000006613412412324463017317 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-monitord$(EXEEXT) subdir = cf-monitord DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcf_monitord_la_DEPENDENCIES = ../libpromises/libpromises.la am_libcf_monitord_la_OBJECTS = verify_measurements.lo \ cf-monitord-enterprise-stubs.lo env_monitor.lo mon_cpu.lo \ mon_disk.lo mon_entropy.lo mon_load.lo mon_network_sniffer.lo \ mon_network.lo mon_processes.lo mon_temp.lo cf-monitord.lo libcf_monitord_la_OBJECTS = $(am_libcf_monitord_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) cf_monitord_SOURCES = cf-monitord.c cf_monitord_OBJECTS = cf_monitord-cf-monitord.$(OBJEXT) @BUILTIN_EXTENSIONS_FALSE@cf_monitord_DEPENDENCIES = \ @BUILTIN_EXTENSIONS_FALSE@ libcf-monitord.la cf_monitord_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(cf_monitord_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_monitord_la_SOURCES) cf-monitord.c DIST_SOURCES = $(libcf_monitord_la_SOURCES) cf-monitord.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-monitord.la AM_CPPFLAGS = \ $(OPENSSL_CPPFLAGS) \ -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv \ -I$(srcdir)/../libpromises \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = @CFLAGS@ \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_monitord_la_LIBADD = ../libpromises/libpromises.la libcf_monitord_la_SOURCES = \ verify_measurements.c verify_measurements.h \ cf-monitord-enterprise-stubs.c cf-monitord-enterprise-stubs.h \ env_monitor.c env_monitor.h \ mon.h \ mon_cpu.c \ mon_disk.c \ mon_entropy.c \ mon_load.c \ mon_network_sniffer.c \ mon_network.c \ mon_processes.c \ mon_temp.c \ cf-monitord.c @BUILTIN_EXTENSIONS_FALSE@cf_monitord_CFLAGS = $(AM_CFLAGS) @BUILTIN_EXTENSIONS_FALSE@cf_monitord_LDADD = libcf-monitord.la CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-monitord/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-monitord/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-monitord.la: $(libcf_monitord_la_OBJECTS) $(libcf_monitord_la_DEPENDENCIES) $(EXTRA_libcf_monitord_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_monitord_la_OBJECTS) $(libcf_monitord_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-monitord$(EXEEXT): $(cf_monitord_OBJECTS) $(cf_monitord_DEPENDENCIES) $(EXTRA_cf_monitord_DEPENDENCIES) @rm -f cf-monitord$(EXEEXT) $(AM_V_CCLD)$(cf_monitord_LINK) $(cf_monitord_OBJECTS) $(cf_monitord_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-monitord-enterprise-stubs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-monitord.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_monitord-cf-monitord.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env_monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_cpu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_disk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_entropy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_load.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_network.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_network_sniffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_processes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mon_temp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify_measurements.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< cf_monitord-cf-monitord.o: cf-monitord.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_monitord_CFLAGS) $(CFLAGS) -MT cf_monitord-cf-monitord.o -MD -MP -MF $(DEPDIR)/cf_monitord-cf-monitord.Tpo -c -o cf_monitord-cf-monitord.o `test -f 'cf-monitord.c' || echo '$(srcdir)/'`cf-monitord.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_monitord-cf-monitord.Tpo $(DEPDIR)/cf_monitord-cf-monitord.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-monitord.c' object='cf_monitord-cf-monitord.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_monitord_CFLAGS) $(CFLAGS) -c -o cf_monitord-cf-monitord.o `test -f 'cf-monitord.c' || echo '$(srcdir)/'`cf-monitord.c cf_monitord-cf-monitord.obj: cf-monitord.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_monitord_CFLAGS) $(CFLAGS) -MT cf_monitord-cf-monitord.obj -MD -MP -MF $(DEPDIR)/cf_monitord-cf-monitord.Tpo -c -o cf_monitord-cf-monitord.obj `if test -f 'cf-monitord.c'; then $(CYGPATH_W) 'cf-monitord.c'; else $(CYGPATH_W) '$(srcdir)/cf-monitord.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_monitord-cf-monitord.Tpo $(DEPDIR)/cf_monitord-cf-monitord.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-monitord.c' object='cf_monitord-cf-monitord.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_monitord_CFLAGS) $(CFLAGS) -c -o cf_monitord-cf-monitord.obj `if test -f 'cf-monitord.c'; then $(CYGPATH_W) 'cf-monitord.c'; else $(CYGPATH_W) '$(srcdir)/cf-monitord.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS @BUILTIN_EXTENSIONS_FALSE@ # Workaround for automake madness (try removing it if you want to know why). # 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: cfengine-3.6.2/cf-monitord/cf-monitord-enterprise-stubs.c0000644000175100017510000000320712316547775023161 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(void, MonOtherInit) { } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, MonOtherGatherData, ARG_UNUSED double *, cf_this) { } ENTERPRISE_VOID_FUNC_2ARG_DEFINE_STUB(void, HistoryUpdate, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED Averages, newvals) { } ENTERPRISE_FUNC_4ARG_DEFINE_STUB(PromiseResult, VerifyMeasurement, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED double *, this, ARG_UNUSED Attributes, a, ARG_UNUSED const Promise *, pp) { return PROMISE_RESULT_NOOP; } cfengine-3.6.2/cf-monitord/env_monitor.h0000664000175100017510000000226612243421446017757 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ENV_MONITOR_H #define CFENGINE_ENV_MONITOR_H #include extern double FORGETRATE; void MonitorInitialize(void); void MonitorStartServer(EvalContext *ctx, const Policy *policy); #endif cfengine-3.6.2/cf-monitord/Makefile.am0000664000175100017510000000206212411001073017260 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-monitord.la AM_CPPFLAGS = \ $(OPENSSL_CPPFLAGS) \ -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv \ -I$(srcdir)/../libpromises \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = @CFLAGS@ \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_monitord_la_LIBADD = ../libpromises/libpromises.la libcf_monitord_la_SOURCES = \ verify_measurements.c verify_measurements.h \ cf-monitord-enterprise-stubs.c cf-monitord-enterprise-stubs.h \ env_monitor.c env_monitor.h \ mon.h \ mon_cpu.c \ mon_disk.c \ mon_entropy.c \ mon_load.c \ mon_network_sniffer.c \ mon_network.c \ mon_processes.c \ mon_temp.c \ cf-monitord.c if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-monitord # Workaround for automake madness (try removing it if you want to know why). cf_monitord_CFLAGS = $(AM_CFLAGS) cf_monitord_LDADD = libcf-monitord.la endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/cf-monitord/env_monitor.c0000664000175100017510000010072312412512427017745 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // WritePID #include #include #include #include #include #include /*****************************************************************************/ /* Globals */ /*****************************************************************************/ #define CF_ENVNEW_FILE "env_data.new" #define cf_noise_threshold 6 /* number that does not warrent large anomaly status */ #define MON_THRESHOLD_HIGH 1000000 // samples should stay below this threshold #define LDT_BUFSIZE 10 double FORGETRATE = 0.7; static char ENVFILE_NEW[CF_BUFSIZE] = ""; static char ENVFILE[CF_BUFSIZE] = ""; static double HISTOGRAM[CF_OBSERVABLES][7][CF_GRAINS] = { { { 0.0 } } }; /* persistent observations */ static double CF_THIS[CF_OBSERVABLES] = { 0.0 }; /* Work */ static long ITER = 0; /* Iteration since start */ static double AGE = 0.0, WAGE = 0.0; /* Age and weekly age of database */ static Averages LOCALAV = { 0 }; /* Leap Detection vars */ static double LDT_BUF[CF_OBSERVABLES][LDT_BUFSIZE] = { { 0 } }; static double LDT_SUM[CF_OBSERVABLES] = { 0 }; static double LDT_AVG[CF_OBSERVABLES] = { 0 }; static double CHI_LIMIT[CF_OBSERVABLES] = { 0 }; static double CHI[CF_OBSERVABLES] = { 0 }; static double LDT_MAX[CF_OBSERVABLES] = { 0 }; static int LDT_POS = 0; static int LDT_FULL = false; int NO_FORK = false; /*******************************************************************/ /* Prototypes */ /*******************************************************************/ static void GetDatabaseAge(void); static void LoadHistogram(void); static void GetQ(EvalContext *ctx, const Policy *policy); static Averages EvalAvQ(EvalContext *ctx, char *timekey); static void ArmClasses(EvalContext *ctx, Averages newvals); static void GatherPromisedMeasures(EvalContext *ctx, const Policy *policy); static void LeapDetection(void); static Averages *GetCurrentAverages(char *timekey); static void UpdateAverages(EvalContext *ctx, char *timekey, Averages newvals); static void UpdateDistributions(EvalContext *ctx, char *timekey, Averages *av); static double WAverage(double newvals, double oldvals, double age); static double SetClasses(EvalContext *ctx, char *name, double variable, double av_expect, double av_var, double localav_expect, double localav_var, Item **classlist); static void SetVariable(char *name, double now, double average, double stddev, Item **list); static double RejectAnomaly(double new, double av, double var, double av2, double var2); static void ZeroArrivals(void); static PromiseResult KeepMonitorPromise(EvalContext *ctx, const Promise *pp, void *param); /****************************************************************/ void MonitorInitialize(void) { int i, j, k; char vbuff[CF_BUFSIZE]; snprintf(vbuff, sizeof(vbuff), "%s/state/cf_users", CFWORKDIR); MapName(vbuff); CreateEmptyFile(vbuff); snprintf(ENVFILE_NEW, CF_BUFSIZE, "%s/state/%s", CFWORKDIR, CF_ENVNEW_FILE); MapName(ENVFILE_NEW); snprintf(ENVFILE, CF_BUFSIZE, "%s/state/%s", CFWORKDIR, CF_ENV_FILE); MapName(ENVFILE); MonEntropyClassesInit(); GetDatabaseAge(); for (i = 0; i < CF_OBSERVABLES; i++) { LOCALAV.Q[i] = QDefinite(0.0); } for (i = 0; i < CF_OBSERVABLES; i++) { for (j = 0; j < 7; j++) { for (k = 0; k < CF_GRAINS; k++) { HISTOGRAM[i][j][k] = 0; } } } for (i = 0; i < CF_OBSERVABLES; i++) { CHI[i] = 0; CHI_LIMIT[i] = 0.1; LDT_AVG[i] = 0; LDT_SUM[i] = 0; } srand((unsigned int) time(NULL)); LoadHistogram(); /* Look for local sensors - this is unfortunately linux-centric */ MonNetworkInit(); MonTempInit(); MonOtherInit(); Log(LOG_LEVEL_DEBUG, "Finished with monitor initialization"); } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ static void GetDatabaseAge() { CF_DB *dbp; if (!OpenDB(&dbp, dbid_observations)) { return; } if (ReadDB(dbp, "DATABASE_AGE", &AGE, sizeof(double))) { WAGE = AGE / SECONDS_PER_WEEK * CF_MEASURE_INTERVAL; Log(LOG_LEVEL_DEBUG, "Previous DATABASE_AGE %f", AGE); } else { Log(LOG_LEVEL_DEBUG, "No previous DATABASE_AGE"); AGE = 0.0; } CloseDB(dbp); } /*********************************************************************/ static void LoadHistogram(void) { FILE *fp; int i, day, position; double maxval[CF_OBSERVABLES]; char filename[CF_BUFSIZE]; snprintf(filename, CF_BUFSIZE, "%s/state/histograms", CFWORKDIR); if ((fp = fopen(filename, "r")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Unable to load histogram data. (fopen: %s)", GetErrorStr()); return; } for (i = 0; i < CF_OBSERVABLES; i++) { maxval[i] = 1.0; } for (position = 0; position < CF_GRAINS; position++) { if (fscanf(fp, "%d ", &position) != 1) { Log(LOG_LEVEL_ERR, "Format error in histogram file '%s' - aborting", filename); break; } for (i = 0; i < CF_OBSERVABLES; i++) { for (day = 0; day < 7; day++) { if (fscanf(fp, "%lf ", &(HISTOGRAM[i][day][position])) != 1) { Log(LOG_LEVEL_VERBOSE, "Format error in histogram file '%s'. (fscanf: %s)", filename, GetErrorStr()); HISTOGRAM[i][day][position] = 0; } if (HISTOGRAM[i][day][position] < 0) { HISTOGRAM[i][day][position] = 0; } if (HISTOGRAM[i][day][position] > maxval[i]) { maxval[i] = HISTOGRAM[i][day][position]; } HISTOGRAM[i][day][position] *= 1000.0 / maxval[i]; } } } fclose(fp); } /*********************************************************************/ void MonitorStartServer(EvalContext *ctx, const Policy *policy) { char timekey[CF_SMALLBUF]; Averages averages; Policy *monitor_cfengine_policy = PolicyNew(); Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(monitor_cfengine_policy, NamespaceDefault(), "monitor_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "monitor_cfengine"); pp = PromiseTypeAppendPromise(tp, "the monitor daemon", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } assert(pp); CfLock thislock; #ifdef __MINGW32__ if (!NO_FORK) { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - starting in foreground"); } #else /* !__MINGW32__ */ if ((!NO_FORK) && (fork() != 0)) { Log(LOG_LEVEL_INFO, "cf-monitord: starting"); _exit(EXIT_SUCCESS); } if (!NO_FORK) { ActAsDaemon(); } #endif /* !__MINGW32__ */ TransactionContext tc = { .ifelapsed = 0, .expireafter = 0, }; thislock = AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); if (thislock.lock == NULL) { PolicyDestroy(monitor_cfengine_policy); return; } WritePID("cf-monitord.pid"); MonNetworkSnifferOpen(); while (!IsPendingTermination()) { GetQ(ctx, policy); snprintf(timekey, sizeof(timekey), "%s", GenTimeKey(time(NULL))); averages = EvalAvQ(ctx, timekey); LeapDetection(); ArmClasses(ctx, averages); ZeroArrivals(); MonNetworkSnifferSniff(EvalContextGetIpAddresses(ctx), ITER, CF_THIS); ITER++; } PolicyDestroy(monitor_cfengine_policy); YieldCurrentLock(thislock); } /*********************************************************************/ static void GetQ(EvalContext *ctx, const Policy *policy) { MonEntropyClassesReset(); ZeroArrivals(); MonProcessesGatherData(CF_THIS); MonDiskGatherData(CF_THIS); #ifndef __MINGW32__ MonCPUGatherData(CF_THIS); MonLoadGatherData(CF_THIS); MonNetworkGatherData(CF_THIS); MonNetworkSnifferGatherData(); MonTempGatherData(CF_THIS); #endif /* !__MINGW32__ */ MonOtherGatherData(CF_THIS); GatherPromisedMeasures(ctx, policy); } /*********************************************************************/ static Averages EvalAvQ(EvalContext *ctx, char *t) { Averages *lastweek_vals, newvals; double last5_vals[CF_OBSERVABLES]; char name[CF_MAXVARSIZE]; time_t now = time(NULL); int i; for (i = 0; i < CF_OBSERVABLES; i++) { last5_vals[i] = 0.0; } Banner("Evaluating and storing new weekly averages"); if ((lastweek_vals = GetCurrentAverages(t)) == NULL) { Log(LOG_LEVEL_ERR, "Error reading average database"); exit(EXIT_FAILURE); } /* Discard any apparently anomalous behaviour before renormalizing database */ for (i = 0; i < CF_OBSERVABLES; i++) { double delta2; char desc[CF_BUFSIZE]; double This; name[0] = '\0'; GetObservable(i, name, desc); /* Overflow protection */ if (lastweek_vals->Q[i].expect < 0) { lastweek_vals->Q[i].expect = 0; } if (lastweek_vals->Q[i].q < 0) { lastweek_vals->Q[i].q = 0; } if (lastweek_vals->Q[i].var < 0) { lastweek_vals->Q[i].var = 0; } // lastweek_vals is last week's stored data This = RejectAnomaly(CF_THIS[i], lastweek_vals->Q[i].expect, lastweek_vals->Q[i].var, LOCALAV.Q[i].expect, LOCALAV.Q[i].var); newvals.Q[i].q = This; newvals.last_seen = now; // Record the freshness of this slot LOCALAV.Q[i].q = This; Log(LOG_LEVEL_DEBUG, "Previous week's '%s.q' %lf", name, lastweek_vals->Q[i].q); Log(LOG_LEVEL_DEBUG, "Previous week's '%s.var' %lf", name, lastweek_vals->Q[i].var); Log(LOG_LEVEL_DEBUG, "Previous week's '%s.ex' %lf", name, lastweek_vals->Q[i].expect); Log(LOG_LEVEL_DEBUG, "Just measured: CF_THIS[%s] = %lf", name, CF_THIS[i]); Log(LOG_LEVEL_DEBUG, "Just sanitized: This[%s] = %lf", name, This); newvals.Q[i].expect = WAverage(This, lastweek_vals->Q[i].expect, WAGE); LOCALAV.Q[i].expect = WAverage(newvals.Q[i].expect, LOCALAV.Q[i].expect, ITER); if (last5_vals[i] > 0) { newvals.Q[i].dq = newvals.Q[i].q - last5_vals[i]; LOCALAV.Q[i].dq = newvals.Q[i].q - last5_vals[i]; } else { newvals.Q[i].dq = 0; LOCALAV.Q[i].dq = 0; } // Save the last measured value as the value "from five minutes ago" to get the gradient last5_vals[i] = newvals.Q[i].q; delta2 = (This - lastweek_vals->Q[i].expect) * (This - lastweek_vals->Q[i].expect); if (lastweek_vals->Q[i].var > delta2 * 2.0) { /* Clean up past anomalies */ newvals.Q[i].var = delta2; LOCALAV.Q[i].var = WAverage(newvals.Q[i].var, LOCALAV.Q[i].var, ITER); } else { newvals.Q[i].var = WAverage(delta2, lastweek_vals->Q[i].var, WAGE); LOCALAV.Q[i].var = WAverage(newvals.Q[i].var, LOCALAV.Q[i].var, ITER); } Log(LOG_LEVEL_VERBOSE, "[%d] %s q=%lf, var=%lf, ex=%lf", i, name, newvals.Q[i].q, newvals.Q[i].var, newvals.Q[i].expect); Log(LOG_LEVEL_VERBOSE, "[%d] = %lf -> (%lf#%lf) local [%lf#%lf]", i, This, newvals.Q[i].expect, sqrt(newvals.Q[i].var), LOCALAV.Q[i].expect, sqrt(LOCALAV.Q[i].var)); if (This > 0) { Log(LOG_LEVEL_VERBOSE, "Storing %.2lf in %s", This, name); } } UpdateAverages(ctx, t, newvals); UpdateDistributions(ctx, t, lastweek_vals); /* Distribution about mean */ return newvals; } /*********************************************************************/ static void LeapDetection(void) { int i, last_pos = LDT_POS; double n1, n2, d; double padding = 0.2; if (++LDT_POS >= LDT_BUFSIZE) { LDT_POS = 0; if (!LDT_FULL) { Log(LOG_LEVEL_DEBUG, "LDT Buffer full at %d", LDT_BUFSIZE); LDT_FULL = true; } } for (i = 0; i < CF_OBSERVABLES; i++) { /* First do some anomaly rejection. Sudden jumps must be numerical errors. */ if ((LDT_BUF[i][last_pos] > 0) && ((CF_THIS[i] / LDT_BUF[i][last_pos]) > 1000)) { CF_THIS[i] = LDT_BUF[i][last_pos]; } /* Note AVG should contain n+1 but not SUM, hence funny increments */ LDT_AVG[i] = LDT_AVG[i] + CF_THIS[i] / ((double) LDT_BUFSIZE + 1.0); d = (double) (LDT_BUFSIZE * (LDT_BUFSIZE + 1)) * LDT_AVG[i]; if (LDT_FULL && (LDT_POS == 0)) { n2 = (LDT_SUM[i] - (double) LDT_BUFSIZE * LDT_MAX[i]); if (d < 0.001) { CHI_LIMIT[i] = 0.5; } else { CHI_LIMIT[i] = padding + sqrt(n2 * n2 / d); } LDT_MAX[i] = 0.0; } if (CF_THIS[i] > LDT_MAX[i]) { LDT_MAX[i] = CF_THIS[i]; } n1 = (LDT_SUM[i] - (double) LDT_BUFSIZE * CF_THIS[i]); if (d < 0.001) { CHI[i] = 0.0; } else { CHI[i] = sqrt(n1 * n1 / d); } LDT_AVG[i] = LDT_AVG[i] - LDT_BUF[i][LDT_POS] / ((double) LDT_BUFSIZE + 1.0); LDT_BUF[i][LDT_POS] = CF_THIS[i]; LDT_SUM[i] = LDT_SUM[i] - LDT_BUF[i][LDT_POS] + CF_THIS[i]; } } /*********************************************************************/ static void PublishEnvironment(Item *classes) { FILE *fp; Item *ip; unlink(ENVFILE_NEW); if ((fp = fopen(ENVFILE_NEW, "a")) == NULL) { return; } for (ip = classes; ip != NULL; ip = ip->next) { fprintf(fp, "%s\n", ip->name); } MonEntropyClassesPublish(fp); fclose(fp); rename(ENVFILE_NEW, ENVFILE); } /*********************************************************************/ static void AddOpenPorts(const char *name, const Item *value, Item **mon_data) { Writer *w = StringWriter(); WriterWriteF(w, "@%s=", name); PrintItemList(value, w); if (StringWriterLength(w) <= 1500) { AppendItem(mon_data, StringWriterData(w), NULL); } WriterClose(w); } static void ArmClasses(EvalContext *ctx, Averages av) { double sigma; Item *ip, *mon_data = NULL; int i, j, k; char buff[CF_BUFSIZE], ldt_buff[CF_BUFSIZE], name[CF_MAXVARSIZE]; static int anomaly[CF_OBSERVABLES][LDT_BUFSIZE] = { { 0 } }; extern Item *ALL_INCOMING; extern Item *MON_UDP4, *MON_UDP6, *MON_TCP4, *MON_TCP6; for (i = 0; i < CF_OBSERVABLES; i++) { char desc[CF_BUFSIZE]; GetObservable(i, name, desc); sigma = SetClasses(ctx, name, CF_THIS[i], av.Q[i].expect, av.Q[i].var, LOCALAV.Q[i].expect, LOCALAV.Q[i].var, &mon_data); SetVariable(name, CF_THIS[i], av.Q[i].expect, sigma, &mon_data); /* LDT */ ldt_buff[0] = '\0'; anomaly[i][LDT_POS] = false; if (!LDT_FULL) { anomaly[i][LDT_POS] = false; } if (LDT_FULL && (CHI[i] > CHI_LIMIT[i])) { anomaly[i][LDT_POS] = true; /* Remember the last anomaly value */ Log(LOG_LEVEL_VERBOSE, "LDT(%d) in %s chi = %.2f thresh %.2f ", LDT_POS, name, CHI[i], CHI_LIMIT[i]); /* Last printed element is now */ for (j = LDT_POS + 1, k = 0; k < LDT_BUFSIZE; j++, k++) { if (j == LDT_BUFSIZE) /* Wrap */ { j = 0; } if (anomaly[i][j]) { snprintf(buff, CF_BUFSIZE, " *%.2f*", LDT_BUF[i][j]); } else { snprintf(buff, CF_BUFSIZE, " %.2f", LDT_BUF[i][j]); } strcat(ldt_buff, buff); } if (CF_THIS[i] > av.Q[i].expect) { snprintf(buff, CF_BUFSIZE, "%s_high_ldt", name); } else { snprintf(buff, CF_BUFSIZE, "%s_high_ldt", name); } AppendItem(&mon_data, buff, "2"); EvalContextHeapPersistentSave(ctx, buff, CF_PERSISTENCE, CONTEXT_STATE_POLICY_PRESERVE, ""); EvalContextClassPutSoft(ctx, buff, CONTEXT_SCOPE_NAMESPACE, ""); } else { for (j = LDT_POS + 1, k = 0; k < LDT_BUFSIZE; j++, k++) { if (j == LDT_BUFSIZE) /* Wrap */ { j = 0; } if (anomaly[i][j]) { snprintf(buff, CF_BUFSIZE, " *%.2f*", LDT_BUF[i][j]); } else { snprintf(buff, CF_BUFSIZE, " %.2f", LDT_BUF[i][j]); } strcat(ldt_buff, buff); } } } SetMeasurementPromises(&mon_data); // Report on the open ports, in various ways AddOpenPorts("listening_ports", ALL_INCOMING, &mon_data); AddOpenPorts("listening_udp6_ports", MON_UDP6, &mon_data); AddOpenPorts("listening_udp4_ports", MON_UDP4, &mon_data); AddOpenPorts("listening_tcp6_ports", MON_TCP6, &mon_data); AddOpenPorts("listening_tcp4_ports", MON_TCP4, &mon_data); // Port addresses if (ListLen(MON_TCP6) + ListLen(MON_TCP4) > 512) { Log(LOG_LEVEL_INFO, "Disabling address information of TCP ports in LISTEN state: more than 512 listening ports are detected"); } else { for (ip = MON_TCP6; ip != NULL; ip=ip->next) { snprintf(buff,CF_BUFSIZE,"tcp6_port_addr[%s]=%s",ip->name,ip->classes); AppendItem(&mon_data, buff, NULL); } for (ip = MON_TCP4; ip != NULL; ip=ip->next) { snprintf(buff,CF_BUFSIZE,"tcp4_port_addr[%s]=%s",ip->name,ip->classes); AppendItem(&mon_data, buff, NULL); } } for (ip = MON_UDP6; ip != NULL; ip=ip->next) { snprintf(buff,CF_BUFSIZE,"udp6_port_addr[%s]=%s",ip->name,ip->classes); AppendItem(&mon_data, buff, NULL); } for (ip = MON_UDP4; ip != NULL; ip=ip->next) { snprintf(buff,CF_BUFSIZE,"udp4_port_addr[%s]=%s",ip->name,ip->classes); AppendItem(&mon_data, buff, NULL); } PublishEnvironment(mon_data); DeleteItemList(mon_data); } /*****************************************************************************/ static Averages *GetCurrentAverages(char *timekey) { CF_DB *dbp; static Averages entry; /* No need to initialize */ if (!OpenDB(&dbp, dbid_observations)) { return NULL; } memset(&entry, 0, sizeof(entry)); AGE++; WAGE = AGE / SECONDS_PER_WEEK * CF_MEASURE_INTERVAL; if (ReadDB(dbp, timekey, &entry, sizeof(Averages))) { int i; for (i = 0; i < CF_OBSERVABLES; i++) { Log(LOG_LEVEL_DEBUG, "Previous values (%lf,..) for time index '%s'", entry.Q[i].expect, timekey); } } else { Log(LOG_LEVEL_DEBUG, "No previous value for time index '%s'", timekey); } CloseDB(dbp); return &entry; } /*****************************************************************************/ static void UpdateAverages(EvalContext *ctx, char *timekey, Averages newvals) { CF_DB *dbp; if (!OpenDB(&dbp, dbid_observations)) { return; } Log(LOG_LEVEL_INFO, "Updated averages at '%s'", timekey); WriteDB(dbp, timekey, &newvals, sizeof(Averages)); WriteDB(dbp, "DATABASE_AGE", &AGE, sizeof(double)); CloseDB(dbp); HistoryUpdate(ctx, newvals); } static int Day2Number(const char *datestring) { int i = 0; for (i = 0; i < 7; i++) { if (strncmp(datestring, DAY_TEXT[i], 3) == 0) { return i; } } return -1; } static void UpdateDistributions(EvalContext *ctx, char *timekey, Averages *av) { int position, day, i; char filename[CF_BUFSIZE]; FILE *fp; /* Take an interval of 4 standard deviations from -2 to +2, divided into CF_GRAINS parts. Centre each measurement on CF_GRAINS/2 and scale each measurement by the std-deviation for the current time. */ if (IsDefinedClass(ctx, "Min40_45")) { day = Day2Number(timekey); for (i = 0; i < CF_OBSERVABLES; i++) { position = CF_GRAINS / 2 + (int) (0.5 + (CF_THIS[i] - av->Q[i].expect) * CF_GRAINS / (4 * sqrt((av->Q[i].var)))); if ((0 <= position) && (position < CF_GRAINS)) { HISTOGRAM[i][day][position]++; } } snprintf(filename, CF_BUFSIZE, "%s/state/histograms", CFWORKDIR); if ((fp = fopen(filename, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Unable to save histograms. (fopen: %s)", GetErrorStr()); return; } for (position = 0; position < CF_GRAINS; position++) { fprintf(fp, "%d ", position); for (i = 0; i < CF_OBSERVABLES; i++) { for (day = 0; day < 7; day++) { fprintf(fp, "%.0lf ", HISTOGRAM[i][day][position]); } } fprintf(fp, "\n"); } fclose(fp); } } /*****************************************************************************/ /* For a couple of weeks, learn eagerly. Otherwise variances will be way too large. Then downplay newer data somewhat, and rely on experience of a couple of months of data ... */ static double WAverage(double anew, double aold, double age) { double av, cf_sane_monitor_limit = 9999999.0; double wnew, wold; /* First do some database corruption self-healing */ if ((aold > cf_sane_monitor_limit) && (anew > cf_sane_monitor_limit)) { return 0; } if (aold > cf_sane_monitor_limit) { return anew; } if (aold > cf_sane_monitor_limit) { return aold; } /* Now look at the self-learning */ if ((FORGETRATE > 0.9) || (FORGETRATE < 0.1)) { FORGETRATE = 0.6; } if (age < 2.0) /* More aggressive learning for young database */ { wnew = FORGETRATE; wold = (1.0 - FORGETRATE); } else { wnew = (1.0 - FORGETRATE); wold = FORGETRATE; } if ((aold == 0) && (anew == 0)) { return 0; } /* * AV = (Wnew*Anew + Wold*Aold) / (Wnew + Wold). * * Wnew + Wold always equals to 1, so we omit it for better precision and * performance. */ av = (wnew * anew + wold * aold); if (av < 0) { /* Accuracy lost - something wrong */ return 0.0; } return av; } /*****************************************************************************/ static double SetClasses(EvalContext *ctx, char *name, double variable, double av_expect, double av_var, double localav_expect, double localav_var, Item **classlist) { char buffer[CF_BUFSIZE], buffer2[CF_BUFSIZE]; double dev, delta, sigma, ldelta, lsigma, sig; delta = variable - av_expect; sigma = sqrt(av_var); ldelta = variable - localav_expect; lsigma = sqrt(localav_var); sig = sqrt(sigma * sigma + lsigma * lsigma); Log(LOG_LEVEL_DEBUG, "delta = %lf, sigma = %lf, lsigma = %lf, sig = %lf", delta, sigma, lsigma, sig); if ((sigma == 0.0) || (lsigma == 0.0)) { Log(LOG_LEVEL_DEBUG, "No sigma variation .. can't measure class"); snprintf(buffer, CF_MAXVARSIZE, "entropy_%s.*", name); MonEntropyPurgeUnused(buffer); return sig; } Log(LOG_LEVEL_DEBUG, "Setting classes for '%s'...", name); if (fabs(delta) < cf_noise_threshold) /* Arbitrary limits on sensitivity */ { Log(LOG_LEVEL_DEBUG, "Sensitivity too high"); buffer[0] = '\0'; strcpy(buffer, name); if ((delta > 0) && (ldelta > 0)) { strcat(buffer, "_high"); } else if ((delta < 0) && (ldelta < 0)) { strcat(buffer, "_low"); } else { strcat(buffer, "_normal"); } AppendItem(classlist, buffer, "0"); dev = sqrt(delta * delta / (1.0 + sigma * sigma) + ldelta * ldelta / (1.0 + lsigma * lsigma)); if (dev > 2.0 * sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_microanomaly"); AppendItem(classlist, buffer2, "2"); EvalContextHeapPersistentSave(ctx, buffer2, CF_PERSISTENCE, CONTEXT_STATE_POLICY_PRESERVE, ""); EvalContextClassPutSoft(ctx, buffer2, CONTEXT_SCOPE_NAMESPACE, ""); } return sig; /* Granularity makes this silly */ } else { buffer[0] = '\0'; strcpy(buffer, name); if ((delta > 0) && (ldelta > 0)) { strcat(buffer, "_high"); } else if ((delta < 0) && (ldelta < 0)) { strcat(buffer, "_low"); } else { strcat(buffer, "_normal"); } dev = sqrt(delta * delta / (1.0 + sigma * sigma) + ldelta * ldelta / (1.0 + lsigma * lsigma)); if (dev <= sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_normal"); AppendItem(classlist, buffer2, "0"); } else { strcpy(buffer2, buffer); strcat(buffer2, "_dev1"); AppendItem(classlist, buffer2, "0"); } /* Now use persistent classes so that serious anomalies last for about 2 autocorrelation lengths, so that they can be cross correlated and seen by normally scheduled cfagent processes ... */ if (dev > 2.0 * sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_dev2"); AppendItem(classlist, buffer2, "2"); EvalContextHeapPersistentSave(ctx, buffer2, CF_PERSISTENCE, CONTEXT_STATE_POLICY_PRESERVE, ""); EvalContextClassPutSoft(ctx, buffer2, CONTEXT_SCOPE_NAMESPACE, ""); } if (dev > 3.0 * sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_anomaly"); AppendItem(classlist, buffer2, "3"); EvalContextHeapPersistentSave(ctx, buffer2, CF_PERSISTENCE, CONTEXT_STATE_POLICY_PRESERVE, ""); EvalContextClassPutSoft(ctx, buffer2, CONTEXT_SCOPE_NAMESPACE, ""); } return sig; } } /*****************************************************************************/ static void SetVariable(char *name, double value, double average, double stddev, Item **classlist) { char var[CF_BUFSIZE]; snprintf(var, CF_MAXVARSIZE, "value_%s=%.2lf", name, value); AppendItem(classlist, var, ""); snprintf(var, CF_MAXVARSIZE, "av_%s=%.2lf", name, average); AppendItem(classlist, var, ""); snprintf(var, CF_MAXVARSIZE, "dev_%s=%.2lf", name, stddev); AppendItem(classlist, var, ""); } /*****************************************************************************/ static void ZeroArrivals() { memset(CF_THIS, 0, sizeof(CF_THIS)); } /*****************************************************************************/ static double RejectAnomaly(double new, double average, double variance, double localav, double localvar) { double dev = sqrt(variance + localvar); /* Geometrical average dev */ double delta; int bigger; if (average == 0) { return new; } if (new > MON_THRESHOLD_HIGH * 4.0) { return 0.0; } if (new > MON_THRESHOLD_HIGH) { return average; } if ((new - average) * (new - average) < cf_noise_threshold * cf_noise_threshold) { return new; } if (new - average > 0) { bigger = true; } else { bigger = false; } /* This routine puts some inertia into the changes, so that the system doesn't respond to every little change ... IR and UV cutoff */ delta = sqrt((new - average) * (new - average) + (new - localav) * (new - localav)); if (delta > 4.0 * dev) /* IR */ { srand48((unsigned int) time(NULL)); if (drand48() < 0.7) /* 70% chance of using full value - as in learning policy */ { return new; } else { if (bigger) { return average + 2.0 * dev; } else { return average - 2.0 * dev; } } } else { Log(LOG_LEVEL_VERBOSE, "Value accepted"); return new; } } /***************************************************************/ /* Level 5 */ /***************************************************************/ static void GatherPromisedMeasures(EvalContext *ctx, const Policy *policy) { for (size_t i = 0; i < SeqLength(policy->bundles); i++) { const Bundle *bp = SeqAt(policy->bundles, i); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_MONITOR]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepMonitorPromise, NULL); } EvalContextStackPopFrame(ctx); } } EvalContextStackPopFrame(ctx); } EvalContextClear(ctx); DetectEnvironment(ctx); } /*********************************************************************/ /* Level */ /*********************************************************************/ static PromiseResult KeepMonitorPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert(param == NULL); if (strcmp("vars", pp->parent_promise_type->name) == 0) { return PROMISE_RESULT_NOOP; } else if (strcmp("classes", pp->parent_promise_type->name) == 0) { return VerifyClassPromise(ctx, pp, NULL); } else if (strcmp("measurements", pp->parent_promise_type->name) == 0) { PromiseResult result = VerifyMeasurementPromise(ctx, CF_THIS, pp); return result; } else if (strcmp("reports", pp->parent_promise_type->name) == 0) { return PROMISE_RESULT_NOOP; } assert(false && "Unknown promise type"); return PROMISE_RESULT_NOOP; } cfengine-3.6.2/cf-monitord/verify_measurements.h0000644000175100017510000000225612316547775021530 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_VERIFY_MEASUREMENTS_H #define CFENGINE_VERIFY_MEASUREMENTS_H #include PromiseResult VerifyMeasurementPromise(EvalContext *ctx, double *measurement, const Promise *pp); #endif cfengine-3.6.2/cf-monitord/cf-monitord-enterprise-stubs.h0000644000175100017510000000310112316547775023157 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF_MONITORD_ENTERPRISE_STUBS_H #define CFENGINE_CF_MONITORD_ENTERPRISE_STUBS_H #include ENTERPRISE_VOID_FUNC_0ARG_DECLARE(void, MonOtherInit); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, MonOtherGatherData, double *, cf_this); ENTERPRISE_VOID_FUNC_2ARG_DECLARE(void, HistoryUpdate, EvalContext *, ctx, Averages, newvals); ENTERPRISE_FUNC_4ARG_DECLARE(PromiseResult, VerifyMeasurement, EvalContext *, ctx, double *, this, Attributes, a, const Promise *, pp); #endif cfengine-3.6.2/cf-monitord/mon_cpu.c0000644000175100017510000000667112316547775017074 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #if !defined(__MINGW32__) /* Constants */ # define MON_CPU_MAX 4 /* Globals */ static double LAST_CPU_Q[MON_CPU_MAX + 1] = { 0.0 }; static long LAST_CPU_T[MON_CPU_MAX + 1] = { 0 }; /* Implementation */ void MonCPUGatherData(double *cf_this) { double q, dq; char cpuname[CF_MAXVARSIZE], buf[CF_BUFSIZE]; long cpuidx, userticks = 0, niceticks = 0, systemticks = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; long total_time = 1; FILE *fp; enum observables slot = ob_spare; if ((fp = fopen("/proc/stat", "r")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Didn't find proc data"); return; } Log(LOG_LEVEL_VERBOSE, "Reading /proc/stat utilization data -------"); while (!feof(fp)) { if (fgets(buf, sizeof(buf), fp) == NULL) { break; } if (sscanf(buf, "%s%ld%ld%ld%ld%ld%ld%ld", cpuname, &userticks, &niceticks, &systemticks, &idle, &iowait, &irq, &softirq) != 8) { Log(LOG_LEVEL_VERBOSE, "Could not scan /proc/stat line: %60s", buf); continue; } total_time = (userticks + niceticks + systemticks + idle); q = 100.0 * (double) (total_time - idle); if (strcmp(cpuname, "cpu") == 0) { Log(LOG_LEVEL_VERBOSE, "Found aggregate CPU"); slot = ob_cpuall; cpuidx = MON_CPU_MAX; } else if (strncmp(cpuname, "cpu", 3) == 0) { if (sscanf(cpuname, "cpu%ld", &cpuidx) == 1) { if ((cpuidx < 0) || (cpuidx >= MON_CPU_MAX)) { continue; } } else { continue; } slot = ob_cpu0 + cpuidx; } else { Log(LOG_LEVEL_VERBOSE, "Found nothing (%s)", cpuname); slot = ob_spare; fclose(fp); return; } dq = (q - LAST_CPU_Q[cpuidx]) / (double) (total_time - LAST_CPU_T[cpuidx]); /* % Utilization */ if ((dq > 100) || (dq < 0)) // Counter wrap around { dq = 50; } cf_this[slot] = dq; LAST_CPU_Q[cpuidx] = q; LAST_CPU_T[cpuidx] = total_time; Log(LOG_LEVEL_VERBOSE, "Set %s=%d to %.1lf after %ld 100ths of a second ", OBS[slot][1], slot, cf_this[slot], total_time); } fclose(fp); } #endif /* !__MINGW32__ */ cfengine-3.6.2/cf-monitord/cf-monitord.c0000664000175100017510000002305512411001073017616 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef enum { MONITOR_CONTROL_FORGET_RATE, MONITOR_CONTROL_MONITOR_FACILITY, MONITOR_CONTROL_HISTOGRAMS, MONITOR_CONTROL_TCP_DUMP, MONITOR_CONTROL_NONE } MonitorControl; static void ThisAgentInit(EvalContext *ctx); static GenericAgentConfig *CheckOpts(int argc, char **argv); static void KeepPromises(EvalContext *ctx, const Policy *policy); /*****************************************************************************/ /* Globals */ /*****************************************************************************/ extern int NO_FORK; extern const ConstraintSyntax CFM_CONTROLBODY[]; /*******************************************************************/ /* Command line options */ /*******************************************************************/ static const char *const CF_MONITORD_SHORT_DESCRIPTION = "monitoring daemon for CFEngine"; static const char *const CF_MONITORD_MANPAGE_LONG_DESCRIPTION = "cf-monitord is the monitoring daemon for CFEngine. It samples probes defined in policy code and attempts to learn the " "normal system state based on current and past observations. Current estimates are made available as " "special variables (e.g. $(mon.av_cpu)) to cf-agent, which may use them to inform policy decisions."; static const struct option OPTIONS[] = { {"help", no_argument, 0, 'h'}, {"debug", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"dry-run", no_argument, 0, 'n'}, {"version", no_argument, 0, 'V'}, {"no-lock", no_argument, 0, 'K'}, {"file", required_argument, 0, 'f'}, {"inform", no_argument, 0, 'I'}, {"diagnostic", no_argument, 0, 'x'}, {"no-fork", no_argument, 0, 'F'}, {"histograms", no_argument, 0, 'H'}, {"tcpdump", no_argument, 0, 'T'}, {"legacy-output", no_argument, 0, 'l'}, {"color", optional_argument, 0, 'C'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { "Print the help message", "Enable debugging output", "Output verbose information about the behaviour of the agent", "All talk and no action mode - make no changes, only inform of promises not kept", "Output the version of the software", "Ignore system lock", "Specify an alternative input file than the default", "Print basic information about changes made to the system, i.e. promises repaired", "Activate internal diagnostics (developers only)", "Run process in foreground, not as a daemon", "Ignored for backward compatibility", "Interface with tcpdump if available to collect data about network", "Use legacy output format", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", NULL }; /*****************************************************************************/ int main(int argc, char *argv[]) { GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); Policy *policy = LoadPolicy(ctx, config); ThisAgentInit(ctx); KeepPromises(ctx, policy); MonitorStartServer(ctx, policy); PolicyDestroy(policy); GenericAgentFinalize(ctx, config); return 0; } /*******************************************************************/ static GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_MONITOR); while ((c = getopt_long(argc, argv, "dvnIf:VSxHTKMFhlC::", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'l': LEGACY_OUTPUT = true; break; case 'f': GenericAgentConfigSetInputFile(config, GetInputDir(), optarg); MINUSF = true; break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); NO_FORK = true; break; case 'K': config->ignore_locks = true; break; case 'I': LogSetGlobalLevel(LOG_LEVEL_INFO); break; case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); NO_FORK = true; break; case 'F': NO_FORK = true; break; case 'H': /* Keep accepting this option for compatibility -- no longer used */ break; case 'T': MonNetworkSnifferEnable(true); break; case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-monitord", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-monitord", time(NULL), CF_MONITORD_SHORT_DESCRIPTION, CF_MONITORD_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, true); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'x': Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired."); exit(EXIT_SUCCESS); case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-monitord", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_FAILURE); } } if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind)) { Log(LOG_LEVEL_ERR, "Too many arguments"); exit(EXIT_FAILURE); } return config; } /*****************************************************************************/ static void KeepPromises(EvalContext *ctx, const Policy *policy) { Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_MONITOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_monitor"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in monitor control body", cp->lval); continue; } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_HISTOGRAMS].lval) == 0) { /* Keep accepting this option for backward compatibility. */ } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_TCP_DUMP].lval) == 0) { MonNetworkSnifferEnable(BooleanFromString(value)); } if (strcmp(cp->lval, CFM_CONTROLBODY[MONITOR_CONTROL_FORGET_RATE].lval) == 0) { sscanf(value, "%lf", &FORGETRATE); Log(LOG_LEVEL_DEBUG, "forget rate %f", FORGETRATE); } } } } /*****************************************************************************/ /* Level 1 */ /*****************************************************************************/ static void ThisAgentInit(EvalContext *ctx) { umask(077); strcpy(VPREFIX, "cf-monitord"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); FORGETRATE = 0.6; MonitorInitialize(); } cfengine-3.6.2/cf-monitord/mon_disk.c0000664000175100017510000000570412400110676017211 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* Globals */ static double LASTQ[CF_OBSERVABLES] = { 0.0 }; /* Prototypes */ static int GetFileGrowth(const char *filename, enum observables index); /* Implementation */ void MonDiskGatherData(double *cf_this) { char accesslog[CF_BUFSIZE]; char errorlog[CF_BUFSIZE]; char syslog[CF_BUFSIZE]; char messages[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "Gathering disk data"); cf_this[ob_diskfree] = GetDiskUsage("/", CF_SIZE_PERCENT); Log(LOG_LEVEL_VERBOSE, "Disk free = %.0lf%%", cf_this[ob_diskfree]); /* Here would should have some detection based on OS type VSYSTEMHARDCLASS */ strcpy(accesslog, "/var/log/apache2/access_log"); strcpy(errorlog, "/var/log/apache2/error_log"); strcpy(syslog, "/var/log/syslog"); strcpy(messages, "/var/log/messages"); cf_this[ob_webaccess] = GetFileGrowth(accesslog, ob_webaccess); Log(LOG_LEVEL_VERBOSE, "Webaccess = %.2lf%%", cf_this[ob_webaccess]); cf_this[ob_weberrors] = GetFileGrowth(errorlog, ob_weberrors); Log(LOG_LEVEL_VERBOSE, "Web error = %.2lf%%", cf_this[ob_weberrors]); cf_this[ob_syslog] = GetFileGrowth(syslog, ob_syslog); Log(LOG_LEVEL_VERBOSE, "Syslog = %.2lf%%", cf_this[ob_syslog]); cf_this[ob_messages] = GetFileGrowth(messages, ob_messages); Log(LOG_LEVEL_VERBOSE, "Messages = %.2lf%%", cf_this[ob_messages]); } /****************************************************************************/ static int GetFileGrowth(const char *filename, enum observables index) { struct stat statbuf; size_t q; double dq; if (stat(filename, &statbuf) == -1) { return 0; } q = statbuf.st_size; Log(LOG_LEVEL_VERBOSE, "GetFileGrowth(%s) = %zu", filename, q); dq = (double) q - LASTQ[index]; if (LASTQ[index] == 0) { LASTQ[index] = q; return (int) (q / 100 + 0.5); /* arbitrary spike mitigation */ } LASTQ[index] = q; return (int) (dq + 0.5); } cfengine-3.6.2/cf-monitord/mon_temp.c0000644000175100017510000002400012316547775017234 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include /* Globals */ static bool ACPI = false; static bool LMSENSORS = false; /* Prototypes */ #if defined(__linux__) static bool GetAcpi(double *cf_this); static bool GetLMSensors(double *cf_this); #endif /* Implementation */ /****************************************************************************** * Motherboard sensors - how to standardize this somehow * We're mainly interested in temperature and power consumption, but only the * temperature is generally available. Several temperatures exist too ... ******************************************************************************/ #if defined(__linux__) void MonTempGatherData(double *cf_this) { if (ACPI && GetAcpi(cf_this)) { return; } if (LMSENSORS && GetLMSensors(cf_this)) { return; } } #else void MonTempGatherData(ARG_UNUSED double *cf_this) { } #endif /******************************************************************************/ void MonTempInit(void) { struct stat statbuf; if (stat("/proc/acpi/thermal_zone", &statbuf) != -1) { Log(LOG_LEVEL_DEBUG, "Found an acpi service"); ACPI = true; } if (stat("/usr/bin/sensors", &statbuf) != -1) { if (statbuf.st_mode & 0111) { Log(LOG_LEVEL_DEBUG, "Found an lmsensor system"); LMSENSORS = true; } } } /******************************************************************************/ #if defined(__linux__) static bool GetAcpi(double *cf_this) { Dir *dirh; FILE *fp; const struct dirent *dirp; int count = 0; char path[CF_BUFSIZE], buf[CF_BUFSIZE], index[4]; double temp = 0; if ((dirh = DirOpen("/proc/acpi/thermal_zone")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Can't open directory '%s'. (opendir: %s)", path, GetErrorStr()); return false; } for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, "..")) { continue; } snprintf(path, CF_BUFSIZE, "/proc/acpi/thermal_zone/%s/temperature", dirp->d_name); if ((fp = fopen(path, "r")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open '%s'", path); continue; } if (fgets(buf, sizeof(buf), fp) == NULL) { Log(LOG_LEVEL_ERR, "Failed to read line from stream '%s'", path); fclose(fp); continue; } sscanf(buf, "%*s %lf", &temp); for (count = 0; count < 4; count++) { snprintf(index, 2, "%d", count); if (strstr(dirp->d_name, index)) { switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf", count, temp); } } fclose(fp); } DirClose(dirh); return true; } /******************************************************************************/ static bool GetLMSensors(double *cf_this) { FILE *pp; Item *ip, *list = NULL; double temp = 0; char name[CF_BUFSIZE]; int count; cf_this[ob_temp0] = 0.0; cf_this[ob_temp1] = 0.0; cf_this[ob_temp2] = 0.0; cf_this[ob_temp3] = 0.0; if ((pp = cf_popen("/usr/bin/sensors", "r", true)) == NULL) { LMSENSORS = false; /* Broken */ return false; } { size_t vbuff_size = CF_BUFSIZE; char *vbuff = xmalloc(vbuff_size); ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res <= 0) { /* FIXME: do we need to log anything here? */ cf_pclose(pp); free(vbuff); return false; } for (;;) { ssize_t res = CfReadLine(&vbuff, &vbuff_size, pp); if (res == -1) { if (!feof(pp)) { /* FIXME: Do we need to log anything here? */ cf_pclose(pp); free(vbuff); return false; } else { break; } } if (strstr(vbuff, "Temp") || strstr(vbuff, "temp")) { PrependItem(&list, vbuff, NULL); } } cf_pclose(pp); free(vbuff); } if (ListLen(list) > 0) { Log(LOG_LEVEL_DEBUG, "LM Sensors seemed to return ok data"); } else { return false; } /* lmsensor names are hopelessly inconsistent - so try a few things */ for (ip = list; ip != NULL; ip = ip->next) { for (count = 0; count < 4; count++) { snprintf(name, 16, "CPU%d Temp:", count); if (strncmp(ip->name, name, strlen(name)) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf from what looks like cpu temperature", count, temp); } } } if (cf_this[ob_temp0] != 0) { /* We got something plausible */ return true; } /* Alternative name Core x: */ for (ip = list; ip != NULL; ip = ip->next) { for (count = 0; count < 4; count++) { snprintf(name, 16, "Core %d:", count); if (strncmp(ip->name, name, strlen(name)) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf from what looks like core temperatures", count, temp); } } } if (cf_this[ob_temp0] != 0) { /* We got something plausible */ return true; } for (ip = list; ip != NULL; ip = ip->next) { if (strncmp(ip->name, "CPU Temp:", strlen("CPU Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to CPU Temp"); cf_this[ob_temp0] = temp; } if (strncmp(ip->name, "M/B Temp:", strlen("M/B Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to M/B Temp"); cf_this[ob_temp1] = temp; } if (strncmp(ip->name, "Sys Temp:", strlen("Sys Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to Sys Temp"); cf_this[ob_temp2] = temp; } if (strncmp(ip->name, "AUX Temp:", strlen("AUX Temp:")) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); Log(LOG_LEVEL_DEBUG, "Setting temp0 to AUX Temp"); cf_this[ob_temp3] = temp; } } if (cf_this[ob_temp0] != 0) { /* We got something plausible */ return true; } /* Alternative name Core x: */ for (ip = list; ip != NULL; ip = ip->next) { for (count = 0; count < 4; count++) { snprintf(name, 16, "temp%d:", count); if (strncmp(ip->name, name, strlen(name)) == 0) { sscanf(ip->name, "%*[^:]: %lf", &temp); switch (count) { case 0: cf_this[ob_temp0] = temp; break; case 1: cf_this[ob_temp1] = temp; break; case 2: cf_this[ob_temp2] = temp; break; case 3: cf_this[ob_temp3] = temp; break; } Log(LOG_LEVEL_DEBUG, "Set temp%d to %lf", count, temp); } } } /* Give up? */ DeleteItemList(list); return true; } #endif cfengine-3.6.2/cf-monitord/mon_network_sniffer.c0000644000175100017510000003612312352557236021476 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include typedef enum { IP_TYPES_ICMP, IP_TYPES_UDP, IP_TYPES_DNS, IP_TYPES_TCP_SYN, IP_TYPES_TCP_ACK, IP_TYPES_TCP_FIN, IP_TYPES_TCP_MISC } IPTypes; /* Constants */ #define CF_TCPDUMP_COMM "/usr/sbin/tcpdump -t -n -v" static const int SLEEPTIME = 2.5 * 60; /* Should be a fraction of 5 minutes */ static const char *const TCPNAMES[CF_NETATTR] = { "icmp", "udp", "dns", "tcpsyn", "tcpack", "tcpfin", "misc" }; /* Global variables */ static bool TCPDUMP = false; static bool TCPPAUSE = false; static FILE *TCPPIPE = NULL; static Item *NETIN_DIST[CF_NETATTR] = { NULL }; static Item *NETOUT_DIST[CF_NETATTR] = { NULL }; /* Prototypes */ static void Sniff(Item *ip_addresses, long iteration, double *cf_this); static void AnalyzeArrival(Item *ip_addresses, long iteration, char *arrival, double *cf_this); static void DePort(char *address); /* Implementation */ void MonNetworkSnifferSniff(Item *ip_addresses, long iteration, double *cf_this) { if (TCPDUMP) { Sniff(ip_addresses, iteration, cf_this); } else { sleep(SLEEPTIME); } } /******************************************************************************/ void MonNetworkSnifferOpen(void) { char tcpbuffer[CF_BUFSIZE]; if (TCPDUMP) { struct stat statbuf; char buffer[CF_MAXVARSIZE]; sscanf(CF_TCPDUMP_COMM, "%s", buffer); if (stat(buffer, &statbuf) != -1) { if ((TCPPIPE = cf_popen(CF_TCPDUMP_COMM, "r", true)) == NULL) { TCPDUMP = false; } /* Skip first banner */ if (fgets(tcpbuffer, sizeof(tcpbuffer), TCPPIPE) == NULL) { UnexpectedError("Failed to read output from '%s'", CF_TCPDUMP_COMM); cf_pclose(TCPPIPE); TCPPIPE = NULL; TCPDUMP = false; } } else { TCPDUMP = false; } } } /******************************************************************************/ void MonNetworkSnifferEnable(bool enable) { TCPDUMP = enable; Log(LOG_LEVEL_DEBUG, "use tcpdump = %d", TCPDUMP); } /******************************************************************************/ static void CfenvTimeOut(ARG_UNUSED int signum) { alarm(0); TCPPAUSE = true; Log(LOG_LEVEL_VERBOSE, "Time out"); } /******************************************************************************/ static void Sniff(Item *ip_addresses, long iteration, double *cf_this) { char tcpbuffer[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "Reading from tcpdump..."); memset(tcpbuffer, 0, CF_BUFSIZE); signal(SIGALRM, CfenvTimeOut); alarm(SLEEPTIME); TCPPAUSE = false; while (!feof(TCPPIPE) && !IsPendingTermination()) { if (TCPPAUSE) { break; } if (fgets(tcpbuffer, sizeof(tcpbuffer), TCPPIPE) == NULL) { UnexpectedError("Unable to read data from tcpdump; closing pipe"); cf_pclose(TCPPIPE); TCPPIPE = NULL; TCPDUMP = false; break; } if (TCPPAUSE) { break; } if (strstr(tcpbuffer, "tcpdump:")) /* Error message protect sleeptime */ { Log(LOG_LEVEL_DEBUG, "Error - '%s'", tcpbuffer); alarm(0); TCPDUMP = false; break; } AnalyzeArrival(ip_addresses, iteration, tcpbuffer, cf_this); } signal(SIGALRM, SIG_DFL); TCPPAUSE = false; fflush(TCPPIPE); } /******************************************************************************/ static void IncrementCounter(Item **list, char *name) { if (!IsItemIn(*list, name)) { AppendItem(list, name, ""); } IncrementItemListCounter(*list, name); } /* This coarsely classifies TCP dump data */ static void AnalyzeArrival(Item *ip_addresses, long iteration, char *arrival, double *cf_this) { char src[CF_BUFSIZE], dest[CF_BUFSIZE], flag = '.', *arr; int isme_dest, isme_src; src[0] = dest[0] = '\0'; if (strstr(arrival, "listening")) { return; } if (Chop(arrival, CF_EXPANDSIZE) == -1) { Log(LOG_LEVEL_ERR, "Chop was called on a string that seemed to have no terminator"); } /* Most hosts have only a few dominant services, so anomalies will show up even in the traffic without looking too closely. This will apply only to the main interface .. not multifaces New format in tcpdump IP (tos 0x10, ttl 64, id 14587, offset 0, flags [DF], proto TCP (6), length 692) 128.39.89.232.22 > 84.215.40.125.48022: P 1546432:1547072(640) ack 1969 win 1593 IP (tos 0x0, ttl 251, id 14109, offset 0, flags [DF], proto UDP (17), length 115) 84.208.20.110.53 > 192.168.1.103.32769: 45266 NXDomain 0/1/0 (87) arp who-has 192.168.1.1 tell 192.168.1.103 arp reply 192.168.1.1 is-at 00:1d:7e:28:22:c6 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.1.103 > 128.39.89.10: ICMP echo request, id 48474, seq 1, length 64 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.1.103 > 128.39.89.10: ICMP echo request, id 48474, seq 2, length 64 */ for (arr = strstr(arrival, "length"); (arr != NULL) && (*arr != ')'); arr++) { } if (arr == NULL) { arr = arrival; } else { arr++; } if ((strstr(arrival, "proto TCP")) || (strstr(arrival, "ack"))) { sscanf(arr, "%s %*c %s %c ", src, dest, &flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(ip_addresses, dest); isme_src = IsInterfaceAddress(ip_addresses, src); switch (flag) { case 'S': Log(LOG_LEVEL_DEBUG, "%ld: TCP new connection from '%s' to '%s' - i am '%s'", iteration, src, dest, VIPADDRESS); if (isme_dest) { cf_this[ob_tcpsyn_in]++; IncrementCounter(&(NETIN_DIST[IP_TYPES_TCP_SYN]), src); } else if (isme_src) { cf_this[ob_tcpsyn_out]++; IncrementCounter(&(NETOUT_DIST[IP_TYPES_TCP_SYN]), dest); } break; case 'F': Log(LOG_LEVEL_DEBUG, "%ld: TCP end connection from '%s' to '%s'", iteration, src, dest); if (isme_dest) { cf_this[ob_tcpfin_in]++; IncrementCounter(&(NETIN_DIST[IP_TYPES_TCP_FIN]), src); } else if (isme_src) { cf_this[ob_tcpfin_out]++; IncrementCounter(&(NETOUT_DIST[IP_TYPES_TCP_FIN]), dest); } break; default: Log(LOG_LEVEL_DEBUG, "%ld: TCP established from '%s' to '%s'", iteration, src, dest); if (isme_dest) { cf_this[ob_tcpack_in]++; IncrementCounter(&(NETIN_DIST[IP_TYPES_TCP_ACK]), src); } else if (isme_src) { cf_this[ob_tcpack_out]++; IncrementCounter(&(NETOUT_DIST[IP_TYPES_TCP_ACK]), dest); } break; } } else if (strstr(arrival, ".53")) { sscanf(arr, "%s %*c %s %c ", src, dest, &flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(ip_addresses, dest); isme_src = IsInterfaceAddress(ip_addresses, src); Log(LOG_LEVEL_DEBUG, "%ld: DNS packet from '%s' to '%s'", iteration, src, dest); if (isme_dest) { cf_this[ob_dns_in]++; IncrementCounter(&(NETIN_DIST[IP_TYPES_DNS]), src); } else if (isme_src) { cf_this[ob_dns_out]++; IncrementCounter(&(NETOUT_DIST[IP_TYPES_TCP_ACK]), dest); } } else if (strstr(arrival, "proto UDP")) { sscanf(arr, "%s %*c %s %c ", src, dest, &flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(ip_addresses, dest); isme_src = IsInterfaceAddress(ip_addresses, src); Log(LOG_LEVEL_DEBUG, "%ld: UDP packet from '%s' to '%s'", iteration, src, dest); if (isme_dest) { cf_this[ob_udp_in]++; IncrementCounter(&(NETIN_DIST[IP_TYPES_UDP]), src); } else if (isme_src) { cf_this[ob_udp_out]++; IncrementCounter(&(NETOUT_DIST[IP_TYPES_UDP]), dest); } } else if (strstr(arrival, "proto ICMP")) { sscanf(arr, "%s %*c %s %c ", src, dest, &flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(ip_addresses, dest); isme_src = IsInterfaceAddress(ip_addresses, src); Log(LOG_LEVEL_DEBUG, "%ld: ICMP packet from '%s' to '%s'", iteration, src, dest); if (isme_dest) { cf_this[ob_icmp_in]++; IncrementCounter(&(NETIN_DIST[IP_TYPES_ICMP]), src); } else if (isme_src) { cf_this[ob_icmp_out]++; IncrementCounter(&(NETOUT_DIST[IP_TYPES_ICMP]), src); } } else { Log(LOG_LEVEL_DEBUG, "%ld: Miscellaneous undirected packet (%.100s)", iteration, arrival); cf_this[ob_tcpmisc_in]++; /* Here we don't know what source will be, but .... */ sscanf(arrival, "%s", src); if (!isdigit((int) *src)) { Log(LOG_LEVEL_DEBUG, "Assuming continuation line..."); return; } DePort(src); if (strstr(arrival, ".138")) { snprintf(dest, CF_BUFSIZE - 1, "%s NETBIOS", src); } else if (strstr(arrival, ".2049")) { snprintf(dest, CF_BUFSIZE - 1, "%s NFS", src); } else { strncpy(dest, src, 60); dest[60] = '\0'; } IncrementCounter(&(NETIN_DIST[IP_TYPES_TCP_MISC]), dest); } } /******************************************************************************/ static void SaveTCPEntropyData(Item *list, int i, char *inout) { Item *ip; FILE *fp; char filename[CF_BUFSIZE]; Log(LOG_LEVEL_VERBOSE, "TCP Save '%s'", TCPNAMES[i]); if (list == NULL) { Log(LOG_LEVEL_VERBOSE, "No %s-%s events", TCPNAMES[i], inout); return; } if (strncmp(inout, "in", 2) == 0) { snprintf(filename, CF_BUFSIZE - 1, "%s/state/cf_incoming.%s", CFWORKDIR, TCPNAMES[i]); } else { snprintf(filename, CF_BUFSIZE - 1, "%s/state/cf_outgoing.%s", CFWORKDIR, TCPNAMES[i]); } Log(LOG_LEVEL_VERBOSE, "TCP Save '%s'", filename); if ((fp = fopen(filename, "w")) == NULL) { Log(LOG_LEVEL_VERBOSE, "Unable to write datafile '%s'", filename); return; } for (ip = list; ip != NULL; ip = ip->next) { fprintf(fp, "%d %s\n", ip->counter, ip->name); } fclose(fp); } /******************************************************************************/ void MonNetworkSnifferGatherData(void) { int i; char vbuff[CF_BUFSIZE]; for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; double entropy; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save incoming '%s'", TCPNAMES[i]); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_incoming.%s", CFWORKDIR, TCPNAMES[i]); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(NETIN_DIST[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state %s is smaller, retaining old for 40 mins longer", TCPNAMES[i]); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETIN_DIST[i], i, "in"); entropy = MonEntropyCalculate(NETIN_DIST[i]); MonEntropyClassesSet(TCPNAMES[i], "in", entropy); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; } for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; double entropy; time_t now = time(NULL); Log(LOG_LEVEL_DEBUG, "save outgoing '%s'", TCPNAMES[i]); snprintf(vbuff, CF_MAXVARSIZE, "%s/state/cf_outgoing.%s", CFWORKDIR, TCPNAMES[i]); if (stat(vbuff, &statbuf) != -1) { if (ItemListSize(NETOUT_DIST[i]) < statbuf.st_size && now < statbuf.st_mtime + 40 * 60) { Log(LOG_LEVEL_VERBOSE, "New state '%s' is smaller, retaining old for 40 mins longer", TCPNAMES[i]); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETOUT_DIST[i], i, "out"); entropy = MonEntropyCalculate(NETOUT_DIST[i]); MonEntropyClassesSet(TCPNAMES[i], "out", entropy); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; } } void DePort(char *address) { char *sp, *chop, *fc = NULL, *fd = NULL, *ld = NULL; int ccount = 0, dcount = 0; /* Start looking for ethernet/ipv6 addresses */ for (sp = address; *sp != '\0'; sp++) { if (*sp == ':') { if (!fc) { fc = sp; } ccount++; } if (*sp == '.') { if (!fd) { fd = sp; } ld = sp; dcount++; } } if (!fd) { /* This does not look like an IP address+port, maybe ethernet */ return; } if (dcount == 4) { chop = ld; } else if ((dcount > 1) && (fc != NULL)) { chop = fc; } else if ((ccount > 1) && (fd != NULL)) { chop = fd; } else { /* Don't recognize address */ return; } if (chop < address + strlen(address)) { *chop = '\0'; } return; } cfengine-3.6.2/examples/0000775000175100017510000000000012413020724014627 5ustar00a10038a1003800000000000000cfengine-3.6.2/examples/isvariable.cf0000644000175100017510000000263512316547775017314 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "bla" string => "xyz.."; classes: "exists" expression => isvariable("bla"); reports: exists:: "Variable exists: \"$(bla)\".."; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Variable exists: "xyz..".. #@ ``` #+end_src cfengine-3.6.2/examples/countlinesmatching.cf0000644000175100017510000000262612316547775021071 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: # typically there is only one root user "no" int => countlinesmatching("root:.*","/etc/passwd"); reports: "Found $(no) lines matching"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found 1 lines matching #@ ``` #+end_src cfengine-3.6.2/examples/datastate.cf0000644000175100017510000000407412316547775017144 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { holder, test }; } bundle common holder { classes: "holderclass" expression => "any"; # will be global vars: "s" string => "Hello!"; "d" data => parsejson('[4,5,6]'); "list" slist => { "element1", "element2" }; } bundle agent test { vars: "state" data => datastate(); # all the variables in bundle "holder" defined as of the execution of datastate() will be here "holderstate" string => format("%S", "state[vars][holder]"); # all the classes defined as of the execution of datastate() will be here "allclasses" slist => getindices("state[classes]"); classes: "have_holderclass" expression => some("holderclass", allclasses); reports: "holder vars = $(holderstate)"; have_holderclass:: "I have the holder class"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: holder vars = {"list":["element1","element2"],"s":"Hello!","d":[4,5,6]} #@ R: I have the holder class #@ ``` #+end_src cfengine-3.6.2/examples/edit_passwd_file_basic.cf0000664000175100017510000000250512243421446021620 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "edit_passwd" }; } bundle agent edit_passwd { vars: "userset" slist => { "user1", "user2", "user3" }; files: "/etc/passwd" edit_line => set_user_field("mark","7","/set/this/shell"); "/etc/group" edit_line => append_user_field("root","4","@(main.userset)"); } cfengine-3.6.2/examples/parallel_exec.cf0000664000175100017510000000324112243421446017750 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple backgrounding - try this with background = true and false # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## body agent control { agentaccess => { "mark", "root" }; } ######################################################## bundle agent example { commands: "/bin/sleep 10" action => background; "/bin/sleep" args => "20", action => background; } ######################################################### body action background { background => "true"; } cfengine-3.6.2/examples/user_edit_method.cf0000664000175100017510000000365012243421446020477 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # body common control { bundlesequence => { "users" }; } body agent control { abortbundleclasses => { "ldap_fail" }; } #################################################################################### bundle agent users { vars: "users" slist => { "mark", "nakarin", "three" }; methods: "all" usebundle => fix_user("$(users)"); } ################################################################################### bundle agent fix_user(x) { classes: "ldap_fail" not => ldaparray("dat","ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(uid=$(x))","subtree","none"); files: "/tmp/passwd" create => "true", edit_line => fix_passwd("$(x)"); reports: !ldap_fail:: "Editing user $(x)"; } #################################################################################### bundle edit_line fix_passwd(x) { insert_lines: "Hello $(x),$(fix_user.dat[uid]),$(fix_user.dat[gecos])"; } cfengine-3.6.2/examples/container_key_iteration.cf0000644000175100017510000000556212352022221022053 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "animals" data => parsejson(' { "dog": { "legs": 4, "tail": true, "names": [ "Fido", "Cooper", "Sandy" ] }, "cat": { "legs": 4, "tail": true, "names": [ "Fluffy", "Snowball", "Tabby" ] }, "dolphin": { "legs": 0, "tail": true, "names": [ "Flipper", "Duffy" ] }, "hamster": { "legs": 4, "tail": true, "names": [ "Skullcrusher", "Kimmy", "Fluffadoo" ] }, }'); "keys_unsorted" slist => getindices("animals"); "keys" slist => sort(keys_unsorted, "lex"); "animals_$(keys)" data => mergedata("animals[$(keys)]"); methods: # pass the container and a key inside it "any" usebundle => analyze(@(animals), $(keys)); } bundle agent analyze(animals, a) { vars: "names" slist => getvalues("animals[$(a)][names]"); "names_str" string => format("%S", names); reports: "$(this.bundle): possible names for animal '$(a)': $(names_str)"; "$(this.bundle): describe animal '$(a)' => name = $(a), legs = $(animals[$(a)][legs]), tail = $(animals[$(a)][tail])"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: analyze: possible names for animal 'cat': { "Fluffy", "Snowball", "Tabby" } #@ R: analyze: describe animal 'cat' => name = cat, legs = 4, tail = true #@ R: analyze: possible names for animal 'dog': { "Fido", "Cooper", "Sandy" } #@ R: analyze: describe animal 'dog' => name = dog, legs = 4, tail = true #@ R: analyze: possible names for animal 'dolphin': { "Flipper", "Duffy" } #@ R: analyze: describe animal 'dolphin' => name = dolphin, legs = 0, tail = true #@ R: analyze: possible names for animal 'hamster': { "Skullcrusher", "Kimmy", "Fluffadoo" } #@ R: analyze: describe animal 'hamster' => name = hamster, legs = 4, tail = true #@ ``` #+end_src cfengine-3.6.2/examples/edit_passwd_file.cf0000664000175100017510000000425512243421446020463 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "addpasswd" }; } bundle agent addpasswd { vars: # want to set these values by the names of their array keys "pwd[mark]" string => "mark:x:1000:100:Mark Burgess:/home/mark:/bin/bash"; "pwd[fred]" string => "fred:x:1001:100:Right Said:/home/fred:/bin/bash"; "pwd[jane]" string => "jane:x:1002:100:Jane Doe:/home/jane:/bin/bash"; files: "/tmp/passwd" create => "true", edit_line => append_users_starting("addpasswd.pwd"); } ############################################################ # Library stuff ############################################################ bundle edit_line append_users_starting(v) { vars: "index" slist => getindices("$(v)"); classes: "add_$(index)" not => userexists("$(index)"); insert_lines: "$($(v)[$(index)])", ifvarclass => "add_$(index)"; } ############################################################ bundle edit_line append_groups_starting(v) { vars: "index" slist => getindices("$(v)"); classes: "add_$(index)" not => groupexists("$(index)"); insert_lines: "$($(v)[$(index)])", ifvarclass => "add_$(index)"; } cfengine-3.6.2/examples/id.cf0000664000175100017510000000510612243421446015546 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test of promise references # ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { vars: classes: files: "/home/mark/tmp/testcopy" handle => "update_rule", copy_from => mycopy("/home/mark/LapTop/words","127.0.0.1"), perms => system, depth_search => recurse("inf"); } ######################################################### body perms system { mode => "0644"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body copy_from mycopy(from,server) { source => "$(from)"; servers => { "$(server)" }; copy_backup => "true"; #/false/timestamp purge => "false"; type_check => "true"; force_ipv4 => "true"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "/home/mark/LapTop" handle => "update_rule", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/global_list_expansion.cf0000664000175100017510000000306512243421446021533 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Show access of external lists. # # - to pass lists globally, use a parameter to dereference them # body common control { bundlesequence => { hardening(@(va.tmpdirs)) }; } ######################################################### bundle common va { vars: "tmpdirs" slist => { "/tmp", "/var/tmp", "/usr/tmp" }; } ########################################################## bundle agent hardening(x) { classes: "ok" expression => "any"; vars: "other" slist => { "/tmp", "/var/tmp" }; reports: ok:: "Do $(x)"; "Other: $(other)"; } cfengine-3.6.2/examples/change_detect.cf0000664000175100017510000000326512243421446017733 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Change detect # ######################################################## #[%+%] body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp/web" # Directory to monitor for changes. changes => detect_all_change, depth_search => recurse("inf"); } ######################################################### body changes detect_all_change { report_changes => "all"; update_hashes => "true"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/intarray.cf0000664000175100017510000000234712243421446017007 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "dim_array" int => readstringarray("array_name","/tmp/array","#[^\n]*",":",10,4000); } cfengine-3.6.2/examples/filesize.cf0000644000175100017510000000305612316547775017003 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { example }; } bundle agent example { vars: # my own size! "exists" int => filesize("$(this.promise_filename)"); "nexists" int => filesize("/etc/passwdx"); reports: "File size $(exists)"; "Does not exist: $(nexists)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: File size 301 #@ R: Does not exist: $(nexists) #@ ``` #+end_src cfengine-3.6.2/examples/countclassesmatching.cf0000644000175100017510000000264512316547775021415 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: # this is anchored, so you need .* to match multiple things "num" int => countclassesmatching("cfengine"); reports: "Found $(num) classes matching"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found 1 classes matching #@ ``` #+end_src cfengine-3.6.2/examples/root_passwd.cf0000664000175100017510000000647612243421446017531 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # Root password distribution # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "SetRootPassword" }; } ######################################################## bundle common g { vars: "secret_keys_dir" string => "/tmp"; } ######################################################## bundle agent SetRootPassword { files: "/var/cfengine/ppkeys/rootpw.txt" copy_from => scp("$(fqhost)-root.txt","master_host.example.org"); # or $(pw_class)-root.txt # Test this on a copy "/tmp/shadow" edit_line => SetPasswd("root"); } ######################################################## bundle edit_line SetPasswd(user) { vars: # Assume this file contains a single string of the form :passwdhash: # with : delimiters to avoid end of line/file problems "gotpw" int => readstringarray("pw","$(sys.workdir)/ppkeys/root-pw.txt","#[^\n]*",":","3","200"); field_edits: "$(user).*" # Set field of the file to parameter # File has format root:HASH: or user:HASH: edit_field => col(":","2","$(pw[root][1])","set"); } ######################################################## bundle server passwords { vars: # Read a file of format # # classname: host1,host2,host4,IP-address,regex.*,etc # "pw_classes" int => readstringarray("acl","$(g.secret_keys_dir)/classes.txt","#[^\n]*",":","100","4000"); "each_pw_class" slist => getindices("acl"); access: "/secret/keys/$(each_pw_class)-root.txt" admit => splitstring("$(acl[$(each_pw_class)][1])" , ":" , "100"), ifencrypted => "true"; } ######################################## # Bodies ######################################## body edit_field col(split,col,newval,method) { field_separator => "$(split)"; select_field => "$(col)"; value_separator => ","; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "true"; allow_blank_fields => "true"; } ######################################## body copy_from scp(from,server) { source => "$(from)"; compare => "digest"; encrypt => "true"; verify => "true"; } cfengine-3.6.2/examples/some.cf0000644000175100017510000000700512352022221016100 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { classes: # This is an easy way to check if a list is empty, better than # expression => strcmp(length(x), "0") # Note that if you use length() or none() or every() they will # go through all the elements!!! some() returns as soon as any # element matches. "empty_x" not => some(".*", x); "empty_y" not => some(".*", y); "some11" expression => some("long string", test1); "some12" expression => some("none", test1); "some21" expression => some("long string", test2); "some22" expression => some("none", test2); vars: "x" slist => { "a", "b" }; "y" slist => { }; "test1" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "test2" data => parsejson('[1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three",]'); reports: empty_x:: "x has no elements"; empty_y:: "y has no elements"; any:: "The test1 list is $(test1)"; some11:: "some() test1 1 passed"; !some11:: "some() test1 1 failed"; some12:: "some() test1 2 failed"; !some12:: "some() test1 2 passed"; "The test2 list is $(test2)"; some21:: "some() test2 1 passed"; !some21:: "some() test2 1 failed"; some22:: "some() test2 2 failed"; !some22:: "some() test2 2 passed"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: y has no elements #@ R: The test1 list is 1 #@ R: The test1 list is 2 #@ R: The test1 list is 3 #@ R: The test1 list is one #@ R: The test1 list is two #@ R: The test1 list is three #@ R: The test1 list is long string #@ R: The test1 list is four #@ R: The test1 list is fix #@ R: The test1 list is six #@ R: some() test1 1 passed #@ R: some() test1 2 passed #@ R: The test2 list is 1 #@ R: The test2 list is 2 #@ R: The test2 list is 3 #@ R: The test2 list is one #@ R: The test2 list is two #@ R: The test2 list is three #@ R: The test2 list is long string #@ R: The test2 list is four #@ R: The test2 list is fix #@ R: The test2 list is six #@ R: some() test2 1 passed #@ R: some() test2 2 passed #@ ``` #+end_src cfengine-3.6.2/examples/rename.cf0000664000175100017510000000224412243421446016421 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => {"test"}; } bundle agent example { files: "/tmp/foo" rename => moveit; } body rename moveit { newname => "/tmp/foo_moved"; } cfengine-3.6.2/examples/orchestrate_delay_trigger.cf0000664000175100017510000000301712243421446022375 0ustar00a10038a1003800000000000000# # Time based orchestration # body common control { bundlesequence => { "example" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ########################################### bundle common orchestrate { vars: # Must have delay < reset_time "reset_time" int => "2"; "delay" int => "1"; } ########################################### bundle agent example { methods: "immediate" usebundle => one, classes => if_repaired_persist("countdown", "$(orchestrate.delay)"), ifvarclass => "!one"; "delayed" usebundle => two, ifvarclass => "one.!countdown"; reports: countdown:: "Counting down ... $(sys.date)"; } ########################################### bundle agent one { reports: "One = $(this.bundle) at $(sys.date)" classes => if_repaired_persist("$(this.bundle)", "$(orchestrate.reset_time)"), action => if_elapsed("0"); "Set class $(this.bundle)" ifvarclass => "$(this.bundle)"; } ########################################## bundle agent two { reports: "Two = $(this.bundle) at $(sys.date)" classes => if_repaired_persist("$(this.bundle)", "$(orchestrate.reset_time)"), action => if_elapsed("0"); "Set class $(this.bundle)" ifvarclass => "$(this.bundle)"; } ########################################### body classes if_repaired_persist(x,t) { promise_repaired => { "$(x)" }; persist_time => "$(t)"; } body classes cancel_persist(x) { cancel_repaired => { "$(x)" }; } cfengine-3.6.2/examples/readfile.cf0000644000175100017510000000317112316547775016742 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo alpha > /tmp/cfe_hostlist #@ echo beta >> /tmp/cfe_hostlist #@ echo gamma >> /tmp/cfe_hostlist #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "xxx" string => readfile( "/tmp/cfe_hostlist" , "5" ); reports: "first 5 characters of /tmp/cfe_hostlist: $(xxx)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: first 5 characters of /tmp/cfe_hostlist: alpha #@ ``` #+end_src cfengine-3.6.2/examples/pathtype.cf0000664000175100017510000000346612243421446017017 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple backgrounding # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp" -> "me" changes => tripwire, pathtype => "literal", depth_search => recurse("inf"); } ######################################################### body changes tripwire { hash => "md5"; report_changes => "all"; update_hashes => "true"; } ######################################################### body action background { background => "true"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/win_dns_client.cf0000664000175100017510000000164512243421446020155 0ustar00a10038a1003800000000000000# Ensures correct DNS settings for Windows DNS clients # Tested on: Windows Server 2003 32-bit, Windows Server 2008 R2 64-bit body common control { bundlesequence => { "windows_dns" }; } bundle agent windows_dns { vars: "dns_servers" string => "192.168.1.3 192.168.1.4"; "keys" string => execresult("$(sys.winsysdir)\reg.exe query HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces", "noshell"); "key_list" slist => splitstring("$(keys)", "\r\n", 50); databases: "$(key_list)" comment => "Ensure DNS client configuration is correct", handle => canonify("windows_dns_$(dns_servers)"), database_operation => "create", database_rows => { "NameServer,REG_SZ,$(dns_servers)" }, database_type => "ms_registry", ifvarclass => not( strcmp("$(key_list)", "" )); } cfengine-3.6.2/examples/orchestrate_dominoes2.cf0000664000175100017510000000540612243421446021457 0ustar00a10038a1003800000000000000############################################################ # # Dominoes # # This method works with either Community of Enterprise # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # ############################################################ body common control { bundlesequence => { "dominoes_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################################ bundle agent dominoes_symphony { methods: # We have to seed the beginning by creating the dominoes # /tmp/dominoes_localhost host1:: "dominoes" usebundle => hand_over("localhost","host1","overture"); host2:: "dominoes" usebundle => hand_over("host1","host2","first_movement"); host3:: "dominoes" usebundle => hand_over("host2","host3","second_movement"); host4:: "dominoes" usebundle => hand_over("host3","host4","final_movement"), classes => if_ok("finale"); reports: finale:: "The visitors book of the Dominoes method" printfile => visitors_book("/tmp/dominoes_host4"); } ############################################################ bundle agent hand_over(predecessor,myalias,method) { # This is a wrapper for the orchestration files: "/tmp/tip_the_dominoes" comment => "Wait for our cue or relay/conductor baton", copy_from => secure_cp("/tmp/dominoes_$(predecessor)","$(predecessor)"), classes => if_repaired("cue_action"); methods: cue_action:: "the music happens" comment => "One off activity", usebundle => $(method), classes => if_ok("pass_the_stick"); files: pass_the_stick:: "/tmp/tip_the_dominoes" comment => "Add our signature to the dominoes's tail", edit_line => append_if_no_line("Knocked over $(myalias) and did: $(method)"); "/tmp/dominoes_$(myalias)" comment => "Dominoes in position to be beamed up by next agent", copy_from => local_cp("/tmp/tip_the_dominoes"); } ############################################################ bundle agent overture { reports: "Singing the overture..."; } bundle agent first_movement { reports: "Singing the first adagio..."; } bundle agent second_movement { reports: "Singing second allegro..."; } bundle agent final_movement { reports: "Trumpets for the finale"; } ############################################################ bundle server access_rules() { access: "/tmp" admit => { "127.0.0.1" }; "did.*" resource_type => "context", admit => { "127.0.0.1" }; } body printfile visitors_book(file) { file_to_print => "$(file)"; number_of_lines => "10"; } cfengine-3.6.2/examples/getvariablemetatags.cf0000644000175100017510000000265512316547775021210 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "v" string => "myvalue", meta => { "mytag" }; "vtags" slist => getvariablemetatags("example.v"); reports: "Found tags: $(vtags)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found tags: source=promise #@ R: Found tags: mytag #@ ``` #+end_src cfengine-3.6.2/examples/readintrealstringlist.cf0000644000175100017510000000464712316547775021615 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo 1 > /tmp/cfe_list_ints #@ echo 2 >> /tmp/cfe_list_ints #@ echo 3 >> /tmp/cfe_list_ints #@ echo 1.1 > /tmp/cfe_list_reals #@ echo 2.2 >> /tmp/cfe_list_reals #@ echo 3 >> /tmp/cfe_list_reals #@ echo alpha > /tmp/cfe_list_strings #@ echo beta >> /tmp/cfe_list_strings #@ echo gamma >> /tmp/cfe_list_strings #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "integers" ilist => readintlist("/tmp/cfe_list_ints","#.*","[\n]",10,400); "strings" slist => readstringlist("/tmp/cfe_list_strings", "#.*", "\s", 10, 400); "reals" rlist => readreallist("/tmp/cfe_list_reals","#.*","[\n]",10,400); reports: "integers in /tmp/cfe_list_ints: $(integers)"; "strings in /tmp/cfe_list_strings: $(strings)"; "reals in /tmp/cfe_list_reals: $(reals)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: integers in /tmp/cfe_list_ints: 1 #@ R: integers in /tmp/cfe_list_ints: 2 #@ R: integers in /tmp/cfe_list_ints: 3 #@ R: strings in /tmp/cfe_list_strings: alpha #@ R: strings in /tmp/cfe_list_strings: beta #@ R: strings in /tmp/cfe_list_strings: gamma #@ R: reals in /tmp/cfe_list_reals: 1.1 #@ R: reals in /tmp/cfe_list_reals: 2.2 #@ R: reals in /tmp/cfe_list_reals: 3 #@ ``` #+end_src cfengine-3.6.2/examples/accessed_before.cf0000664000175100017510000000255712243421446020255 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Show the definition of classes by comparing timestamps # body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "do_it" and => { accessedbefore("/tmp/earlier","/tmp/later") }; reports: do_it:: "The earlier file has been accessed before the later"; } cfengine-3.6.2/examples/helloworld.cf0000664000175100017510000000216112243421446017323 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # Hard promises body common control { bundlesequence => { "hello" }; } # soft promises bundle agent hello { reports: "Hello world!"; } cfengine-3.6.2/examples/resolveconf.cf0000664000175100017510000000544312243421446017503 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Resolve conf # ####################################################### bundle common g # globals { vars: "searchlist" slist => { "search iu.hio.no", "search cfengine.com" }; "nameservers" slist => { "128.39.89.10", "128.39.74.16", "192.168.1.103" }; classes: "am_name_server" expression => reglist("@(nameservers)","$(sys.ipv4[eth1])"); } ####################################################### body common control { any:: bundlesequence => { "g", resolver(@(g.searchlist),@(g.nameservers)) }; domain => "iu.hio.no"; } ####################################################### bundle agent resolver(s,n) { files: # When passing parameters down, we have to refer to # a source context "$(sys.resolv)" # test on "/tmp/resolv.conf" # create => "true", edit_line => doresolv("@(this.s)","@(this.n)"), edit_defaults => reconstruct; # or edit_defaults => modify } ####################################################### # For the library ####################################################### bundle edit_line doresolv(s,n) { vars: "line" slist => { @(s), @(n) }; insert_lines: "$(line)"; } ####################################################### body edit_defaults reconstruct { empty_file_before_editing => "true"; edit_backup => "false"; max_file_size => "100000"; } ####################################################### body edit_defaults modify { empty_file_before_editing => "false"; edit_backup => "false"; max_file_size => "100000"; } cfengine-3.6.2/examples/log_private.cf0000664000175100017510000000266412243421446017473 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } bundle agent example { vars: "software" slist => { "/root/xyz", "/tmp/xyz" }; files: "$(software)" create => "true", action => logme("$(software)"); } # body action logme(x) { log_kept => "/tmp/private_keptlog.log"; log_failed => "/tmp/private_faillog.log"; log_repaired => "/tmp/private_replog.log"; log_string => "$(sys.date) $(x) promise status"; } cfengine-3.6.2/examples/package_bundles.cf0000644000175100017510000000634312316547775020302 0ustar00a10038a1003800000000000000# Copyright (C) CFengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # #+begin_src cfengine3 body common control { inputs => { "$(sys.libdir)/packages.cf" }; bundlesequence => { "runme" }; } bundle agent runme { methods: "nozip" usebundle => cfe_package_ensure_absent("zip"); # delete "pleasezip" usebundle => cfe_package_ensure_present("zip"); # add "latestzip" usebundle => cfe_package_ensure_upgrade("zip"); # add/update # add a package from a file with a specific selection method, # version, and architecture "addfilezip" usebundle => cfe_package_named_ensure_present("/mydir/zip.deb-or-rpm", "==", "3.0-7", ifelse("debian", "amd64", "x86_64")); # add a package with a specific selection method, version, and # architecture "addzip" usebundle => cfe_package_named_ensure_present("zip", "==", ifelse("redhat", "3.0-7", "2.99"), ifelse("debian", "amd64", "x86_64")); # add or update a package from a file with a specific selection # method, version, and architecture "upgradefilezip" usebundle => cfe_package_named_ensure_upgrade("/mydir/zip.deb-or-rpm", "==", "3.0-7", ifelse("debian", "amd64", "x86_64")); # add or update a package with a specific selection method, # version, and architecture "upgradezip" usebundle => cfe_package_named_ensure_upgrade("zip", "==", "3.0-7", ifelse("debian", "amd64", "x86_64")); } #+end_src cfengine-3.6.2/examples/sublist.cf0000644000175100017510000001012212316547775016646 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", }; "test_head9999" slist => sublist("test", "head", 9999); "test_head1" slist => sublist("test", "head", 1); "test_head0" slist => sublist("test", "head", 0); "test_tail9999" slist => sublist("test", "tail", 9999); "test_tail10" slist => sublist("test", "tail", 10); "test_tail2" slist => sublist("test", "tail", 2); "test_tail1" slist => sublist("test", "tail", 1); "test_tail0" slist => sublist("test", "tail", 0); reports: "The test list is $(test)"; "This line should not appear: $(test_head0)"; "The head(1) of the test list is $(test_head1)"; "The head(9999) of the test list is $(test_head9999)"; "This line should not appear: $(test_tail0)"; "The tail(1) of the test list is $(test_tail1)"; "The tail(10) of the test list is $(test_tail10)"; "The tail(2) of the test list is $(test_tail2)"; "The tail(9999) of the test list is $(test_tail9999)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test list is 1 #@ R: The test list is 2 #@ R: The test list is 3 #@ R: The test list is one #@ R: The test list is two #@ R: The test list is three #@ R: The test list is long string #@ R: The test list is four #@ R: The test list is fix #@ R: The test list is six #@ R: The head(1) of the test list is 1 #@ R: The head(9999) of the test list is 1 #@ R: The head(9999) of the test list is 2 #@ R: The head(9999) of the test list is 3 #@ R: The head(9999) of the test list is one #@ R: The head(9999) of the test list is two #@ R: The head(9999) of the test list is three #@ R: The head(9999) of the test list is long string #@ R: The head(9999) of the test list is four #@ R: The head(9999) of the test list is fix #@ R: The head(9999) of the test list is six #@ R: The tail(1) of the test list is six #@ R: The tail(10) of the test list is 1 #@ R: The tail(10) of the test list is 2 #@ R: The tail(10) of the test list is 3 #@ R: The tail(10) of the test list is one #@ R: The tail(10) of the test list is two #@ R: The tail(10) of the test list is three #@ R: The tail(10) of the test list is long string #@ R: The tail(10) of the test list is four #@ R: The tail(10) of the test list is fix #@ R: The tail(10) of the test list is six #@ R: The tail(2) of the test list is fix #@ R: The tail(2) of the test list is six #@ R: The tail(9999) of the test list is 1 #@ R: The tail(9999) of the test list is 2 #@ R: The tail(9999) of the test list is 3 #@ R: The tail(9999) of the test list is one #@ R: The tail(9999) of the test list is two #@ R: The tail(9999) of the test list is three #@ R: The tail(9999) of the test list is long string #@ R: The tail(9999) of the test list is four #@ R: The tail(9999) of the test list is fix #@ R: The tail(9999) of the test list is six #@ ``` #+end_src cfengine-3.6.2/examples/difference.cf0000644000175100017510000000471312332665147017254 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "a" slist => { 1,2,3,"x" }; "b" slist => { "x" }; # normal usage "diff_between_a_and_b" slist => difference(a, b); "diff_between_a_and_b_str" string => join(",", diff_between_a_and_b); # NOTE: advanced usage! "mylist1" slist => { "a", "b" }; "mylist2" slist => { "a", "b" }; "$(mylist1)_str" string => join(",", $(mylist1)); # Here we're going to really call difference(a,a) then difference(a,b) then difference(b,a) then difference(b,b) # We create a new variable for each difference!!! "diff_$(mylist1)_$(mylist2)" slist => difference($(mylist1), $(mylist2)); "diff_$(mylist1)_$(mylist2)_str" string => join(",", "diff_$(mylist1)_$(mylist2)"); reports: # normal usage "The difference between lists a and b is '$(diff_between_a_and_b_str)'"; # NOTE: advanced usage results! "The difference of list '$($(mylist1)_str)' with '$($(mylist2)_str)' is '$(diff_$(mylist1)_$(mylist2)_str)'"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The difference between lists a and b is '1,2,3' #@ R: The difference of list '1,2,3,x' with '1,2,3,x' is '' #@ R: The difference of list '1,2,3,x' with 'x' is '1,2,3' #@ R: The difference of list 'x' with '1,2,3,x' is '' #@ R: The difference of list 'x' with 'x' is '' #@ ``` #+end_src cfengine-3.6.2/examples/switchcase.cf0000664000175100017510000000217512243421446017312 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "test1", "test2" }; } ################################################## bundle agent test1 { classes: "default" expression => "any"; reports: linux:: "This is a linux box" classes => exclusive; solaris:: "This is a solaris box" classes => exclusive; default:: "This is something not worth mentioning specifically" classes => reset_default; } ################################################## bundle agent test2 { classes: "default" expression => "any"; reports: linux:: "This is another linux box" classes => exclusive; solaris:: "This is another solaris box" classes => exclusive; default:: "This is something else not worth mentioning specifically" classes => reset_default; } ########################################################## body classes exclusive { cancel_kept => { "default" }; cancel_notkept => { "default" }; cancel_repaired => { "default" }; } body classes reset_default { promise_kept => { "default" }; } cfengine-3.6.2/examples/server_callback.cf0000664000175100017510000000476012243421446020301 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-v] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; #fips_mode => "true"; } ######################################################## bundle agent example { vars: } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; call_collect_interval => "1"; # allowusers } ######################################################### bundle server access_rules() { access: # On the policy hub "collect_calls" resource_type => "query", admit => { "127.0.0.1" }; # On the isolated client in the field "delta" comment => "Grant access to cfengine hub to collect report deltas", resource_type => "query", admit => { "127.0.0.1" }; "full" comment => "Grant access to cfengine hub to collect full report dump", resource_type => "query", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/process_restart_basic.cf0000664000175100017510000000237212243421446021537 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "process_restart" }; } ######################################################### bundle agent process_restart { processes: "/usr/bin/daemon" restart_class => "launch"; commands: launch:: "/usr/bin/daemon"; } cfengine-3.6.2/examples/process_signalling.cf0000664000175100017510000000333412243421446021040 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test process restart # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { processes: "cfservd" process_count => up("cfservd"); cfservd_out_of_control:: "cfservd" signals => { "stop" , "term" }, restart_class => "start_cfserv"; commands: start_cfserv:: "/usr/local/sbin/cfservd"; } ######################################################## body process_count up(s) { match_range => "1,10"; # or irange("1","10"); out_of_range_define => { "$(s)_out_of_control" }; } cfengine-3.6.2/examples/reporting.cf0000664000175100017510000000277112243421446017170 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => {"cf_null"}; } body reporter control { reports => { # "audit", # "performance", # "all_locks", # "active_locks", # "hashes", # "classes", # "last_seen", #"monitor_now", #"monitor_history" #"monitor_summary" "compliance", "file_changes", "setuid" }; build_directory => "/home/mark/tmp/reports"; # html,xml,csv,text report_output => "html"; } cfengine-3.6.2/examples/pattern_and_edit.cf0000664000175100017510000000276012243421446020461 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => {"test"}; } ######################################################## bundle agent example { files: "/home/(.*)/testfile" create => "true", edit_line => AppendIfNoLine("key_$(match.1)"); } ######################################################## bundle edit_line AppendIfNoLine(x) { insert_lines: "Line $(x)" location => append; } ######################################################## body location append { before_after => "before"; } cfengine-3.6.2/examples/filenames.cf0000664000175100017510000000232612243421446017116 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # filenames # body common control { bundlesequence => { "example" }; } bundle agent example { files: "/etc/passwd" create => "true"; "C:\etc\passwd" create => "true"; "etc/passwd" create => "true"; } cfengine-3.6.2/examples/edit_template.cf0000664000175100017510000000050212243421446017765 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "main" }; } bundle agent main { vars: "here" string => "/home/a10004/LapTop/cfengine/core/examples"; "list" slist => { "one", "two", "three" }; files: "/tmp/output" create => "true", edit_template => "$(here)/input.edittemplate"; } cfengine-3.6.2/examples/select_class.cf0000664000175100017510000000243312243421446017616 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "g" }; } ################################# bundle common g { classes: "selection" select_class => { "one", "two" }; reports: one:: "One was selected"; two:: "Two was selected"; selection:: "A selection was made"; } cfengine-3.6.2/examples/reg_multiline.cf0000664000175100017510000000135512243421446020013 0ustar00a10038a1003800000000000000############################################# # Matching multiple lines in regexp (PCRE) ############################################## body common control { bundlesequence => { "example" }; } bundle agent example { vars: "data" string => "Something boring is written up here. This is the interesting part: KWYDK (know what you don't know)"; classes: # note the (?s) at the beginning of the pattern - this ensures newlines are matched by . "matched" expression => regextract("(?s).*: (.*)", "$(data)", "interesting"); reports: matched:: "This is interesting: \"$(interesting[1])\""; !matched:: "Nothing was interesting!"; } cfengine-3.6.2/examples/remotescalar.cf0000664000175100017510000000474412243421446017642 0ustar00a10038a1003800000000000000 # Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################################## # # Testing comms for remote orchestration # ######################################################################## body common control { bundlesequence => { "overture" }; inputs => { "libraries/cfengine_stdlib.cf" }; } body server control { allowconnects => { "127.0.0.1" , "::1",}; allowallconnects => { "127.0.0.1" , "::1", }; trustkeysfrom => { "127.0.0.1" , "::1",}; } ####################################################### bundle agent overture { vars: "remote" string => remotescalar("test_scalar","127.0.0.1","yes"); "know" string => hubknowledge("test_scalar"); "count_getty" string => hubknowledge("count_getty"); processes: # Use the enumerated library body to count hosts running getty "getty" comment => "Count this host if a job is matched", classes => enumerate("count_getty"); reports: "GOT remote scalar $(remote)"; "GOT knowedge scalar $(know)"; "GOT persistent scalar $(xyz)"; } ####################################################### bundle server access_rules() { access: "value of my test_scalar, can expand variables here - $(sys.host)" handle => "test_scalar", comment => "Grant access to contents of test_scalar VAR", resource_type => "literal", admit => { "127.0.0.1" }; "XYZ" resource_type => "variable", handle => "XYZ", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/edit_insert_fuzzylines.cf0000664000175100017510000000351712243421446021771 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Insert a number of lines with vague whitespace # ####################################################### body common control { any:: bundlesequence => { "insert" }; } ####################################################### bundle agent insert { vars: "v" string => " One potato"; files: "/tmp/test_insert" create => "true", edit_line => Insert("$(insert.v)"); } ####################################################### # For the library ####################################################### bundle edit_line Insert(name) { insert_lines: " $(name)" whitespace_policy => { "ignore_leading", "ignore_embedded" }; } ####################################################### body edit_defaults empty { empty_file_before_editing => "true"; } cfengine-3.6.2/examples/reglist.cf0000644000175100017510000000336212316547775016642 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "nameservers" slist => { "128.39.89.10", "128.39.74.16", "192.168.1.103", "10.132.51.66" }; classes: "am_name_server" expression => reglist(@(nameservers), "127\.0\.0\.1"); reports: am_name_server:: "127.0.0.1 is currently set as a nameserver"; !am_name_server:: "127.0.0.1 is NOT currently set as a nameserver"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: 127.0.0.1 is NOT currently set as a nameserver #@ ``` #+end_src cfengine-3.6.2/examples/grep.cf0000644000175100017510000000373212316547775016127 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "mylist" slist => { "One", "Two", "Three", "Four", "Five" }; "Tlist" slist => grep("T.*","mylist"); "empty_list" slist => grep("ive","mylist"); "datalist" data => parsejson('[1,2,3, "Tab", "chive"]'); "data_Tlist" slist => grep("T.*","datalist"); "data_empty_list" slist => grep("ive","datalist"); "todo" slist => { "mylist", "Tlist", "empty_list", "datalist", "data_Tlist", "data_empty_list" }; "$(todo)_str" string => format("%S", $(todo)); reports: "$(todo): $($(todo)_str)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: mylist: { "One", "Two", "Three", "Four", "Five" } #@ R: Tlist: { "Two", "Three" } #@ R: empty_list: { --empty-list-- } #@ R: datalist: [1,2,3,"Tab","chive"] #@ R: data_Tlist: { "Tab" } #@ R: data_empty_list: { --empty-list-- } #@ ``` #+end_src cfengine-3.6.2/examples/accumulated_time.cf0000664000175100017510000000343312243421446020460 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test processes # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { processes: ".*" process_count => anyprocs, process_select => proc_finder; reports: any_procs:: "Found processes in range"; } ######################################################## body process_select proc_finder { ttime_range => irange(accumulated(0,0,0,0,2,0),accumulated(0,0,0,0,20,0)); process_result => "ttime"; } ######################################################## body process_count anyprocs { match_range => "0,0"; out_of_range_define => { "any_procs" }; } cfengine-3.6.2/examples/parseintrealstringarray.cf0000644000175100017510000000320412316547775022143 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test(f) { vars: # Define data inline for convenience "table" string => "1:2 3:4 5:6"; "dim" int => parseintarray( "items", "$(table)", "\s*#[^\n]*", ":", "1000", "200000" ); "keys" slist => getindices("items"); "sorted_keys" slist => sort(keys, "int"); reports: "$(sorted_keys)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: 1 #@ R: 3 #@ R: 5 #@ ``` #+end_src cfengine-3.6.2/examples/dollar.cf0000664000175100017510000000247412243421446016434 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "some" expression => "any"; reports: some:: "The value of $(const.dollar)(const.dollar) is $(const.dollar)"; "But the value of \$(dollar) is \$(dollar)"; } cfengine-3.6.2/examples/host2ip.cf0000664000175100017510000000253212243421446016542 0ustar00a10038a1003800000000000000 # Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # host2ip function # ####################################################### body common control { bundlesequence => { "example" }; } ####################################################### bundle agent example { vars: "ip" string => host2ip("www.google.com"); reports: "IP address $(ip)"; } cfengine-3.6.2/examples/regline.cf0000664000175100017510000000312312243421446016574 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # Function regline(regex,file) ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/tmp/testfile" edit_line => test; } ######################################################## bundle edit_line test { classes: "ok" expression => regline(".*mark.*","$(edit.filename)"); reports: ok:: "File matched $(edit.filename)"; } cfengine-3.6.2/examples/process_matching3.cf0000664000175100017510000000337012243421446020566 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test processes # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { processes: ".*" process_select => proc_finder("a.*"), process_count => up("cfservd"); } ######################################################## body process_count up(s) { match_range => "1,10"; # or irange("1","10"); out_of_range_define => { "$(s)_out_of_control" }; } ######################################################## body process_select proc_finder(p) { stime_range => irange(ago("0","0","0","2","0","0"),now); process_result => "stime"; } cfengine-3.6.2/examples/stringarray.cf0000664000175100017510000000262312243421446017520 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "dim_array" int => readstringarray("array_name","/etc/passwd","#[^\n]*",":",10,4000); "idx" slist => getindices("array_name"); reports: "Index $(idx): [1]=$(array_name[$(idx)][1]),[2]=$(array_name[$(idx)][2])...[7]=$(array_name[$(idx)][6])"; } cfengine-3.6.2/examples/maplist.cf0000644000175100017510000000342612316547775016643 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle common g { vars: "otherlist" slist => { "x", "y", "z" }; } ####################################################### bundle agent example { vars: "oldlist" slist => { "a", "b", "c" }; "newlist1" slist => maplist("Element ($(this))","@(g.otherlist)"); "newlist2" slist => maplist("Element ($(this))",@(oldlist)); reports: "Transform: $(newlist1)"; "Transform: $(newlist2)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Transform: Element (x) #@ R: Transform: Element (y) #@ R: Transform: Element (z) #@ R: Transform: Element (a) #@ R: Transform: Element (b) #@ R: Transform: Element (c) #@ ``` #+end_src cfengine-3.6.2/examples/fileexists.cf0000644000175100017510000000305112316547775017343 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: # this.promise_filename has the currently-executed file, so it # better exist! "exists" expression => fileexists($(this.promise_filename)); "exists_etc_passwd" expression => fileexists("/etc/passwd"); reports: exists:: "I exist! I mean, file exists!"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: I exist! I mean, file exists! #@ ``` #+end_src cfengine-3.6.2/examples/edit_deletenotmatch.cf0000664000175100017510000000313512243421446021157 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test editfile # ######################################################## # # This assumes a file format like: # # [section 1] # # lines.... # # [section 2] # # lines... etc body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/tmp/passwd_excerpt" create => "true", edit_line => MarkNRoot; } ######################################################## bundle edit_line MarkNRoot { delete_lines: "mark.*|root.*" not_matching => "true"; } cfengine-3.6.2/examples/package_latest.cf0000664000175100017510000000072612243421446020124 0ustar00a10038a1003800000000000000# # Makes sure a package is installed at latest version. # Does not take any action if the package has already # reached the version given in package_version. # body common control { inputs => { "libraries/cfengine_stdlib.cf" }; bundlesequence => { "example" }; } bundle agent example { packages: "apache2" package_method => generic, package_version => "2.2.00", package_select => ">=", package_policy => "addupdate"; } cfengine-3.6.2/examples/method.cf0000664000175100017510000000270512243421446016434 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; version => "1.2.3"; } ########################################### bundle agent example { vars: "userlist" slist => { "mark", "jeang", "jonhenrik", "thomas", "eben" }; methods: "any" usebundle => subtest("$(userlist)"); } ########################################### bundle agent subtest(user) { commands: "/bin/echo Fix $(user)"; reports: "Finished doing stuff for $(user)"; } cfengine-3.6.2/examples/control_expand.cf0000664000175100017510000000361312243421446020172 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. bundle common g { classes: "softclass" expression => "any"; vars: "bundle" slist => { "bundle1", "bundle2", @(g.extra) }; any:: # default extra "extra" slist => { "bundle3" }, policy => "overridable"; softclass:: "extra" slist => { "bundle3", "bundle4" }, policy => "overridable"; } ############################################################## body common control { bundlesequence => { @(g.bundle) }; } ############################################################## bundle agent bundle1 { vars: "var1" string => "anything"; "bundle" slist => { @(g.bundle) }; reports: "$(bundle)"; } bundle agent bundle2 { classes: "ok" expression => isvariable("bundle1.var1"); reports: ok:: "Success"; } bundle agent bundle3 { reports: "Success extra..."; } bundle agent bundle4 { reports: "Success extra more..."; } cfengine-3.6.2/examples/win_registry.cf0000664000175100017510000000501312243421446017674 0ustar00a10038a1003800000000000000######################################################################### # # win_registry.cf - Windows Registry Management # ######################################################################### bundle agent win_registry { vars: "cache_keys" slist => { "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS" }; "reg_create" slist => { "value1,REG_SZ,this is the first value...", "value2,REG_SZ,...and this is the second!" }; "reg_delete" slist => { "value1" }; methods: # 1) Cfengine can cache and restore any part of the registry # "any" usebundle => registry_cache("@(win_registry.cache_keys)"); # "any" usebundle => registry_restore("@(win_registry.cache_keys)"); # 2) Registry settings may also be explicitly defined/deleted in policy # "any" usebundle => registry_define("HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine", "@(win_registry.reg_create)"); # "any" usebundle => registry_delete("HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine", "@(win_registry.reg_delete)"); } ######################################################################### bundle agent registry_cache(keys) { databases: windows:: "$(keys)" database_operation => "cache", database_type => "ms_registry", comment => "Save correct registry settings"; } ######################################################################### bundle agent registry_restore(keys) { databases: windows:: "$(keys)" database_operation => "restore", database_type => "ms_registry", comment => "Make sure correct registry settings are set, according to cached version"; } ######################################################################### bundle agent registry_define(key, contents) { databases: windows:: "$(key)" database_operation => "create", database_rows => { "$(contents)" } , database_type => "ms_registry", comment => "Explicitly define important registry settings"; } ######################################################################### bundle agent registry_delete(key, values) { databases: windows:: "$(key)" database_operation => "delete", database_columns => { "@(values)" } , database_type => "ms_registry", comment => "Remove unwanted registry values"; } cfengine-3.6.2/examples/bundle_return_values.cf0000664000175100017510000000100312243421446021371 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "example" }; } bundle agent example { methods: "any" usebundle => child, useresult => "my_return_var"; reports: "My return was: \"$(my_return_var[1])\" and \"$(my_return_var[2])\""; } bundle agent child { reports: # Map these indices into the useresult namespace "this is a return value" bundle_return_value_index => "1"; "this is another return value" bundle_return_value_index => "2"; } cfengine-3.6.2/examples/inherit.cf0000664000175100017510000000376412243421446016624 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # Inheritance of classes # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "parent" }; } ######################################################## bundle agent parent { classes: "parent_private" expression => "any"; methods: "any" usebundle => child, inherit => "true"; files: "/tmp/bla" create => "true", edit_line => edit_child, edit_defaults => inherit_all; } ######################################################## bundle agent child { reports: parent_private:: "Parent class is inherited"; !parent_private:: "Parent class is not inherited"; } # bundle edit_line edit_child { reports: parent_private:: "Parent editclass is inherited"; !parent_private:: "Parent editclass is not inherited"; } # body edit_defaults inherit_all { inherit => "true"; } cfengine-3.6.2/examples/vars.cf0000664000175100017510000000225112243421446016123 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => {"yes"}; } bundle agent yes { vars: "var" string => "/one/two/last1", comment => "This is a comment"; reports: "Test = $(var)"; } cfengine-3.6.2/examples/orchestrate_dominoes1.cf0000664000175100017510000000471512243421446021460 0ustar00a10038a1003800000000000000############################################################ # # Dominoes # # This method works with either Community of Enterprise # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # ############################################################ body common control { bundlesequence => { "dominoes_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################################ bundle agent dominoes_symphony { methods: # We have to seed the beginning by creating the dominoes # /tmp/dominoes_localhost host1:: "dominoes" usebundle => hand_over("localhost","host1","overture"); host2:: "dominoes" usebundle => hand_over("host1","host2","first movement"); host3:: "dominoes" usebundle => hand_over("host2","host3","second movement"); host4:: "dominoes" usebundle => hand_over("host3","host4","final movement"), classes => if_ok("finale"); reports: finale:: "The visitors book of the Dominoes method" printfile => visitors_book("/tmp/dominoes_host4"); } ############################################################ bundle agent hand_over(predecessor,myalias,method) { # This is a wrapper for the orchestration files: "/tmp/tip_the_dominoes" comment => "Wait for our cue or relay/conductor baton", copy_from => secure_cp("/tmp/dominoes_$(predecessor)","$(predecessor)"), classes => if_repaired("cue_action"); cue_action:: "/tmp/outcome_of_part" comment => "One off activity", create => "true", edit_line => append_if_no_line("Do something meaningful by calling $(method)"), classes => if_ok("pass_the_stick"); pass_the_stick:: "/tmp/tip_the_dominoes" comment => "Add our signature to the dominoes's tail", edit_line => append_if_no_line("Knocked over $(myalias) and did: $(method)"); "/tmp/dominoes_$(myalias)" comment => "Dominoes in position to be beamed up by next agent", copy_from => local_cp("/tmp/tip_the_dominoes"); } ############################################################ bundle server access_rules() { access: "/tmp" admit => { "127.0.0.1" }; "did.*" resource_type => "context", admit => { "127.0.0.1" }; } body printfile visitors_book(file) { file_to_print => "$(file)"; number_of_lines => "10"; } cfengine-3.6.2/examples/lsdir.cf0000644000175100017510000000272612332665147016301 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "listfiles" slist => lsdir("/etc", "(p.sswd|gr[ou]+p)", "true"); "sorted_listfiles" slist => sort(listfiles, "lex"); reports: "files in list: $(sorted_listfiles)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: files in list: /etc/group #@ R: files in list: /etc/passwd #@ ``` #+end_src cfengine-3.6.2/examples/varclass.cf0000664000175100017510000000241112243421446016764 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { commands: "/bin/echo This is linux" ifvarclass => "linux"; "/bin/echo This is solaris" ifvarclass => "solaris"; } cfengine-3.6.2/examples/hostsseen.cf0000664000175100017510000000226412243421446017167 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } bundle agent example { vars: "myhosts" slist => { hostsseen("inf","lastseen","address") }; reports: "Found client/peer: $(myhosts)"; } cfengine-3.6.2/examples/cf2_integration.cf0000664000175100017510000000315712243421446020233 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Cfagent 2 can be run as a command within cfengine 3 # so that cfagent 2 AND cfagent 3 can coexist # # It does not matter which versions of the daemons are run # but you must choose version 2 XOR version 3 # body common control { # Reads default # /var/cfengine/inputs/promises.cf # /var/cfengine/inputs/failsafe.cf bundlesequence => { "cfengine3", "cfengine2" }; } ########################################### bundle agent cfengine2 { commands: "/var/cfengine/bin/cfagent"; } ########################################### bundle agent cfengine3 { # Stuff commands: "/var/cfengine/bin/cf-agent"; } cfengine-3.6.2/examples/namespace_classes.cf0000664000175100017510000000116412400110676020616 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "xxx:globalclass", "main" }; inputs => { "namespace_class1.cf" }; } bundle agent main { classes: cfengine_3:: "local_default" expression => "any"; methods: "namespace demo" usebundle => xxx:localclass; reports: local_default:: "Got locally set class in default namespace"; xxx:xclass_local:: "Got remote set local class in xxx namespace (impossible)"; xxx:xclass_global:: "Got remote set global class in xxx namespace"; not_a_defined_class:: "test"; cfengine_3:: "Hard classes work everywhere - here too"; } cfengine-3.6.2/examples/orchestrate_chain2.cf0000664000175100017510000000464712243421446020732 0ustar00a10038a1003800000000000000############################################################ # # The self-healing tower: Anti-Dominoes # # This method works with either Community of Enterprise # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # ############################################################ body common control { bundlesequence => { "weak_dependency_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } body server control { allowconnects => { "127.0.0.1" , "::1", @(def.acl) }; allowallconnects => { "127.0.0.1" , "::1", @(def.acl) }; } ############################################################ bundle agent weak_dependency_symphony { methods: # We have to seed the beginning by creating the tower # /tmp/tower_localhost host1:: "tower" usebundle => tier1, classes => publish_ok("ok_O"); host2:: "tower" usebundle => tier2, classes => publish_ok("ok_1"); host3:: "tower" usebundle => tier3, classes => publish_ok("ok_2"); host4:: "tower" usebundle => tier4, classes => publish_ok("ok_f"); classes: ok_O:: # Wait for the methods, report on host1 only "check1" expression => remoteclassesmatching("ok.*","host2","yes","a"); "check2" expression => remoteclassesmatching("ok.*","host3","yes","a"); "check3" expression => remoteclassesmatching("ok.*","host4","yes","a"); reports: ok_O&a_ok_1&a_ok_2&a_ok_f:: "The Tower is standing"; !(ok_O&a_ok_1&a_ok_2&a_ok_f):: "The Tower is down"; } ############################################################ bundle agent tier1 { files: "/tmp/something_to_do_1" create => "true"; } bundle agent tier2 { files: "/tmp/something_to_do_2" create => "true"; } bundle agent tier3 { files: "/tmp/something_to_do_3" create => "true"; } bundle agent tier4 { files: "/tmp/something_to_do_4" create => "true"; } ############################################################ bundle server access_rules() { access: "ok.*" resource_type => "context", admit => { "127.0.0.1" }; } ############################################################ body classes publish_ok(x) { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; cancel_notkept => { "$(x)" }; persist_time => "5"; } cfengine-3.6.2/examples/orchestration_hostlist.cf0000664000175100017510000000334412243421446021771 0ustar00a10038a1003800000000000000# # Make list of hosts available to all clients, and use it on clients # in order to configure a sample monitoring application that checks # health of all clients. # # Sample application configuration file contents below, put this in # /var/cfengine/masterfiles/template_monitoring on the hub. # # --- # #monitor_hosts = $(orchestration_hostlist_use.host_string) # # --- # # Note that your copy_from statement in failsafe.cf or update.cf must # copy this file also (e.g. not only copy *.cf files in any file_select) body common control { inputs => { "libraries/cfengine_stdlib.cf" }; bundlesequence => { "orchestration_hostlist_update", "orchestration_hostlist_use"}; } bundle agent orchestration_hostlist_update { vars: am_policy_hub:: "host_list" slist => hostsseen("inf", "lastseen", "address"); files: am_policy_hub:: "$(sys.workdir)/masterfiles/host_list" comment => "Write the addresses of all hosts to a file", handle => "orchestration_hostlit_update_files_host_list_write", edit_line => insert_lines( "@(orchestration_hostlist_update.host_list)" ), create => "true", edit_defaults => empty; } bundle agent orchestration_hostlist_use { vars: "host_list" slist => readstringlist("$(sys.workdir)/inputs/host_list", "#.*", "\n", 1000, 40000); "host_string" string => join(", ", "host_list"); files: "/tmp/monitoring" comment => "Update application configuration to reflect all hosts on this hub", handle => "orchestration_read_files_host_list_configuration", edit_line => expand_template("$(sys.workdir)/inputs/template_monitoring"), create => "true", edit_defaults => empty; } cfengine-3.6.2/examples/reverse.cf0000644000175100017510000000367512316547775016653 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "one", "two", "three", }; "reversed" slist => reverse("test"); reports: "Original list is $(test)"; "The reversed list is $(reversed)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Original list is 1 #@ R: Original list is 2 #@ R: Original list is 3 #@ R: Original list is one #@ R: Original list is two #@ R: Original list is three #@ R: Original list is long string #@ R: The reversed list is three #@ R: The reversed list is two #@ R: The reversed list is one #@ R: The reversed list is long string #@ R: The reversed list is 3 #@ R: The reversed list is 2 #@ R: The reversed list is 1 #@ ``` #+end_src cfengine-3.6.2/examples/sort.cf0000664000175100017510000000743212243421446016145 0ustar00a10038a1003800000000000000#+begin_src cfengine3 body common control { bundlesequence => { test }; } bundle agent test { vars: "a" slist => { "b", "c", "a" }; "b" slist => { "100", "9", "10", "8.23" }; "c" slist => { }; "d" slist => { "", "a", "", "b" }; "e" slist => { "a", "1", "b" }; "ips" slist => { "100.200.100.0", "1.2.3.4", "9.7.5.1", "9", "9.7", "9.7.5", "", "-1", "where are the IP addresses?" }; "ipv6" slist => { "FE80:0000:0000:0000:0202:B3FF:FE1E:8329", "FE80::0202:B3FF:FE1E:8329", "::1", # the following should all be parsed as the same address and sorted together "2001:db8:0:0:1:0:0:1", "2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1", "2001:db8::0:1:0:0:1", "2001:0db8::1:0:0:1", "2001:db8:0:0:1::1", "2001:db8:0000:0:1::1", "2001:DB8:0:0:1::1", # note uppercase IPv6 addresses are invalid # examples from https://www.ripe.net/lir-services/new-lir/ipv6_reference_card.pdf "8000:63bf:3fff:fdd2", "::ffff:192.0.2.47", "fdf8:f53b:82e4::53", "fe80::200:5aee:feaa:20a2", "2001:0000:4136:e378:", "8000:63bf:3fff:fdd2", "2001:0002:6c::430", "2001:10:240:ab::a", "2002:cb0a:3cdd:1::1", "2001:db8:8:4::2", "ff01:0:0:0:0:0:0:2", "-1", "where are the IP addresses?" }; "macs" slist => { "00:14:BF:F7:23:1D", "0:14:BF:F7:23:1D", ":14:BF:F7:23:1D", "00:014:BF:0F7:23:01D", "00:14:BF:F7:23:1D", "0:14:BF:F7:23:1D", ":14:BF:F7:23:1D", "00:014:BF:0F7:23:01D", "01:14:BF:F7:23:1D", "1:14:BF:F7:23:1D", "01:14:BF:F7:23:2D", "1:14:BF:F7:23:2D", "-1", "where are the MAC addresses?" }; "ja" string => join(",", "a"); "jb" string => join(",", "b"); "jc" string => join(",", "c"); "jd" string => join(",", "d"); "je" string => join(",", "e"); "jips" string => join(",", "ips"); "jipv6" string => join(",", "ipv6"); "jmacs" string => join(",", "macs"); "sa" slist => sort("a", "lex"); "sb" slist => sort("b", "lex"); "sc" slist => sort("c", "lex"); "sd" slist => sort("d", "lex"); "se" slist => sort("e", "lex"); "sb_int" slist => sort("b", "int"); "sb_real" slist => sort("b", "real"); "sips" slist => sort("ips", "ip"); "sipv6" slist => sort("ipv6", "ip"); "smacs" slist => sort("macs", "mac"); "jsa" string => join(",", "sa"); "jsb" string => join(",", "sb"); "jsc" string => join(",", "sc"); "jsd" string => join(",", "sd"); "jse" string => join(",", "se"); "jsb_int" string => join(",", "sb_int"); "jsb_real" string => join(",", "sb_real"); "jsips" string => join(",", "sips"); "jsipv6" string => join(",", "sipv6"); "jsmacs" string => join(",", "smacs"); reports: "sorted lexicographically '$(ja)' => '$(jsa)'"; "sorted lexicographically '$(jb)' => '$(jsb)'"; "sorted lexicographically '$(jc)' => '$(jsc)'"; "sorted lexicographically '$(jd)' => '$(jsd)'"; "sorted lexicographically '$(je)' => '$(jse)'"; "sorted integers '$(jb)' => '$(jsb_int)'"; "sorted reals '$(jb)' => '$(jsb_real)'"; "sorted IPs '$(jips)' => '$(jsips)'"; "sorted IPv6s '$(jipv6)' => '$(jsipv6)'"; "sorted MACs '$(jmacs)' => '$(jsmacs)'"; } #+end_src cfengine-3.6.2/examples/every.cf0000644000175100017510000000764112316547775016327 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { classes: "every_dot_star" expression => every(".*", test); "every_dot" expression => every(".", test); "every_number" expression => every("[0-9]", test); "every2_dot_star" expression => every(".*", test2); "every2_dot" expression => every(".", test2); "every2_number" expression => every("[0-9]", test2); vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "test2" data => parsejson('[1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three",]'); reports: "The test list is $(test)"; every_dot_star:: "every() test passed: every element matches '.*'"; !every_dot_star:: "every() test failed: not every element matches '.*'"; every_number:: "every() test failed: every element matches '[0-9]'"; !every_number:: "every() test passed: not every element matches '[0-9]'"; every_dot:: "every() test failed: every element matches '.'"; !every_dot:: "every() test passed: not every element matches '.'"; "The test2 list is $(test2)"; every2_dot_star:: "every() test2 passed: every element matches '.*'"; !every2_dot_star:: "every() test2 failed: not every element matches '.*'"; every2_number:: "every() test2 failed: every element matches '[0-9]'"; !every2_number:: "every() test2 passed: not every element matches '[0-9]'"; every2_dot:: "every() test2 failed: every element matches '.'"; !every2_dot:: "every() test2 passed: not every element matches '.'"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test list is 1 #@ R: The test list is 2 #@ R: The test list is 3 #@ R: The test list is one #@ R: The test list is two #@ R: The test list is three #@ R: The test list is long string #@ R: The test list is four #@ R: The test list is fix #@ R: The test list is six #@ R: every() test passed: every element matches '.*' #@ R: every() test passed: not every element matches '[0-9]' #@ R: every() test passed: not every element matches '.' #@ R: The test2 list is 1 #@ R: The test2 list is 2 #@ R: The test2 list is 3 #@ R: The test2 list is one #@ R: The test2 list is two #@ R: The test2 list is three #@ R: The test2 list is long string #@ R: The test2 list is four #@ R: The test2 list is fix #@ R: The test2 list is six #@ R: every() test2 passed: every element matches '.*' #@ R: every() test2 passed: not every element matches '[0-9]' #@ R: every() test2 passed: not every element matches '.' #@ ``` #+end_src cfengine-3.6.2/examples/select_size.cf0000664000175100017510000000274312243421446017467 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } # bundle agent example { files: # Show files in range "/home/mark/tmp" file_select => name_and_sizes(".*cf","100","300"), depth_search => recurse("1"), transformer => "/bin/ls -l $(this.promiser)"; } # body file_select name_and_sizes(n,x,y) { leaf_name => { "$(n)" }; search_size => irange("$(x)", "$(y)"); file_result => "leaf_name&size"; } body depth_search recurse(x) { depth => "$(x)"; } cfengine-3.6.2/examples/package_zypper.cf0000664000175100017510000000275312243421446020163 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Package managment # body common control { bundlesequence => { "packages" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################# bundle agent packages { vars: # Test the simplest case -- leave everything to the zypper smart manager "match_package" slist => { "apache2", "apache2-mod_php5", "apache2-prefork", "php5" }; packages: "$(match_package)" package_policy => "add", package_method => zypper; } cfengine-3.6.2/examples/ordering.cf0000664000175100017510000000352312243421446016764 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ################################################################## # # cfengine 3 - ordering promises into dependent chains # ## # # cf-agent -f ./cftest.cf -K # ################################################################## body common control { bundlesequence => { "order" }; } ################################################################## bundle agent order { vars: "list" slist => { "three", "four" }; commands: ok_later:: "/bin/echo five"; otherthing:: "/bin/echo six"; any:: "/bin/echo one" classes => d("ok_later","otherthing"); "/bin/echo two"; "/bin/echo $(list)"; preserved_class:: "/bin/echo seven"; } ############################################ body classes d(if,else) { promise_repaired => { "$(if)" }; repair_failed => { "$(else)" }; persist_time => "0"; } cfengine-3.6.2/examples/getvalues.cf0000644000175100017510000000350012352022221017130 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "v[index_1]" string => "value_1"; "v[index_2]" string => "value_2"; "values" slist => getvalues("v"); # works with data containers too "d" data => parsejson('{ "k": [ 1, 2, 3, "a", "b", "c" ] }'); "cvalues" slist => getvalues("d[k]"); reports: "Found values: $(values)"; "Found container values: $(cvalues)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found values: value_2 #@ R: Found values: value_1 #@ R: Found container values: 1 #@ R: Found container values: 2 #@ R: Found container values: 3 #@ R: Found container values: a #@ R: Found container values: b #@ R: Found container values: c #@ ``` #+end_src cfengine-3.6.2/examples/getclassmetatags.cf0000644000175100017510000000265612316547775020531 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "c" expression => "any", meta => { "mytag" }; vars: "ctags" slist => getclassmetatags("c"); reports: "Found tags: $(ctags)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found tags: source=promise #@ R: Found tags: mytag #@ ``` #+end_src cfengine-3.6.2/examples/filestat.cf0000644000175100017510000000547112316547775017007 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo 1234567890 > FILE.txt #@ chmod 0755 FILE.txt #@ chown 0 FILE.txt #@ chgrp 0 FILE.txt #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "file" string => "$(this.promise_filename).txt"; methods: "fileinfo" usebundle => fileinfo("$(file)"); } bundle agent fileinfo(f) { vars: # use the full list if you want to see all the attributes! # "fields" slist => splitstring("size,gid,uid,ino,nlink,ctime,atime,mtime,mode,modeoct,permstr,permoct,type,devno,dev_minor,dev_major,basename,dirname,linktarget,linktarget_shallow", ",", 999); # ino (inode number), ctime (creation time), # devno/dev_minor/dev_major (device numbers) were omitted but # they are all integers "fields" slist => splitstring("size,gid,uid,nlink,mode,modeoct,permstr,permoct,type,basename", ",", 999); "stat[$(f)][$(fields)]" string => filestat($(f), $(fields)); reports: "$(this.bundle): file $(stat[$(f)][basename]) has $(fields) = $(stat[$(f)][$(fields)])"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: fileinfo: file filestat.cf.txt has size = 11 #@ R: fileinfo: file filestat.cf.txt has gid = 0 #@ R: fileinfo: file filestat.cf.txt has uid = 0 #@ R: fileinfo: file filestat.cf.txt has nlink = 1 #@ R: fileinfo: file filestat.cf.txt has mode = 33261 #@ R: fileinfo: file filestat.cf.txt has modeoct = 100755 #@ R: fileinfo: file filestat.cf.txt has permstr = -rwxr-xr-x #@ R: fileinfo: file filestat.cf.txt has permoct = 755 #@ R: fileinfo: file filestat.cf.txt has type = regular file #@ R: fileinfo: file filestat.cf.txt has basename = filestat.cf.txt #@ ``` #+end_src cfengine-3.6.2/examples/package_yum.cf0000664000175100017510000000274512243421446017445 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Package managment # body common control { bundlesequence => { "packages" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################# bundle agent packages { vars: # Test the simplest case -- leave everything to the yum smart manager "match_package" slist => { "apache2", "apache2-mod_php5", "apache2-prefork", "php5" }; packages: "$(match_package)" package_policy => "add", package_method => yum; } cfengine-3.6.2/examples/iteration.cf0000664000175100017510000000240012243421446017142 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Nested iteration # body common control { bundlesequence => {"x"}; } bundle agent x { vars: "list1" slist => { "a", "b", "c" }; "list2" slist => { "1", "2", "3", "4" }; "list3" slist => { "x", "y", "z" }; reports: "Hello $(list1) $(list2) $(list3)"; } cfengine-3.6.2/examples/server_copy_localhost.cf0000664000175100017510000000645312243421446021570 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-v] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; #fips_mode => "true"; } ######################################################## bundle agent example { files: "/tmp/testcopy" comment => "test copy promise", copy_from => mycopy("/tmp/test-src","127.0.0.1"), perms => system, depth_search => recurse("inf"), classes => satisfied("copy_ok"); "/tmp/testcopy/single_file" comment => "test copy promise", copy_from => mycopy("/tmp/test-src/README","127.0.0.1"), perms => system; reports: copy_ok:: "Files were copied.."; } ######################################################### body perms system { mode => "0644"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body copy_from mycopy(from,server) { source => "$(from)"; servers => { "$(server)" }; compare => "digest"; encrypt => "true"; verify => "true"; copy_backup => "true"; #/false/timestamp purge => "false"; type_check => "true"; force_ipv4 => "true"; trustkey => "true"; } ######################################################### body classes satisfied(x) { promise_repaired => { "$(x)" }; persist_time => "0"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; # allowusers } ######################################################### bundle server access_rules() { access: "/tmp/test-src" admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/syslog2.cf0000664000175100017510000000100212243421446016543 0ustar00a10038a1003800000000000000# # With Nova, log directly to a central server -- careful of scalability (UDP) # body common control { bundlesequence => { "example" }; syslog_host => "loghost.example.org"; } # bundle agent example { vars: "software" slist => { "/root/xyz", "/tmp/xyz" }; files: "$(software)" create => "true", action => logme("$(software)"); } # body action logme(x) { log_repaired => "udp_syslog"; log_string => "cfengine repaired promise $(this.handle) - $(x)"; } cfengine-3.6.2/examples/hashcomment.cf0000664000175100017510000000354212243421446017462 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # Comment lines # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp/comment_test" create => "true", edit_line => comment_lines_matching; } ######################################################## bundle edit_line comment_lines_matching { vars: "regexes" slist => { "one.*", "two.*", "four.*" }; replace_patterns: "^($(regexes))$" replace_with => comment("# "); } ######################################## # Bodies ######################################## body replace_with comment(c) { replace_value => "$(c) $(match.1)"; occurrences => "all"; } cfengine-3.6.2/examples/namespace_class1.cf0000664000175100017510000000062512243421446020355 0ustar00a10038a1003800000000000000 body file control { namespace => "xxx"; } bundle common globalclass { classes: "xclass_global" expression => "any"; reports: xclass_global:: "!!!!!!!!!!!!"; } bundle agent localclass { classes: "xclass_local" expression => "any"; reports: xclass_global:: "Local classes in the namespace work"; "Hard classes work everywhere - like here"; } cfengine-3.6.2/examples/copy_classes.cf0000664000175100017510000000510212243421446017635 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "copy_file"}; inputs => {"libraries/cfengine_stdlib.cf"}; } ###################################################### bundle agent copy_file() { files: "/tmp/non_existent" copy_from => local_cp_compare("/non_existent"), # perms => m("777"), action => warn_only, classes => check_promises("NE_NE"); "/tmp/non_existent" copy_from => local_cp_compare("/tmp/existent_file"), # perms => m("777"), action => warn_only, classes => check_promises("NE_E"); "/tmp/existent_file" copy_from => local_cp_compare("/tmp/existent_file"), # perms => m("777"), action => warn_only, classes => check_promises("E_E"); "/tmp/existent_file" copy_from => local_cp_compare("/tmp/different_file"), # perms => m("777"), action => warn_only, classes => check_promises("D_E"); "/tmp/existent_file" copy_from => local_cp_compare("/non_existent"), # perms => m("777"), action => warn_only, classes => check_promises("E_NE"); reports: NE_NE_kept:: "NE_NE_kept"; NE_NE_repaired:: "NE_NE_repaired"; NE_NE_failed:: "NE_NE_failed"; NE_NE_denied:: "NE_NE_denied"; NE_NE_timeout:: "NE_NE_timeout"; NE_E_kept:: "NE_E_kept"; NE_E_repaired:: "NE_E_repaired"; NE_E_failed:: "NE_E_failed"; NE_E_denied:: "NE_E_denied"; NE_E_timeout:: "NE_E_timeout"; E_E_kept:: "E_E_kept"; E_E_repaired:: "E_E_repaired"; E_E_failed:: "E_E_failed"; E_E_denied:: "E_E_denied"; E_E_timeout:: "E_E_timeout"; D_E_kept:: "D_E_kept"; D_E_repaired:: "D_E_repaired"; D_E_failed:: "D_E_failed"; D_E_denied:: "D_E_denied"; D_E_timeout:: "D_E_timeout"; E_NE_kept:: "E_NE_kept"; E_NE_repaired:: "E_NE_repaired"; E_NE_failed:: "E_NE_failed"; E_NE_denied:: "E_NE_denied"; E_NE_timeout:: "E_NE_timeout"; } ###################################################### body classes check_promises(prom) { promise_kept => { "$(prom)_kept" }; promise_repaired => { "$(prom)_repaired" }; repair_failed => { "$(prom)_failed" }; repair_denied => { "$(prom)_denied" }; repair_timeout => { "$(prom)_timeout" }; } ###################################################### body copy_from local_cp_compare(from) { source => "$(from)"; verify => "true"; compare => "hash"; } cfengine-3.6.2/examples/namespace_var_meta2.cf0000664000175100017510000000054612243421446021051 0ustar00a10038a1003800000000000000 body file control { namespace => "fred"; } bundle agent example { vars: "bundle_version" string => "4.5.6"; meta: "bundle_version" string => "1.2.3"; "works_with_cfengine" string => "3.4.0"; reports: "Not a local variable: $(bundle_version)"; "Meta data (variable): $(example_meta.bundle_version)"; } cfengine-3.6.2/examples/edit_triggerclass.cf0000664000175100017510000000427712243421446020660 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Insert a number of lines and trigger a followup if edited # ####################################################### body common control { any:: bundlesequence => { "insert" }; } ####################################################### bundle agent insert { vars: "v" string => " One potato Two potato Three potahto Four "; files: "/tmp/test_insert" edit_line => Insert("$(insert.v)"), edit_defaults => empty, classes => trigger("edited"); commands: edited:: "/bin/echo make bananas"; reports: edited:: "The potatoes are bananas"; } ####################################################### # For the library ####################################################### bundle edit_line Insert(name) { insert_lines: "Begin$(const.n) $(name)$(const.n)End"; } ####################################################### body edit_defaults empty { empty_file_before_editing => "true"; } ####################################################### body classes trigger(x) { promise_repaired => { "$(x)" }; } cfengine-3.6.2/examples/nth.cf0000644000175100017510000000634712316547775015770 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "test_str" string => format("%S", test); "test2" data => parsejson("[1, 2, 3, null]"); "test2_str" string => format("%S", test2); "test3" data => parsejson('{ "x": true, "y": "z" }'); "test3_str" string => format("%S", test3); "nth" slist => { 1, 2, 6, 10, 11, 1000 }; "nth2" slist => getindices(test2); "nth3" slist => getindices(test3); "access[$(nth)]" string => nth(test, $(nth)); "access[0]" string => nth(test, 0); "access2[$(nth2)]" string => nth(test2, $(nth2)); "access3[$(nth3)]" string => nth(test3, $(nth3)); reports: "The test list is $(test_str)"; "element #$(nth) of the test list: $(access[$(nth)])"; "element #0 of the test list: $(access[0])"; "The test2 data container is $(test2_str)"; "element #$(nth2) of the test2 data container: $(access2[$(nth2)])"; "The test3 data container is $(test3_str)"; "element #$(nth3) of the test3 data container: $(access3[$(nth3)])"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test list is { "1", "2", "3", "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three" } #@ R: element #1 of the test list: 2 #@ R: element #2 of the test list: 3 #@ R: element #6 of the test list: long string #@ R: element #10 of the test list: one #@ R: element #11 of the test list: two #@ R: element #1000 of the test list: $(access[1000]) #@ R: element #0 of the test list: 1 #@ R: The test2 data container is [1,2,3,null] #@ R: element #0 of the test2 data container: 1 #@ R: element #1 of the test2 data container: 2 #@ R: element #2 of the test2 data container: 3 #@ R: element #3 of the test2 data container: null #@ R: The test3 data container is {"x":true,"y":"z"} #@ R: element #x of the test3 data container: true #@ R: element #y of the test3 data container: z #@ ``` #+end_src cfengine-3.6.2/examples/canonify.cf0000644000175100017510000000267412316547775017004 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "component" string => "/var/cfengine/bin/cf-serverd"; "canon" string => canonify("$(component)"); reports: "canonified component == $(canon)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: canonified component == _var_cfengine_bin_cf_serverd #@ ``` #+end_src cfengine-3.6.2/examples/package_solaris.cf0000664000175100017510000000332112243421446020276 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Package managment # body common control { bundlesequence => { "packages" }; inputs => { "cfengine_stdlb.cf" }; } ############################################# bundle agent packages { vars: "solaris_packages[SMCzlib]" string => "zlib-1.2.3-sol10-sparc-local"; "admin_file" string => "cfengine_admin_file"; "package_names" slist => getindices("solaris_packages"); files: "/tmp/$(admin_file)" create => "true", edit_defaults => empty_file, edit_line => create_solaris_admin_file; packages: "$(package_names)" package_policy => "add", package_method => solaris("$(package_names)", "$(solaris_packages[$(package_names)])", "$(admin_file)"); } cfengine-3.6.2/examples/fix_names.cf0000664000175100017510000000350712243421446017126 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # File editing # # Normal ordering: # - delete # - replace | colum_edit # - insert # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/LapTop/Cfengine3/trunk/src/.*\.[ch]" edit_line => change_name; } ######################################################## bundle edit_line change_name { replace_patterns: "Verbose\(" replace_with => With("CfOut(cf_verbose,\"\","); } ######################################## # Bodies ######################################## body replace_with With(x) { replace_value => "$(x)"; occurrences => "all"; } cfengine-3.6.2/examples/software_dist.cf0000664000175100017510000001461212243421446020031 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################################### # # software_local.cf - Application Deployment From Directory Repository # # NOTE: Windows needs to support WMI queries about installed msi files # in order for Cfengine to detect them. On Windows 2003, # go to Control Panel -> Add/Remove Programs -> # Windows Components -> Mgmnt and Monitoring Tools and check # WMI Windows Installer Provider. # # NOTE: Naming conventions are important when updating packages. # By default, Cfengine expects "name-version-arch.msi" # on Windows, where name is lowercase, and arch is # i686 or x86_64. No spaces should be included in the filename. # The Caption and Version fields inside the msi package # are important. They must correspond to the file name as # follows: name = lowercase(spacetodash(Caption)), # version = Version. For any msi-file, use InstEd # (www.instedit.com) to check/modify the # Caption and Version fields # (Tables->Property->ProductName/ProductVersion). # # For example, ProductName "CFEngine Nova" with ProductVersion # "1.1.2" for 32-bit Windows will correspond to the filename # "cfengine-nova-1.1.2-i686.msi". # ######################################################################### bundle agent check_software { vars: # software to install if not installed "include_software" slist => { "7-zip-4.50-$(sys.arch).msi" }; # this software gets updated if it is installed "autoupdate_software" slist => { "7-zip" }; # software to uninstall if it is installed "exclude_software" slist => { "7-zip-4.65-$(sys.arch).msi" }; methods: # "any" usebundle => add_software( "@(check_software.include_software)", "$(sys.policy_hub)" ); # "any" usebundle => update_software( "@(check_software.autoupdate_software)", "$(sys.policy_hub)" ); # "any" usebundle => remove_software( "@(check_software.exclude_software)", "$(sys.policy_hub)" ); } ######################################################################### bundle agent add_software(pkg_name, srv) { vars: # dir to install from locally - can also check multiple directories "local_software_dir" string => "C:\Program Files\Cfengine\software\add"; files: "$(local_software_dir)" copy_from => remote_cp("/var/cfengine/master_software_updates/$(sys.flavour)_$(sys.arch)/add", "$(srv)"), depth_search => recurse("1"), classes => if_repaired("got_newpkg"), comment => "Copy software from remote repository"; packages: # When to check if the package is installed ? got_newpkg|any:: "$(pkg_name)" package_policy => "add", package_method => msi_implicit( "$(local_software_dir)" ), classes => if_else("add_success", "add_fail" ), comment => "Install new software, if not already present"; reports:: add_fail:: "Failed to install one or more packages"; } ######################################################################### bundle agent update_software(sw_names, srv) { vars: # dir to install from locally - can also check multiple directories "local_software_dir" string => "C:\Program Files\Cfengine\software\update"; files: "$(local_software_dir)" copy_from => remote_cp("/var/cfengine/master_software_updates/$(sys.flavour)_$(sys.arch)/update", "$(srv)"), depth_search => recurse("1"), classes => if_repaired("got_newpkg"), comment => "Copy software updates from remote repository"; packages: # When to check if the package is updated ? got_newpkg|any:: "$(sw_names)" package_policy => "update", package_select => ">=", # picks the newest update available package_architectures => { "$(sys.arch)" }, # install 32 or 64 bit package ? package_version => "1.0", # at least version 1.0 package_method => msi_explicit( "$(local_software_dir)" ), classes => if_else("update_success", "update_fail"); reports:: update_fail:: "Failed to update one or more packages"; } ######################################################################### bundle agent remove_software(pkg_name, srv) { vars: # dir to install from locally - can also check multiple directories "local_software_dir" string => "C:\Program Files\Cfengine\software\remove"; files: "$(local_software_dir)" copy_from => remote_cp("/var/cfengine/master_software_updates/$(sys.flavour)_$(sys.arch)/remove", "$(srv)"), depth_search => recurse("1"), classes => if_repaired("got_newpkg"), comment => "Copy removable software from remote repository"; packages: got_newpkg:: "$(pkg_name)" package_policy => "delete", package_method => msi_implicit( "$(local_software_dir)" ), classes => if_else("remove_success", "remove_fail" ), comment => "Remove software, if present"; reports:: remove_fail:: "Failed to remove one or more packages"; } cfengine-3.6.2/examples/insert_users.cf0000664000175100017510000000602112243421446017674 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Insert users into the passwd file of a system by # extracting named users from a master file - repeat # for /etc/shadow # ######################################################## body common control { bundlesequence => { "updateusers" }; } ######################################################## bundle agent updateusers { vars: # Set $(testing) to "" for production "testing" string => "/home/mark/tmp"; "tmp" string => "$(testing)/etc/passwd_tmp"; "extract_users" slist => { "mark", "root", "at", "www-run" }; files: # # Take the passwed entries from source and add them to real_passwd # "$(tmp)" create => "true", edit_line => SelectUsers("$(testing)/masterfiles/passwd","@(this.extract_users)"); # # Intermediate file - should be secure - not in /tmp # "$(testing)/etc/passwd" edit_line => ReplaceUsers("$(tmp)","@(this.extract_users)"); # "$(testing)/home/$(extract_users)/." create => "true", perms => userdir("$(extract_users)"); } ######################################################## # Library stuff ######################################################## body perms userdir(u) { mode => "755"; owners => { "$(u)" }; groups => { "users" }; } ######################################################## bundle edit_line SelectUsers(f,l) { insert_lines: "$(f)" insert_type => "file", insert_select => keep("@(l)"); } ######################################################## bundle edit_line ReplaceUsers(f,l) { delete_lines: "$(f)" delete_select => discard("@(l)"); insert_lines: "$(f)" insert_type => "file"; } ######################################################## body insert_select keep(s) { insert_if_startwith_from_list => { @(s) }; } ######################################################## body delete_select discard(s) { delete_if_not_startwith_from_list => { @(s) }; } cfengine-3.6.2/examples/repairedcommand.cf0000664000175100017510000000055112243421446020303 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "cmdtest" }; } bundle agent cmdtest { commands: "/bin/false" classes => example; reports: wasrepaired:: "The command-promise got repaired!"; } body classes example { repaired_returncodes => { "0", "1" }; promise_repaired => { "wasrepaired" }; } cfengine-3.6.2/examples/hash.cf0000644000175100017510000000404112316547775016107 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "md5" string => hash("Cfengine is not cryptic","md5"); "sha256" string => hash("Cfengine is not cryptic","sha256"); "sha384" string => hash("Cfengine is not cryptic","sha384"); "sha512" string => hash("Cfengine is not cryptic","sha512"); reports: "Hashed to: md5 $(md5)"; "Hashed to: sha256 $(sha256)"; "Hashed to: sha384 $(sha384)"; "Hashed to: sha512 $(sha512)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Hashed to: md5 2036af0ee58d6d9dffcc6507af92664f #@ R: Hashed to: sha256 e2fb1927976bfe1ea3987c1a731c75e8ac1453d22a21811dc352db5e62d3f73c #@ R: Hashed to: sha384 b348c0b83ccd9ee12673f5daaba3ee5f49c42906540936bb16cf9d2001ed502b8c56f6e36b8389ab596febb529aab17f #@ R: Hashed to: sha512 29ce0883afbe7740bb2a016735499ae5a0a9b067539018ce6bb2c309a7e885c2d7da64744956e9f151bc72ec8dc19f85efd85eb0a73cbf1e829a15ac9ac35358 #@ ``` #+end_src cfengine-3.6.2/examples/setuidlog.cf0000664000175100017510000000302512243421446017147 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp" -> "me" changes => tripwire, depth_search => recurse("1"); } ######################################################### body changes tripwire { hash => "md5"; report_changes => "content"; update_hashes => "true"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/occurrences.cf0000664000175100017510000000254612243421446017472 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } body knowledge control { query_engine => "123"; } bundle knowledge test { topics: "test topic"; occurrences: test_topic:: "(.*)/help.html" represents => { "host $(match.1)" }, representation => "file", path_root => "/home/mark/tmp", web_root => "http://www.cfengine.com"; } cfengine-3.6.2/examples/islink.cf0000644000175100017510000000277212316547775016466 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ ln -fs /tmp/cfe_testhere.txt /tmp/link #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "islink" expression => islink("/tmp/link"); reports: islink:: "It's a link."; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: It's a link. #@ ``` #+end_src cfengine-3.6.2/examples/webserver.cf0000664000175100017510000000600712243421446017157 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Apache 2 reconfig - modelled on SuSE # ####################################################### body common control { any:: bundlesequence => { apache }; } ####################################################### bundle agent apache { files: "/home/mark/tmp/apache2" # "/etc/sysconfig/apache2" edit_line => fixapache; } ####################################################### # For the library ####################################################### bundle edit_line fixapache { # Values have the form NAME = "quoted space separated list" vars: "add_modules" slist => { "dav", "dav_fs", "ssl", "php5", "dav_svn", "xyz", "superduper" }; "del_modules" slist => { "php3", "jk", "userdir", "imagemap", "alias" }; insert_lines: "APACHE_CONF_INCLUDE_FILES=\"/site/masterfiles/local-http.conf\""; field_edits: ##################################################################### # APACHE_MODULES="authz_host actions alias auth_basic dav dav_fs imagemap ssl php5 dav_svn authz_default jk" ##################################################################### "APACHE_MODULES=.*" # Insert module "columns" between the quoted RHS # using space separators edit_field => quotedvar("$(add_modules)","append"); "APACHE_MODULES=.*" # Delte module "columns" between the quoted RHS # using space separators edit_field => quotedvar("$(del_modules)","delete"); # if this line already exists, edit it } ######################################## # Bodies ######################################## body edit_field quotedvar(newval,method) { field_separator => "\""; select_field => "2"; value_separator => " "; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "false"; allow_blank_fields => "true"; } cfengine-3.6.2/examples/acl_ntfs.cf0000664000175100017510000000116712243421446016746 0ustar00a10038a1003800000000000000body common control { inputs => { "libraries/cfengine_stdlib.cf" }; bundlesequence => { "example" }; } ### bundle agent example { vars: "acl_secret_dir" slist => { "user:Administrator:rwx:allow", "group:Administrators:rx:allow" }; "acl_secret_file" slist => { "user:Administrator:rw:allow" }; files: windows:: "C:\Secret", acl => ntfs( "@(acl_secret_dir)" ), depth_search => include_base, perms => owner( "Administrator" ); "C:\Secret\file.txt", acl => ntfs( "@(acl_secret_file)" ), perms => owner( "Administrator" ); } cfengine-3.6.2/examples/test_environment.cf0000664000175100017510000000542512243421446020561 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Guest environments # ####################################################### body common control { bundlesequence => { "my_vm_cloud" }; } ####################################################### bundle agent my_vm_cloud { guest_environments: scope||any:: # These should probably be in class "any" to ensure uniqueness "test2" environment_resources => my_environment, environment_interface => vnet("eth0,192.168.1.100/24"), environment_type => "test", environment_state => "create", environment_host => "atlas"; "test2" environment_resources => my_environment, environment_interface => vnet("eth0,192.168.1.101/24"), environment_type => "test", environment_state => "delete", environment_host => "atlas"; "test4" environment_resources => my_environment, environment_interface => vnet("eth0,192.168.1.102/24"), environment_type => "test", environment_state => "create", environment_host => "atlas"; "network1" environment_type => "test_net", environment_state => "create", environment_host => "atlas"; # default environment_state => "create" on host, and "suspended elsewhere" } ####################################################### body environment_resources my_environment { env_cpus => "2"; env_memory => "512"; # in KB env_disk => "1024"; # in MB } ####################################################### body environment_interface vnet(primary) { env_name => "$(this.promiser)"; env_addresses => { "$(primary)" }; host1:: env_network => "default_vnet1"; host2:: env_network => "default_vnet2"; } cfengine-3.6.2/examples/isgreaterthan.cf0000644000175100017510000000260412316547775020027 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "ok" expression => isgreaterthan("1","0"); reports: ok:: "Assertion is true"; !ok:: "Assertion is false"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Assertion is true #@ ``` #+end_src cfengine-3.6.2/examples/method_polymorph.cf0000664000175100017510000000106612243421446020544 0ustar00a10038a1003800000000000000# # Demonstrates the use of polymorphism to call bundles. # body common control { bundlesequence => { "example" }; } ########################################### bundle agent example { methods: "Patch Group" comment => "Apply OS specific patches and modifications", usebundle => "$(sys.class)_fix"; } ########################################### bundle agent linux_fix { reports: "Fixes for linux"; } ########################################### bundle agent solaris_android { reports: "Fixes for android"; } cfengine-3.6.2/examples/classes_global.cf0000664000175100017510000000302012243421446020120 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "g","tryclasses_1", "tryclasses_2" }; } ################################# bundle common g { classes: "one" expression => "any"; "client_network" expression => iprange("128.39.89.0/24"); } ################################# bundle agent tryclasses_1 { classes: "two" expression => "any"; } ################################# bundle agent tryclasses_2 { classes: "three" expression => "any"; reports: one.three.!two:: "Success"; } ################################# cfengine-3.6.2/examples/randomint.cf0000644000175100017510000000304212316547775017157 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "randomint_example" }; } bundle agent randomint_example { vars: "low" string => "4"; "high" string => "60"; "random" int => randomint($(low), $(high)); classes: "isabove" expression => isgreaterthan($(random), 3); reports: isabove:: "The generated random number was above 3"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The generated random number was above 3 #@ ``` #+end_src cfengine-3.6.2/examples/getfields.cf0000644000175100017510000000353712332665147017133 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "no" int => getfields("root:.*","/etc/passwd",":","userdata"); reports: "Found $(no) lines matching"; "root's handle = $(userdata[1])"; "root's passwd = ... forget it!"; "root's uid = $(userdata[3])"; # uncomment this if you want to see the HOMEDIR field #"root's homedir = $(userdata[6])"; # uncomment this if you want to see the GID field #"root's gid = $(userdata[4])"; # uncomment this if you want to see the GECOS field #"root's name = $(userdata[5])"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found 1 lines matching #@ R: root's handle = root #@ R: root's passwd = ... forget it! #@ R: root's uid = 0 #@ ``` #+end_src cfengine-3.6.2/examples/getmacaddress.cf0000664000175100017510000000272112243421446017760 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "get_mac_adr" }; } ############################################################## bundle agent get_mac_adr { vars: linux:: "interface" string => execresult("/sbin/ifconfig eth0","noshell"); solaris:: "interface" string => execresult("/usr/sbin/ifconfig bge0","noshell"); freebsd:: "interface" string => execresult("/sbin/ifconfig le0","noshell"); darwin:: "interface" string => execresult("/sbin/ifconfig en0","noshell"); classes: linux:: "ok" expression => regextract( ".*HWaddr ([^\s]+).*(\n.*)*", "$(interface)", "mac" ); solaris:: "ok" expression => regextract( ".*ether ([^\s]+).*(\n.*)*", "$(interface)", "mac" ); freebsd:: "ok" expression => regextract( ".*ether ([^\s]+).*(\n.*)*", "$(interface)", "mac" ); darwin:: "ok" expression => regextract( "(?s).*ether ([^\s]+).*(\n.*)*", "$(interface)", "mac" ); reports: ok:: "MAC address is $(mac[1])"; } cfengine-3.6.2/examples/bsdflags.cf0000664000175100017510000000235112243421446016736 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } bundle agent example { files: freebsd:: "/tmp/newfile" create => "true", perms => setbsd; } body perms setbsd { bsdflags => { "+uappnd","+uchg", "+uunlnk", "-nodump" }; } cfengine-3.6.2/examples/orchestrate_n_of_m.cf0000664000175100017510000000257212243421446021016 0ustar00a10038a1003800000000000000############################################################ # # Keep a special promise only if at least n or m hosts # keep a specific promise # # This method works with Enterprise CFEngine # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # ############################################################ body common control { bundlesequence => { "n_of_m_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################################ bundle agent n_of_m_symphony { vars: "count_compliant_hosts" string => hubknowledge("running_myprocess"); classes: "reboot" expression => isgreaterthan("$(count_compliant_hosts)","20"); processes: "myprocess" comment => "Count this host if a job is matched", classes => enumerate("running_myprocess"); commands: reboot:: "/bin/shutdown now"; } ####################################################### bundle server access_rules() { access: "value of my test_scalar, can expand variables here - $(sys.host)" handle => "test_scalar", comment => "Grant access to contents of test_scalar VAR", resource_type => "literal", admit => { "127.0.0.1" }; "running_myprocess" resource_type => "variable", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/varnet.cf0000664000175100017510000000046212243421446016451 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "example" }; } bundle agent example { reports: "My default interface and ip4 address is $(sys.interface) and $(sys.ipv4)"; "Can also extract $(sys.ipv4[Local_Area_Connection_3]), $(sys.ipv4_2[Wireless_Network_Connection])"; } cfengine-3.6.2/examples/regcmp.cf0000644000175100017510000000274012316547775016445 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { subtest("mark") }; } bundle agent subtest(user) { classes: "invalid" not => regcmp("[a-z]{4}","$(user)"); reports: !invalid:: "User name $(user) is valid at exactly 4 letters"; invalid:: "User name $(user) is invalid"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: User name mark is valid at exactly 4 letters #@ ``` #+end_src cfengine-3.6.2/examples/regarray.cf0000644000175100017510000000276712316547775017015 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "myarray[0]" string => "bla1"; "myarray[1]" string => "bla2"; "myarray[3]" string => "bla"; classes: "ok" expression => regarray("myarray","b.*2"); reports: ok:: "Found in list"; !ok:: "Not found in list"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found in list #@ ``` #+end_src cfengine-3.6.2/examples/splitstring.cf0000644000175100017510000000332412316547775017551 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "split1" slist => splitstring("one:two:three",":","10"); "split2" slist => splitstring("one:two:three",":","1"); "split3" slist => splitstring("alpha:xyz:beta","xyz","10"); reports: "split1: $(split1)"; # will list "one", "two", and "three" "split2: $(split2)"; # will list "one" and "two:three" "split3: $(split3)"; # will list "alpha:" and ":beta" } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: split1: one #@ R: split1: two #@ R: split1: three #@ R: split2: one #@ R: split3: alpha: #@ R: split3: :beta #@ ``` #+end_src cfengine-3.6.2/examples/module_exec_2.cf0000664000175100017510000000332312243421446017663 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Test module execution as class function # body common control { bundlesequence => { "def", "example" }; } ################################################################### bundle agent def { commands: "$(sys.workdir)/modules/module_name" module => "true"; reports: # # Each module forms a private context with its name as id # module_class:: "Module set variable $(module_name.myscalar)"; } ################################################################### bundle agent example { vars: "mylist" slist => { @(module_name.mylist) }; reports: # # Each module forms a private context with its name as id # module_class:: "Module set variable $(mylist)"; } cfengine-3.6.2/examples/islessthan.cf0000644000175100017510000000257312316547775017351 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { classes: "ok" expression => islessthan("0","1"); reports: ok:: "Assertion is true"; !ok:: "Assertion is false"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Assertion is true #@ ``` #+end_src cfengine-3.6.2/examples/defaults2.cf0000664000175100017510000000331112243421446017037 0ustar00a10038a1003800000000000000 # Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Default values for variables and parameters, introduced 3.4.0 # body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "Y" slist => { "I am list item 1", "I am list item 2" }; methods: # More useful, defaults if parameters are passed to a param bundle "example" usebundle => mymethod(@(example.Y)); } ########################################################### bundle agent mymethod(list) { defaults: "list" slist => { "1", "2", "3"}, if_match_regex => ".*list item.*"; # "list" string => "1" , if_match_regex => ".*list item.*"; reports: "The value of list is $(list)"; } cfengine-3.6.2/examples/parsestringarrayidx.cf0000644000175100017510000000371312316547775021276 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test(f) { vars: # Define data inline for convenience "table" string => "one: a two: b three: c"; ####################################### "dim" int => parsestringarrayidx( "items", "$(table)", "\s*#[^\n]*", ":", "1000", "200000" ); "keys" slist => getindices("items"); "sorted_keys" slist => sort(keys, "int"); reports: "item $(sorted_keys) has column 0 = $(items[$(sorted_keys)][0]) and column 1 = $(items[$(sorted_keys)][1])"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: item 0 has column 0 = one and column 1 = a #@ R: item 1 has column 0 = two and column 1 = b #@ R: item 2 has column 0 = three and column 1 = c #@ ``` #+end_src cfengine-3.6.2/examples/copydir_copbl.cf0000664000175100017510000000261412243421446020003 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "my_recursive_copy" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent my_recursive_copy { files: "/home/mark/tmp/test_dir" copy_from => local_cp("$(sys.workdir)/bin/."), depth_search => recurse("inf"); "/home/mark/tmp/test_dir" copy_from => secure_cp("$(sys.workdir)/bin","serverhost"), depth_search => recurse("inf"); } cfengine-3.6.2/examples/exec_args.cf0000664000175100017510000000254012243421446017111 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Test the symmetry between using / not using args => # Locks should prevent these from being run twice, all else being equal. # body common control { bundlesequence => { "main" }; } bundle agent main { vars: "testlist" slist => { "apple", "banana", "carrot" }; commands: "/bin/echo test1 $(testlist)"; "/bin/echo test1" args => "$(testlist)"; } cfengine-3.6.2/examples/user_edit.cf0000664000175100017510000000337512243421446017143 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # body common control { bundlesequence => { "users" }; } body agent control { abortbundleclasses => { "ldap_fail" }; } ################################################################################ bundle agent users { vars: "users" slist => { "mark", "nakarin", "jonhenrik" }; files: "/tmp/passwd2" create => "true", edit_line => fix_passwd("$(users)"); reports: !ldap_fail:: "Editing user $(users)"; } ################################################################################################### bundle edit_line fix_passwd(x) { classes: "ldap_fail" not => ldaparray("dat","ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(uid=$(x))","subtree","none"); insert_lines: "Hello $(x),$(dat[uid]),$(dat[gecos])"; } cfengine-3.6.2/examples/method_var2.cf0000664000175100017510000000135412243421446017365 0ustar00a10038a1003800000000000000# # Demonstrates the use of polymorphism to call bundles. # body common control { bundlesequence => { "example" }; } ########################################### bundle agent example { vars: "m" slist => { "login", "ssh_keys", "environment" }; "user" slist => { "diego", "mark", "neil" }; methods: "set of $(m)" usebundle => $(m)("$(user)"); } ########################################### bundle agent login(x) { reports: "Setup login for $(x)"; } ########################################### bundle agent ssh_keys(x) { reports: "Setup ssh keys for $(x)"; } ########################################### bundle agent environment(x) { reports: "Setup login environment for $(x)"; } cfengine-3.6.2/examples/edit_sectioned_file.cf0000664000175100017510000000533712243421446021141 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test editfile # ######################################################## # # This assumes a file format like: # # [section 1] # # lines.... # # [section 2] # # lines... etc body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { vars: "v1" string => "numerical backreference"; files: "/home/mark/tmp/cf3_test" create => "true", edit_line => AppendIfNoLine("cfengine tcp 5308","second"); } ######################################################## bundle edit_line AppendIfNoLine(parameter,two) { vars: "list" slist => { "1", "2", "3" }; insert_lines: "$(parameter) and $(two)-$(list)" location => append; "NEW Special-insert!!!" select_region => MySection("New section"); "set variable = value" select_region => MySection("New section"); "/home/mark/tmp/insert" insert_type => "file", expand_scalars => "true", select_region => MySection("New section"); delete_lines: # "l.*"; # "NEW.*" select_region => MySection("New section"); # Delete LinesStarting in file } ######################################################## body location append { # If not line to match, applies to whole text body before_after => "after"; } ######################################################## body location after(x) { # If not line to match, applies to whole text body #select_line_matching => "$(x)"; before_after => "after"; } ######################################################## body select_region MySection(x) { select_start => "\[$(x)\]"; select_end => "\[.*\]"; } cfengine-3.6.2/examples/services_concept.cf0000664000175100017510000000620412243421446020510 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ##################################################################### # # Concept of standard services promises # ##################################################################### body common control { bundlesequence => { "example" }; } # bundle agent example { vars: "mail" slist => { "milter", "spamassassin", "postfix" }; services: "www" service_policy => "start", service_method => service_test; "$(mail)" service_policy => "stop", service_method => service_test; } #################################################################### body service_method service_test { service_bundle => non_standard_services("$(this.promiser)","$(this.service_policy)"); } #################################################################### bundle agent standard_services(service,state) { # DATA, vars: suse|redhat:: "startcommand[www]" string => "/etc/init.d/apache2 start"; "stopcommand[www]" string => "/etc/init.d/apache2 stop"; debian|ubuntu:: "startcommand[www]" string => "/etc/init.d/httpd start"; "stopcommand[www]" string => "/etc/init.d/httpd stop"; linux:: "startcommand[postfix]" string => "/etc/init.d/postfix start"; "stopcommand[postfix]" string => "/etc/init.d/postfix stop"; # METHODS classes: "start" expression => strcmp("start","$(state)"); "stop" expression => strcmp("stop","$(state)"); processes: start:: ".*$(service).*" comment => "Verify that the service appears in the process table", restart_class => "restart_$(service)"; stop:: ".*$(service).*" comment => "Verify that the service does not appear in the process", process_stop => "$(stopcommand[$(service)])", signals => { "term", "kill"}; commands: "$(startcommand[$(service)])" comment => "Execute command to restart the $(service) service", ifvarclass => "restart_$(service)"; } ###################################################################### bundle agent non_standard_services(service,state) { reports: !done:: "Test service promise for \"$(service)\" -> $(state)"; } cfengine-3.6.2/examples/knowledge_txt.cf0000664000175100017510000000456112243421446020034 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "tm" }; } body knowledge control { query_output => "text"; query_engine => "none"; sql_database => "test_map"; sql_owner => "mark"; sql_type => "mysql"; sql_passwd => ""; # No passwd for localhost } ################################################### bundle knowledge tm { topics: any:: # We have to start somewhere "Processes" comment => "Programs running on a computer"; "Computers" comment => "Generic boxes", association => a("run","Services","are run on"); Computers:: "server" comment => "Common name for a computer in a datacentre without separate screen and keyboard"; "desktop" comment => "Common name for a computer for end users"; Programs:: "httpd" comment => "A web service process"; "named" comment => "A name service process"; Services:: "WWW" comment => "World Wide Web service", association => a("is implemented by","httpd","implements"); "WWW" association => a("looks up addresses with","named","serves addresses to"); # occurrences: httpd:: "http://www.apache.org" represents => { "website" }; } ################################################### body association a(f,name,b) { forward_relationship => "$(f)"; backward_relationship => "$(b)"; associates => { $(name) }; } cfengine-3.6.2/examples/depends_on2.cf0000664000175100017510000000111112243421446017342 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "main" }; } bundle agent main { methods: "any" usebundle => one; "any" usebundle => mars.two; } bundle agent one { reports: "two" depends_on => { "handle_one" }; "one" handle => "handle_one"; } body file control { namespace => "mars"; } bundle agent two { reports: "marstwo" handle => "mars_two", depends_on => { "handle_one" }; "marsone" handle => "handle_one"; "marsthree" depends_on => { "default.handle_one", "mars_two" }; } cfengine-3.6.2/examples/eval.cf0000664000175100017510000000250612243421446016102 0ustar00a10038a1003800000000000000#+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "values[0]" string => "x"; # bad "values[1]" string => "+ 200"; # bad "values[2]" string => "200 + 100"; "values[3]" string => "200 - 100"; "values[4]" string => "- - -"; # bad "values[5]" string => "2 + 3 - 1"; "values[6]" string => ""; # 0 "values[7]" string => "3 / 0"; # inf but not an error "values[8]" string => "3^3"; "values[9]" string => "-1^2.1"; # -nan but not an error "values[10]" string => "sin(20)"; "values[11]" string => "cos(20)"; "values[19]" string => "20 % 3"; # remainder "values[20]" string => "sqrt(0.2)"; "values[21]" string => "ceil(3.5)"; "values[22]" string => "floor(3.4)"; "values[23]" string => "abs(-3.4)"; "values[24]" string => "-3.4 == -3.4"; "values[25]" string => "-3.400000 == -3.400001"; "values[26]" string => "e"; "values[27]" string => "pi"; "values[28]" string => "100m"; # 100 million "values[29]" string => "100k"; # 100 thousand "indices" slist => getindices("values"); "eval[$(indices)]" string => eval("$(values[$(indices)])", "math", "infix"); reports: "math/infix eval('$(values[$(indices)])') = '$(eval[$(indices)])'"; } #+end_src cfengine-3.6.2/examples/peers.cf0000644000175100017510000000530612352022221016255 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo alpha > /tmp/cfe_hostlist #@ echo beta >> /tmp/cfe_hostlist #@ echo gamma >> /tmp/cfe_hostlist #@ echo "Set HOSTNAME appropriately beforehand" #@ echo $HOSTNAME >> /tmp/cfe_hostlist #@ echo "Delta Delta Delta may I help ya help ya help ya" #@ echo delta1 >> /tmp/cfe_hostlist #@ echo delta2 >> /tmp/cfe_hostlist #@ echo delta3 >> /tmp/cfe_hostlist #@ echo may1.I.help.ya >> /tmp/cfe_hostlist #@ echo may2.I.help.ya >> /tmp/cfe_hostlist #@ echo may3.I.help.ya >> /tmp/cfe_hostlist #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "peers" }; } bundle agent peers { vars: "mygroup" slist => peers("/tmp/cfe_hostlist","#.*",4); "myleader" string => peerleader("/tmp/cfe_hostlist","#.*",4); "all_leaders" slist => peerleaders("/tmp/cfe_hostlist","#.*",4); reports: # note that the current host name is fourth in the host list, so # its peer group is the first 4-host group, minus the host itself. "/tmp/cfe_hostlist mypeer $(mygroup)"; # note that the current host name is fourth in the host list, so # the peer leader is "alpha" "/tmp/cfe_hostlist myleader $(myleader)"; "/tmp/cfe_hostlist another leader $(all_leaders)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /tmp/cfe_hostlist mypeer alpha #@ R: /tmp/cfe_hostlist mypeer beta #@ R: /tmp/cfe_hostlist mypeer gamma #@ R: /tmp/cfe_hostlist myleader alpha #@ R: /tmp/cfe_hostlist another leader alpha #@ R: /tmp/cfe_hostlist another leader delta1 #@ R: /tmp/cfe_hostlist another leader may2.I.help.ya #@ ``` #+end_src cfengine-3.6.2/examples/badtype.cf0000664000175100017510000000241312243421446016600 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # This is an example of malformed promise file. If you pass it through # cf-promises, syntax checker should complain. # body common control { bundlesequence => { "example" }; } bundle agent example { report: # type report is a typo.... linux:: "Goodbye cruel world..."; } cfengine-3.6.2/examples/postfix.cf0000664000175100017510000000621312243421446016646 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Postfix # ####################################################### body common control { any:: bundlesequence => { postfix }; } ####################################################### bundle agent postfix { vars: "prefix" string => "/home/mark/tmp"; "smtpserver" string => "mailx.domain.tld"; "mailrelay" string => "mailx.domain.tld"; files: "$(prefix)/main.cf" edit_line => prefix_postfix; "$(prefix)/sasl-passwd" create => "true", perms => system("0600","root"), edit_line => AppendIfNSL("$(smtpserver) _$(fqhost):chmsxrcynz4etzefabj9frejizhs22"); } ####################################################### # For the library ####################################################### bundle edit_line prefix_postfix { # # Value have the form NAME = "quoted space separated list" # vars: "ps[relayhost]" string => "[$(postfix.mailrelay)]:587"; "ps[mydomain]" string => "iu.hio.no"; "ps[smtp_sasl_auth_enable]" string => "yes"; "ps[smtp_sasl_password_maps]" string => "hash:/etc/postfix/sasl-passwd"; "ps[smtp_sasl_security_options]" string => ""; "ps[smtp_use_tls]" string => "yes"; "ps[default_privs]" string => "mailman"; "ps[inet_protocols]" string => "all"; "ps[inet_interfaces]" string => "127.0.0.1"; "parameter_name" slist => getindices("ps"); delete_lines: "$(parameter_name).*"; insert_lines: "$(parameter_name) = $(ps[$(parameter_name)])"; } ######################################################## bundle edit_line AppendIfNSL(parameter) { insert_lines: "$(parameter)"; # This is default } ######################################## # Library Bodies ######################################## body replace_with All(x) { replace_value => "$(x)"; occurrences => "all"; } ######################################################### body perms system(x,owner) { mode => "0640"; owners => { "$(owner)", "root" }; } cfengine-3.6.2/examples/classmatch.cf0000644000175100017510000000256012316547775017312 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "do_it" and => { classmatch("cfengine_3.*"), "any" }; reports: do_it:: "Host matches pattern"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Host matches pattern #@ ``` #+end_src cfengine-3.6.2/examples/remoteclasses2.cf0000664000175100017510000000225312243421446020105 0ustar00a10038a1003800000000000000# body common control { bundlesequence => { "overture" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ####################################################### bundle agent overture { classes: "extended_context" expression => remoteclassesmatching(".*did.*","127.0.0.1","yes","got"); files: "/etc/passwd" create => "true", classes => set_outcome_classes; reports: got_did_task_one:: "task 1 complete"; extended_context.got_did_task_two:: "task 2 complete"; extended_context.got_did_task_three:: "task 3 complete"; } body classes set_outcome_classes { promise_kept => { "did_task_one","did_task_two", "did_task_three" }; promise_repaired => { "did_task_one","did_task_two", "did_task_three" }; #cancel_kept => { "did_task_one" }; persist_time => "10"; } body server control { allowconnects => { "127.0.0.1" , "::1",}; allowallconnects => { "127.0.0.1" , "::1", }; trustkeysfrom => { "127.0.0.1" , "::1",}; } bundle server access_rules() { access: "did.*" resource_type => "context", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/string_reverse.cf0000644000175100017510000000256212316547775020233 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "reversed" string => string_reverse("abc"); # will contain "cba" reports: "reversed abs = $(reversed)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: reversed abs = cba #@ ``` #+end_src cfengine-3.6.2/examples/getindices.cf0000644000175100017510000000422512316547775017306 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "ps[relayhost]" string => "[mymailrelay]:587"; "ps[mydomain]" string => "iu.hio.no"; "ps[smtp_sasl_auth_enable]" string => "yes"; "ps[smtp_sasl_password_maps]" string => "hash:/etc/postfix/sasl-passwd"; "ps[smtp_sasl_security_options]" string => ""; "ps[smtp_use_tls]" string => "yes"; "ps[default_privs]" string => "mailman"; "ps[inet_protocols]" string => "all"; "ps[inet_interfaces]" string => "127.0.0.1"; "parameter_name" slist => getindices("ps"); reports: "Found key $(parameter_name)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found key relayhost #@ R: Found key smtp_sasl_security_options #@ R: Found key inet_protocols #@ R: Found key smtp_sasl_auth_enable #@ R: Found key default_privs #@ R: Found key smtp_use_tls #@ R: Found key smtp_sasl_password_maps #@ R: Found key mydomain #@ R: Found key inet_interfaces #@ ``` #+end_src cfengine-3.6.2/examples/escape.cf0000644000175100017510000000261612316547775016432 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "ip" string => "10.123.321.250"; "escaped" string => escape($(ip)); reports: "escaped $(ip) = $(escaped)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: escaped 10.123.321.250 = 10\.123\.321\.250 #@ ``` #+end_src cfengine-3.6.2/examples/namespace3.cf0000664000175100017510000000014012243421446017162 0ustar00a10038a1003800000000000000 bundle agent test_in_last_file { reports: "Final namespace is the default"; } cfengine-3.6.2/examples/shuffle.cf0000644000175100017510000000323312316547775016622 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "mylist" slist => { "b", "c", "a" }; "seeds" slist => { "xx", "yy", "zz" }; "shuffled_$(seeds)" slist => shuffle(mylist, $(seeds)); "joined_$(seeds)" string => join(",", "shuffled_$(seeds)"); reports: "shuffled RANDOMLY by $(seeds) = '$(joined_$(seeds))'"; } #+end_src ############################################################################### # Not checked because shuffle is random. #+begin_src example_output #@ ``` #@ R: shuffled RANDOMLY by xx = 'b,a,c' #@ R: shuffled RANDOMLY by yy = 'a,c,b' #@ R: shuffled RANDOMLY by zz = 'c,b,a' #@ ``` #+end_src cfengine-3.6.2/examples/getenv.cf0000644000175100017510000000304112316547775016453 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "myvar" string => getenv("EXAMPLE","2048"); classes: "isdefined" not => strcmp("$(myvar)",""); reports: isdefined:: "The EXAMPLE environment variable is $(myvar)"; !isdefined:: "The environment variable EXAMPLE does not exist"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The EXAMPLE environment variable is getenv.cf #@ ``` #+end_src cfengine-3.6.2/examples/process_matching.cf0000664000175100017510000000354212243421446020504 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test processes # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { processes: ".*" process_select => proc_finder("a.*"), process_count => up("cfservd"); } ######################################################## body process_count up(s) { match_range => "1,10"; # or irange("1","10"); out_of_range_define => { "$(s)_out_of_control" }; } ######################################################## body process_select proc_finder(p) { process_owner => { "avahi", "bin" }; command => "$(p)"; pid => "100,199"; vsize => "0,1000"; process_result => "command.(process_owner|vsize)"; } cfengine-3.6.2/examples/expand.cf0000664000175100017510000000262512243421446016434 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "component" slist => { "cf-monitord", "cf-serverd", "cf-execd" }; processes: "$(component)" restart_class => canonify("start_$(component)"); commands: "/bin/echo /var/cfengine/bin/$(component)" ifvarclass => canonify("start_$(component)"); } cfengine-3.6.2/examples/knowledge_driver.cf0000664000175100017510000000263712243421446020512 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "tm" }; } body knowledge control { query_output => "text"; query_engine => "none"; sql_database => "test_map"; sql_owner => "mark"; sql_type => "mysql"; sql_passwd => ""; # No passwd for localhost } ################################################### bundle knowledge tm { topics: any:: "Nothing needed here -- we get everything from the db cache"; } cfengine-3.6.2/examples/intersection.cf0000644000175100017510000000366012316547775017700 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "a" slist => { 1,2,3,"x" }; "b" slist => { "x" }; "mylist1" slist => { "a", "b" }; "mylist2" slist => { "a", "b" }; "$(mylist1)_str" string => join(",", $(mylist1)); "int_$(mylist1)_$(mylist2)" slist => intersection($(mylist1), $(mylist2)); "int_$(mylist1)_$(mylist2)_str" string => join(",", "int_$(mylist1)_$(mylist2)"); reports: "The intersection of list '$($(mylist1)_str)' with '$($(mylist2)_str)' is '$(int_$(mylist1)_$(mylist2)_str)'"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The intersection of list '1,2,3,x' with '1,2,3,x' is '1,2,3,x' #@ R: The intersection of list '1,2,3,x' with 'x' is 'x' #@ R: The intersection of list 'x' with '1,2,3,x' is 'x' #@ R: The intersection of list 'x' with 'x' is 'x' #@ ``` #+end_src cfengine-3.6.2/examples/format.cf0000644000175100017510000000447412316547775016466 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "run" }; } bundle agent run { vars: "v" string => "2.5.6"; "vlist" slist => splitstring($(v), "\.", 3); "padded" string => format("%04d%04d%04d", nth("vlist", 0), nth("vlist", 1), nth("vlist", 2)); "a" string => format("%10.10s", "x"); "b" string => format("%-10.10s", "x"); "c" string => format("%04d", 1); "d" string => format("%07.2f", 1); "e" string => format("hello my name is %s %s", "Inigo", "Montoya"); "container" data => parsejson('{ "x": "y", "z": true }'); "packed" string => format("slist = %S, container = %S", vlist, container); reports: "version $(v) => padded $(padded)"; "%10.10s on 'x' => '$(a)'"; "%-10.10s on 'x' => '$(b)'"; "%04d on '1' => '$(c)'"; "%07.2f on '1' => '$(d)'"; "you killed my father... => '$(e)'"; "$(packed)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: version 2.5.6 => padded 000200050006 #@ R: %10.10s on 'x' => ' x' #@ R: %-10.10s on 'x' => 'x ' #@ R: %04d on '1' => '0001' #@ R: %07.2f on '1' => '0001.00' #@ R: you killed my father... => 'hello my name is Inigo Montoya' #@ R: slist = { "2", "5", "6" }, container = {"x":"y","z":true} #@ ``` #+end_src cfengine-3.6.2/examples/backreferences_files.cf0000664000175100017510000000357112243421446021302 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # File editing - back reference # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: # The back reference in a path only applies to the last link # of the pathname, so the (tmp) gets ignored "/tmp/(cf3)_(.*)" edit_line => myedit("second $(match.2)"); # but ... # "/tmp/cf3_test" # create => "true", # edit_line => myedit("second $(match.1)"); } ######################################################## bundle edit_line myedit(parameter) { vars: "edit_variable" string => "private edit variable is $(parameter)"; insert_lines: "$(edit_variable)"; } cfengine-3.6.2/examples/peerleader.cf0000644000175100017510000000530612352022221017247 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo alpha > /tmp/cfe_hostlist #@ echo beta >> /tmp/cfe_hostlist #@ echo gamma >> /tmp/cfe_hostlist #@ echo "Set HOSTNAME appropriately beforehand" #@ echo $HOSTNAME >> /tmp/cfe_hostlist #@ echo "Delta Delta Delta may I help ya help ya help ya" #@ echo delta1 >> /tmp/cfe_hostlist #@ echo delta2 >> /tmp/cfe_hostlist #@ echo delta3 >> /tmp/cfe_hostlist #@ echo may1.I.help.ya >> /tmp/cfe_hostlist #@ echo may2.I.help.ya >> /tmp/cfe_hostlist #@ echo may3.I.help.ya >> /tmp/cfe_hostlist #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "peers" }; } bundle agent peers { vars: "mygroup" slist => peers("/tmp/cfe_hostlist","#.*",4); "myleader" string => peerleader("/tmp/cfe_hostlist","#.*",4); "all_leaders" slist => peerleaders("/tmp/cfe_hostlist","#.*",4); reports: # note that the current host name is fourth in the host list, so # its peer group is the first 4-host group, minus the host itself. "/tmp/cfe_hostlist mypeer $(mygroup)"; # note that the current host name is fourth in the host list, so # the peer leader is "alpha" "/tmp/cfe_hostlist myleader $(myleader)"; "/tmp/cfe_hostlist another leader $(all_leaders)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /tmp/cfe_hostlist mypeer alpha #@ R: /tmp/cfe_hostlist mypeer beta #@ R: /tmp/cfe_hostlist mypeer gamma #@ R: /tmp/cfe_hostlist myleader alpha #@ R: /tmp/cfe_hostlist another leader alpha #@ R: /tmp/cfe_hostlist another leader delta1 #@ R: /tmp/cfe_hostlist another leader may2.I.help.ya #@ ``` #+end_src cfengine-3.6.2/examples/update.cf0000664000175100017510000000622712243421446016441 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #cop update,example #cop What should a failsafe and update file contain?,example # Minimum failsafe body common control { bundlesequence => { "update" }; } bundle agent update { vars: "master_location" string => "$(sys.workdir)/masterfiles"; "policy_server" string => readfile("$(sys.workdir)/policy_server.dat",40), comment => "IP address to locate your policy host."; classes: "policy_host" or => { classmatch(canonify("ipv4_$(policy_server)")), classmatch(canonify("$(policy_server)")) }, comment => "Define the ip identity of the policy source host"; "have_ppkeys" expression => fileexists("$(sys.workdir)/ppkeys/localhost.pub"); "nofile" expression => fileexists("$(sys.workdir)/policy_server.dat"); commands: !have_ppkeys:: "/var/cfengine/bin/cf-key"; files: "/var/cfengine/inputs" handle => "update_policy", perms => u_p("600"), copy_from => u_scp("$(master_location)"), depth_search => u_recurse("inf"), action => immediate; processes: any:: "cf-execd" restart_class => "start_exec"; policy_host:: "cf-serverd" restart_class => "start_server"; commands: start_exec:: "$(sys.workdir)/bin/cf-execd", action => logme("executor"); start_server:: "$(sys.workdir)/bin/cf-serverd", action => logme("server"); reports: bootstrap_mode.policy_host:: "I am the policy host - i.e. with ipv4 address $(policy_server)"; } ############################################ body action logme(x) { log_repaired => "stdout"; log_string => " -> Started the $(x) (success)"; } ############################################ body perms u_p(p) { mode => "$(p)"; } ############################################# body copy_from u_scp(from) { source => "$(from)"; compare => "digest"; trustkey => "true"; !policy_host:: servers => { "$(policy_server)" }; } ######################################################### body action immediate { ifelapsed => "1"; } ############################################ body depth_search u_recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/appgroups.cf0000644000175100017510000001200312316547775017201 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: # you can also readjson() from a file "groups" data => parsejson('{ "ByGroup": { "App1": [ "GrpA", "GrpB", "GrpC" ], "App2": [ "GrpX", "GrpY", "GrpZ" ] }, "ByApp": { "App1": [ "Host1", "Host2", "Host3" ], "App2": [ "Host1", "Host3" ] } }'); methods: # use the first one on the client #"go" usebundle => appgroups($(sys.uqhost), @(groups)); "go" usebundle => appgroups("Host1", @(groups)); "go" usebundle => appgroups("Host2", @(groups)); } bundle agent appgroups(name, g) { classes: # stage (3) now for each APP, define have_app_APP if the host is in APP's host list "have_app_$(apps)" expression => strcmp($(name), "$(hosts_$(apps))"); # stage (4) define the class have_group_GROUP for every GROUP belonging to APP "have_group_$(groups_$(apps))" expression => "have_app_$(apps)"; # stage (5) define the class have_group if we found any groups "have_group" not => strcmp("0", length("$(cname)_list")); vars: # stage (1) start here: we get the apps from the list of "by app" keys "apps" slist => getindices("g[ByApp]"); "apps_str" string => format("%S", "apps"); # stage (2) now for each app, we collect the hosts assigned to it "hosts_$(apps)" slist => getvalues("g[ByApp][$(apps)]"); "hosts_$(apps)_str" string => format("%S", "hosts_$(apps)"); # stage (2) now for each app, we collect the groups assigned to it "groups_$(apps)" slist => getvalues("g[ByGroup][$(apps)]"); "groups_$(apps)_str" string => format("%S", "groups_$(apps)"); # stage (5) collect the space-separated group names from an intermediate array "cname" string => canonify($(name)); "$(cname)_grouplist[$(groups_$(apps))]" string => "1", ifvarclass => "have_app_$(apps)"; "$(cname)_grouplist" slist => getvalues("$(cname)_grouplist"); # get the keys of the array and sort them, then join with spaces "$(cname)_list" slist => getindices("$(cname)_grouplist"); "$(cname)_list_sorted" slist => sort("$(cname)_list", "lex"); "$(cname)_list_spaces" string => join(" ", "$(cname)_list_sorted"); reports: # stage (1) "$(this.bundle): looking for $(name)"; "$(this.bundle): apps: $(apps_str)"; # stage (2) "$(this.bundle): hosts for $(apps): $(hosts_$(apps)_str)"; "$(this.bundle): groups for $(apps): $(groups_$(apps)_str)"; # stage (3) "$(this.bundle): $(name) is assigned $(apps)" ifvarclass => "have_app_$(apps)"; # stage (4) "$(this.bundle): all groups for $(name) = $(groups_$(apps))" ifvarclass => "have_group_$(groups_$(apps))"; # stage (5) have_group:: "$(this.bundle): space-separated groups for $(name) = $($(cname)_list_spaces)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: appgroups: looking for Host1 #@ R: appgroups: apps: { "App1", "App2" } #@ R: appgroups: hosts for App1: { "Host1", "Host2", "Host3" } #@ R: appgroups: hosts for App2: { "Host1", "Host3" } #@ R: appgroups: groups for App1: { "GrpA", "GrpB", "GrpC" } #@ R: appgroups: groups for App2: { "GrpX", "GrpY", "GrpZ" } #@ R: appgroups: Host1 is assigned App1 #@ R: appgroups: Host1 is assigned App2 #@ R: appgroups: all groups for Host1 = GrpA #@ R: appgroups: all groups for Host1 = GrpX #@ R: appgroups: all groups for Host1 = GrpB #@ R: appgroups: all groups for Host1 = GrpC #@ R: appgroups: all groups for Host1 = GrpY #@ R: appgroups: all groups for Host1 = GrpZ #@ R: appgroups: space-separated groups for Host1 = GrpA GrpB GrpC GrpX GrpY GrpZ #@ R: appgroups: looking for Host2 #@ R: appgroups: Host2 is assigned App1 #@ R: appgroups: all groups for Host2 = GrpA #@ R: appgroups: all groups for Host2 = GrpB #@ R: appgroups: all groups for Host2 = GrpC #@ R: appgroups: space-separated groups for Host2 = GrpA GrpB GrpC #@ ``` #+end_src cfengine-3.6.2/examples/length.cf0000644000175100017510000000336512316547775016455 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "length" int => length("test"); "test_str" string => join(",", "test"); reports: "The test list is $(test_str)"; "The test list has $(length) elements"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test list is 1,2,3,one,two,three,long string,four,fix,six,one,two,three #@ R: The test list has 13 elements #@ ``` #+end_src cfengine-3.6.2/examples/filesexist.cf0000644000175100017510000000273012316547775017346 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "mylist" slist => { "/tmp/a", "/tmp/b", "/tmp/c" }; classes: "exists" expression => filesexist("@(mylist)"); reports: exists:: "All files exist"; !exists:: "Not all files exist"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Not all files exist #@ ``` #+end_src cfengine-3.6.2/examples/registry.cf0000664000175100017510000000435512243421446017027 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "databases" }; } bundle agent databases { databases: windows:: # Regsitry has (value,data) pairs in "keys" which are directories # "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS" # database_operation => "create", # database_type => "ms_registry"; # "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine" # database_operation => "create", # database_rows => { "value1,REG_SZ,new value 1", "value2,REG_SZ,new val 2"} , # database_type => "ms_registry"; "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine" database_operation => "delete", database_columns => { "value1", "value2" } , database_type => "ms_registry"; # "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine" # database_operation => "cache", # cache,restore # registry_exclude => { ".*Windows.*CurrentVersion.*", ".*Touchpad.*", ".*Capabilities.FileAssociations.*", ".*Rfc1766.*" , ".*Synaptics.SynTP.*", ".*SupportedDevices.*8086", ".*Microsoft.*ErrorThresholds" }, # database_type => "ms_registry"; "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS" database_operation => "restore", database_type => "ms_registry"; } cfengine-3.6.2/examples/findfiles.cf0000644000175100017510000000277112316547775017137 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "findtmp" slist => findfiles("/[tT][mM][pP]"); # or find all .txt files under /tmp, up to 6 levels deep... # "findtmp" slist => findfiles("/tmp/**/*.txt"); reports: "All files that match '/[tT][mM][pP]' = $(findtmp)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: All files that match '/[tT][mM][pP]' = /tmp #@ ``` #+end_src cfengine-3.6.2/examples/returnszero.cf0000664000175100017510000000363612411001073017545 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "my_result" expression => returnszero("/usr/local/bin/mycommand","noshell"); reports: !my_result:: "Command failed"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ 2014-02-10T17:43:55-0500 error: /default/example/classes: Proposed executable file '/usr/local/bin/mycommand' doesn't exist #@ 2014-02-10T17:43:55-0500 error: /default/example/classes: returnszero '/usr/local/bin/mycommand' is assumed to be executable but isn't #@ 2014-02-10T17:43:55-0500 error: /default/example/classes: Proposed executable file '/usr/local/bin/mycommand' doesn't exist #@ 2014-02-10T17:43:55-0500 error: /default/example/classes: returnszero '/usr/local/bin/mycommand' is assumed to be executable but isn't #@ R: Command failed #@ ``` #+end_src cfengine-3.6.2/examples/edit_comment_lines.cf0000664000175100017510000000431312243421446021012 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # File editing # # Normal ordering: # - delete # - replace | colum_edit # - insert # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp/cf3_test" create => "true", edit_line => myedit("second"); } ######################################################## bundle edit_line myedit(parameter) { vars: "edit_variable" string => "private edit variable is $(parameter)"; replace_patterns: # replace shell comments with C comments "#(.*)" replace_with => C_comment, select_region => MySection("New section"); } ######################################## # Bodies ######################################## body replace_with C_comment { replace_value => "/* $(match.1) */"; # backreference 0 occurrences => "all"; # first, last all } ######################################################## body select_region MySection(x) { select_start => "\[$(x)\]"; select_end => "\[.*\]"; } cfengine-3.6.2/examples/strftime.cf0000644000175100017510000000354312332665147017017 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "time" int => "1234567890"; "at_time" string => strftime("localtime", "%Y-%m-%d %T", $(time)); "then" string => strftime("localtime", "%Y-%m-%d %T", 0); "gmt_at_time" string => strftime("gmtime", "%Y-%m-%d %T", $(time)); "gmt_then" string => strftime("gmtime", "%Y-%m-%d %T", 0); reports: # this will be different depending on your time zone # "time $(time); at_time $(at_time); then $(then)"; # this will be the same in every time zone "time $(time); GMT at_time $(gmt_at_time); GMT then $(gmt_then)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: time 1234567890; GMT at_time 2009-02-13 23:31:30; GMT then 1970-01-01 00:00:00 #@ ``` #+end_src cfengine-3.6.2/examples/disable_and_rotate_files.cf0000664000175100017510000000323212243421446022135 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Disabling / rotating files # ####################################################### body common control { bundlesequence => { "example" }; } ############################################ bundle agent example { files: "/home/mark/tmp/test_create" comment => "this rule does something", rename => disable; "/home/mark/tmp/rotateme" rename => rotate("4"); } ############################################ body rename disable { disable => "true"; disable_suffix => "_blownaway"; } ############################################ body rename rotate(level) { rotate => "$(level)"; } cfengine-3.6.2/examples/multipassvars.cf0000664000175100017510000000226012243421446020065 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } bundle agent example { vars: any:: "tempdir" string => execresult("/bin/mktemp -d", "noshell"); reports: "tempdir: ${tempdir}"; } cfengine-3.6.2/examples/namespace.cf0000664000175100017510000000206612400110676017103 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "main" }; inputs => { "namespace1.cf", "namespace2.cf", "namespace3.cf" }; } bundle agent main { vars: "alien_list" slist => { getindices("name1:mymethod.array")}; "local_list" slist => { getindices("example.array") }; files: "/tmp/bla" create => "true", perms => zub("700"); # or perms => default:zub("700"); methods: "namespace demo" usebundle => name1:mymethod("arg1"); "namespace demo" usebundle => name2:mymethod("arg1","arg2"); "namespace demo" usebundle => example; # Or "namespace demo" usebundle => default:example; "namespace demo" usebundle => test_in_last_file; reports: "Foreign namespace index list: $(alien_list)"; "Local index list: $(local_list)"; } body perms zub(x) { mode => "$(x)"; } bundle agent example { vars: "array[one]" string => "text one"; "array[two]" string => "text two"; "array[three]" string => "text three"; reports: "TEST OK in no namespace"; } cfengine-3.6.2/examples/varexpansion.cf0000664000175100017510000000265712243421446017677 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "scalar1" string => "SCALAR 1"; "list1" slist => { "LIST1_1", "LIST1_2" } ; "array[1]" string => "ARRAY 1"; "array[2]" string => "ARRAY 2"; "i" slist => getindices("array"); reports: "Scalar $(scalar1)"; "LIst $(list1)"; "Array $(array[$(i)])"; } cfengine-3.6.2/examples/readlist.cf0000664000175100017510000000237612243421446016767 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "mylist" ilist => { readintlist("/tmp/listofint","#.*","[\n]",10,400) }; reports: "List entry: $(mylist)"; } cfengine-3.6.2/examples/namespace1.cf0000664000175100017510000000106512243421446017167 0ustar00a10038a1003800000000000000 body file control { namespace => "name1"; } bundle agent mymethod(one) { vars: "array[one]" string => "text one"; "array[two]" string => "text two"; "array[three]" string => "text three"; files: "/tmp/$(one)" create => "true", edit_line => makefile, perms => name2:settings; reports: "test $(one) in $(this.namespace)_$(this.bundle)"; } bundle edit_line makefile { insert_lines: "THIS IS NAME1"; reports: "makefile in name 1"; } body perms settings { mode => "600"; } cfengine-3.6.2/examples/ldap.cf0000664000175100017510000000477512243421446016105 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # body common control { bundlesequence => { "ldap" , "followup"}; } ################################################################################################### # NOTE!! relying on LDAP or other network data without validation is EXTREMELY dangerous. # You could destroy a system by assuming that the service will respond with a # sensible result. Cfengine does not recommend reliance on network services in configuration. ################################################################################################### bundle agent ldap { vars: # Get the first matching value for "uid" "value" string => ldapvalue("ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(sn=User)","uid","subtree","none"); # Geta all matching values for "uid" - should be a single record match "list" slist => ldaplist("ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(sn=User)","uid","subtree","none"); classes: "gotdata" expression => ldaparray("myarray","ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(uid=mark)","subtree","none"); "found" expression => regldap("ldap://eternity.iu.hio.no","dc=cfengine,dc=com","(sn=User)","uid","subtree","jon.*","none"); reports: "LDAP VALUE $(value) found"; "LDAP LIST VALUE $(list)"; gotdata:: "Found specific entry data ...$(ldap.myarray[uid]),$(ldap.myarray[gecos]), etc"; found:: "Matched regex"; } bundle agent followup { reports: "Different bundle ...$(ldap.myarray[uid]),$(ldap.myarray[gecos]), etc"; } cfengine-3.6.2/examples/template.cf0000664000175100017510000000323612243421446016767 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test editfile - template expansion # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp/file_based_on_template" create => "true", edit_line => ExpandMeFrom("/tmp/source_template"); } ######################################################## bundle edit_line ExpandMeFrom(template) { vars: "myvar" string => "[sub string]"; insert_lines: "$(template)" insert_type => "file", expand_scalars => "true"; } cfengine-3.6.2/examples/filesexist2.cf0000664000175100017510000000270512243421446017415 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "mylist" slist => { "/tmp/a", "/tmp/b", "/tmp/c" }; methods: "any" usebundle => crystal_meth(@(example.mylist)); } bundle agent crystal_meth(x) { classes: "exists" expression => filesexist("@(x)"); reports: exists:: "File does exist"; !exists:: "Does not yet exist"; } cfengine-3.6.2/examples/measurements.cf0000664000175100017510000000753112243421446017666 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #cop measurements,example ####################################################### # # Test file: # # First line # Blonk blonk bnklkygsuilnm # ####################################################### body common control { bundlesequence => { "report" }; } ####################################################### body monitor control { forgetrate => "0.7"; histograms => "true"; } ####################################################### bundle agent report { reports: " Free memory read at $(mon.av_free_memory_watch) cf_monitord read $(mon.value_monitor_self_watch) "; } ####################################################### bundle monitor watch { measurements: # Test 1 - extract string matching "/home/mark/tmp/testmeasure" handle => "blonk_watch", stream_type => "file", data_type => "string", history_type => "weekly", units => "blonks", match_value => find_blonks, action => sample_min("10"); # Test 2 - follow a special process over time # using cfengine's process cache to avoid resampling "/var/cfengine/state/cf_rootprocs" handle => "monitor_self_watch", stream_type => "file", data_type => "int", history_type => "static", units => "kB", match_value => proc_value(".*cf-monitord.*", "root\s+[0-9.]+\s+[0-9.]+\s+[0-9.]+\s+[0-9.]+\s+([0-9]+).*"); # Test 3, discover disk device information "/bin/df" handle => "free_disk_watch", stream_type => "pipe", data_type => "slist", history_type => "static", units => "device", match_value => file_system; # Update this as often as possible # Test 4 "/tmp/file" handle => "line_counter", stream_type => "file", data_type => "counter", match_value => scanlines("MYLINE.*"), history_type => "log"; } ########################################################## body match_value scanlines(x) { select_line_matching => "^$(x)$"; } ########################################################## body action sample_min(x) { ifelapsed => "$(x)"; expireafter => "$(x)"; } ########################################################## body match_value find_blonks { select_line_number => "2"; extraction_regex => "Blonk blonk ([blonk]+).*"; } ########################################################## body match_value free_memory # not willy! { select_line_matching => "MemFree:.*"; extraction_regex => "MemFree:\s+([0-9]+).*"; } ########################################################## body match_value proc_value(x,y) { select_line_matching => "$(x)"; extraction_regex => "$(y)"; } ########################################################## body match_value file_system { select_line_matching => "/.*"; extraction_regex => "(.*)"; } cfengine-3.6.2/examples/maparray.cf0000644000175100017510000000367312316547775017012 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "run" }; } bundle agent run { vars: "static[2]" string => "lookup 2"; "static[two]" string => "lookup two"; "static[big]" string => "lookup big"; "static[small]" string => "lookup small"; "todo[1]" string => "2"; "todo[one]" string => "two"; "todo[3999]" slist => { "big", "small" }; "map" slist => maparray("key='$(this.k)', static lookup = '$(static[$(this.v)])', value='$(this.v)'", "todo"); reports: "mapped array: $(map)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: mapped array: key='1', static lookup = 'lookup 2', value='2' #@ R: mapped array: key='one', static lookup = 'lookup two', value='two' #@ R: mapped array: key='3999', static lookup = 'lookup big', value='big' #@ R: mapped array: key='3999', static lookup = 'lookup small', value='small' #@ ``` #+end_src cfengine-3.6.2/examples/zenoss.cf0000664000175100017510000000436512243421446016501 0ustar00a10038a1003800000000000000 ###################################################################### # # Zenoss integration template example # ###################################################################### body common control { bundlesequence => { "zenoss_host", "zenoss_client" }; syslog_host => "zenoss_syslog.example.org"; syslog_port => "514"; inputs => {"libraries/cfengine_stdlib.cf"}; } ######################################################## bundle agent zenoss_host { vars: "cf_server_hosts" string => "cfengine_policy.example.org"; "cf_doc_root" string => "/srv/www/html"; "zCfengineComplianceFile" string => "/home/zenoss/compliance.zen"; files: # Assume Cfengine is running on the zenoss server to collect data zenoss_syslog_example_org:: "$(zCfengineComplianceFile)" comment => "Collect data from the Cfengine policy server", perms => mo("644","zenoss"), copy_from => secure_cp("$(cf_doc_root)/reports/summary.z","$(cf_server_host)"); } ######################################################## bundle agent zenoss_client { processes: # On clients, we just pass any messages to the zenoss server # for logging... "bad_process" comment => "Make sure that process X is not running, tell zenoss if it was", signals => { "term", "kill" }, action => tell_zenoss_repaired("bad_process was killed"); files: "/etc/passwd" comment => "Check passwd security, tell zenoss if permissions were wrong", perms => mog("644","root","root"), action => tell_zenoss_repaired("passwd file had incorrect permissions"); commands: "/my/important/script -xyz" comment => "Run my mission critical batch process", action => tell_zenoss_failed("myscript failed to execute or returned error"); } # # Library stuff # body action tell_zenoss_repaired(x) { log_repaired => "udp_syslog"; log_string => "zenoss_cfengine_integration $(x) promise repaired"; ifelapsed => "10"; # Every 10 mins } body action tell_zenoss_failed(x) { log_failed => "udp_syslog"; log_string => "zenoss_cfengine_integration $(x) persistent problem"; ifelapsed => "10"; # Every 10 mins } cfengine-3.6.2/examples/compare.cf0000664000175100017510000000257512243421446016607 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Testing some variable/class definitions - note scope # # Use browser -f promise_output_agent.html to view # body common control { bundlesequence => { "test" }; } ########################################################### bundle agent example { classes: "ok" expression => isgreaterthan("1","0"); reports: ok:: "Assertion is true"; !ok:: "Assertion is false"; } cfengine-3.6.2/examples/promises.cf0000664000175100017510000000403212243421446017010 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # The starting point for every configuration # ####################################################### body common control { any:: bundlesequence => { "update", "main", "cfengine2" }; inputs => { "update.cf" }; } ####################################################### bundle agent main { # do something vars: "sys_files" slist => { "/etc/passwd", "/etc/services" }; files: "$(sys_files)" perms => p("root","0644"), changes => trip_wire; "/etc/shadow" perms => p("root","0600"), changes => trip_wire; "/usr" changes => trip_wire, depth_search => recurse("inf"); "/tmp" delete => tidy, file_select => days("2"), depth_search => recurse("inf"); } ####################################################### bundle agent cfengine2 { commands: "/var/cfengine/bin/cfagent"; } cfengine-3.6.2/examples/arrays.cf0000664000175100017510000000245512243421446016457 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "array" }; } bundle common g { vars: "array[1]" string => "one"; "array[2]" string => "two"; } bundle agent array { vars: "localarray[1]" string => "one"; "localarray[2]" string => "two"; reports: "Global $(g.array[1]) and $(localarray[2])"; } cfengine-3.6.2/examples/remoteclasses.cf0000664000175100017510000000763412243421446020033 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Remote classes from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-d2] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { job_chain("Hr16|Hr17") }; version => "1.2.3"; } ######################################################## bundle common g { vars: # Signals are in scope of promiser and promisee "signal" string => "pack_a_name"; } ######################################################## bundle agent job_chain(time) { vars: "client" string => "localhost"; "server" string => "localhost"; "margin" string => "5"; # mins deadtime classes: "client_primed" expression => classmatch(canonify("$(client)")), ifvarclass => "$(time)"; "server_primed" expression => classmatch(canonify("$(server)")), ifvarclass => "$(time)"; client_primed:: "succeeded" expression => remoteclassesmatching("$(g.signal)","$(server)","yes","myprefix"); # # Now the job itself # methods: client_primed:: "downstream" usebundle => do_job("Starting local follow-up job"), action => if_elapsed("$(margin)"), ifvarclass => "myprefix_$(g.signal)"; server_primed:: "upstream" usebundle => do_job("Starting remote job"), action => if_elapsed("$(margin)"), classes => signal_repaired("$(g.signal)"); reports: !succeeded:: "Server communication failed", ifvarclass => "$(time)"; "Job completed on the server...", ifvarclass => "$(g.signal)"; } ######################################################### bundle agent do_job(job) { commands: # do whatever... "/bin/echo $(job)"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; allowusers => { "mark" }; } ######################################################### bundle server access_rules() { vars: "localvar" string => "literal string"; access: "$(g.signal)" handle => "test_class_signal", resource_type => "context", admit => { "127.0.0.1" }; } ######################################################### # Standard library ######################################################### body action if_elapsed(x) { ifelapsed => "$(x)"; } ######################################################### body classes signal_repaired(x) { promise_repaired => { "$(x)" }; persist_time => "10"; } cfengine-3.6.2/examples/copy_copbl.cf0000664000175100017510000000326112243421446017303 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "mycopy" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent mycopy { files: "/tmp/test_plain" #@ Path and name of the file we wish to copy to comment => "/tmp/test_plain promises to be an up-to-date copy of /bin/echo to demonstrate copying a local file", copy_from => local_cp("$(sys.workdir)/bin/file"); #@ Copy locally from path/filename "/tmp/test_remote_plain" comment => "/tmp/test_plain_remote promises to be a copy of cfengine://serverhost.example.org/repo/config-files/motd", copy_from => secure_cp("/repo/config-files/motd", "serverhost.example.org"); } #@ Copy remotely from path/filename and specified host cfengine-3.6.2/examples/method_validate.cf0000664000175100017510000000325212243421446020303 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; version => "1.2.3"; } ########################################### body agent control { abortbundleclasses => { "invalid" }; } ########################################### bundle agent example { vars: "userlist" slist => { "xyz", "mark", "jeang", "jonhenrik", "thomas", "eben" }; methods: "any" usebundle => subtest("$(userlist)"); } ########################################### bundle agent subtest(user) { classes: "invalid" not => regcmp("[a-z][a-z][a-z][a-z]","$(user)"); reports: !invalid:: "User name $(user) is valid at 4 letters"; invalid:: "User name $(user) is invalid"; } cfengine-3.6.2/examples/dirname.cf0000644000175100017510000000256612316547775016615 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "apache_dir" string => dirname("/etc/apache2/httpd.conf"); reports: "apache conf dir = $(apache_dir)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: apache conf dir = /etc/apache2 #@ ``` #+end_src cfengine-3.6.2/examples/promise_knowledge.cf0000664000175100017510000045563012403637345020707 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. bundle knowledge CfengineSiteConfiguration { topics: references:: "bundle reference"; "used in promise"; "has current exemplars"; "is a promise of type"; "occurs in bundle"; "bundle contains promiser"; "makes promise of type"; "promises have been made by"; "makes promises"; "is a promise made by"; system_reports:: "audit report"; "performance report"; "all_locks report"; "active_locks report"; "hashes report"; "classes report"; "lastseen report"; "monitor now report"; "monitor history report"; "monitor summary report"; "compliance report"; "setuid report"; "file_changes report"; "installed software report"; "software patches report"; system_policy:: "bundles"; "bodies"; "contexts"; "promisees"; "promisers"; "promises" comment => "occurrences of promise topics or suggestions"; "promise types"; "body constraints"; "comments" association => a("see instances of","comment","is one of a number of"); "functions" comment => "In built functions that may be used to set variables or classes"; "values" comment => "Formal rvalues in constraint assignments and their legal ranges"; values:: "system signals" comment =>"Should match the generic pattern hup,int,trap,kill,pipe,cont,abrt,stop,quit,term,child,usr1,usr2,bus,segv, i.e. a unix signal name"; "boolean" comment =>"Should match the generic pattern true,false,yes,no,on,off, i.e. a positive or a negative"; "link type" comment =>"Should match the generic pattern symlink,hardlink,relative,absolute,none, i.e. a support link type"; "a time range" comment =>"Should match the generic pattern 0,2147483647, i.e. a value from zero to a maximum system time -- but you should use time functions to convert this"; "a positive integer" comment =>"Should match the generic pattern 0,2147483647, i.e. a number between zero and the maximum value"; "integer" comment =>"Should match the generic pattern -2147483648,2147483647, i.e. a number between the minus and positive maximum values"; "real number" comment =>"Should match the generic pattern -9.99999E100,9.99999E100, i.e. a number between the minus and positive maximum values"; "a single character" comment =>"Should match the generic pattern ^.$, i.e. one symbol"; "posix file mode or permission" comment =>"Should match the generic pattern [0-7augorwxst,+-]+, i.e. something that you would give as an argument to chmod"; "a cfengine class expression" comment =>"Should match the generic pattern [a-zA-Z0-9_!&|.()]+, i.e. an alphanumeric string with option underscores and logical operators"; "a cfengine identifier" comment =>"Should match the generic pattern [a-zA-Z0-9_$.]+, i.e. an alphanumeric string with option underscores"; "a user/group id" comment =>"Should match the generic pattern [a-zA-Z0-9_$.-]+, i.e. an alphanumeric string with option underscores and hyphens"; "a file path" comment =>"Should match the generic pattern [cC]:\\.*|/.*, i.e. a system file path suitable for the target system"; "a syslog level" comment =>"Should match the generic pattern LOG_USER,LOG_DAEMON,LOG_LOCAL0,LOG_LOCAL1,LOG_LOCAL2,LOG_LOCAL3,LOG_LOCAL4,LOG_LOCAL5,LOG_LOCAL6,LOG_LOCAL7, i.e. a syslog constant"; "An arbitrary string" comment =>"Should match the generic pattern , i.e. unspecified characters"; "An arbitrary string" comment =>"Should match the generic pattern .*, i.e. unspecified characters"; "boolean" association => a("is a special case of","int","is the generic type for"); "a time range" association => a("is a special case of","int","is the generic type for"); "a positive integer" association => a("is a special case of","int","is the generic type for"); "integer" association => a("is a special case of","int","is the generic type for"); "real number" association => a("is a special case of","real","is the generic type for"); "a cfengine class expression" association => a("is a special case of","class","is the generic type for"); "a cfengine identifier" association => a("is a special case of","string","is the generic type for"); "a user/group id" association => a("is a special case of","string","is the generic type for"); "a file path" association => a("is a special case of","string","is the generic type for"); "a syslog level" association => a("is a special case of","string","is the generic type for"); "An arbitrary string" association => a("is a special case of","string","is the generic type for"); "An arbitrary string" association => a("is a special case of","string","is the generic type for"); bundles:: "sys" comment => "cfengine's internal bundle of system specific values"; promise_types:: "vars"; body_constraints:: "string" comment => "A scalar string", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "string" association => a("is a body constraint of type","string","has possible body constraints"), comment => "A scalar string"; promise_types:: "vars"; body_constraints:: "int" comment => "A scalar integer", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "int" association => a("is a body constraint of type","int","has possible body constraints"), comment => "A scalar integer"; promise_types:: "vars"; body_constraints:: "real" comment => "A scalar real number", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "real" association => a("is a body constraint of type","real","has possible body constraints"), comment => "A scalar real number"; promise_types:: "vars"; body_constraints:: "slist" comment => "A list of scalar strings", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "slist" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of scalar strings"; "slist" association => a("is a list of type","slist","is used in"); promise_types:: "vars"; body_constraints:: "ilist" comment => "A list of integers", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "ilist" association => a("is a body constraint of type","ilist","has possible body constraints"), comment => "A list of integers"; "ilist" association => a("is a list of type","ilist","is used in"); promise_types:: "vars"; body_constraints:: "rlist" comment => "A list of real numbers", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "rlist" association => a("is a body constraint of type","rlist","has possible body constraints"), comment => "A list of real numbers"; "rlist" association => a("is a list of type","rlist","is used in"); promise_types:: "vars"; body_constraints:: "policy" comment => "The policy for (dis)allowing redefinition of variables", association => a("is a possible body constraint for","promise_types::vars","can have body constraints"); body_constraints:: "policy" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The policy for (dis)allowing redefinition of variables"; promise_types:: "classes"; body_constraints:: "or" comment => "Combine class sources with inclusive OR", association => a("is a possible body constraint for","promise_types::classes","can have body constraints"); body_constraints:: "or" association => a("is a body constraint of type","clist","has possible body constraints"), comment => "Combine class sources with inclusive OR"; promise_types:: "classes"; body_constraints:: "and" comment => "Combine class sources with AND", association => a("is a possible body constraint for","promise_types::classes","can have body constraints"); body_constraints:: "and" association => a("is a body constraint of type","clist","has possible body constraints"), comment => "Combine class sources with AND"; promise_types:: "classes"; body_constraints:: "xor" comment => "Combine class sources with XOR", association => a("is a possible body constraint for","promise_types::classes","can have body constraints"); body_constraints:: "xor" association => a("is a body constraint of type","clist","has possible body constraints"), comment => "Combine class sources with XOR"; promise_types:: "classes"; body_constraints:: "dist" comment => "Generate a probabilistic class distribution (strategy in cfengine 2)", association => a("is a possible body constraint for","promise_types::classes","can have body constraints"); body_constraints:: "dist" association => a("is a body constraint of type","rlist","has possible body constraints"), comment => "Generate a probabilistic class distribution (strategy in cfengine 2)"; "dist" association => a("is a list of type","rlist","is used in"); promise_types:: "classes"; body_constraints:: "expression" comment => "Evaluate string expression of classes in normal form", association => a("is a possible body constraint for","promise_types::classes","can have body constraints"); body_constraints:: "expression" association => a("is a body constraint of type","class","has possible body constraints"), comment => "Evaluate string expression of classes in normal form"; promise_types:: "classes"; body_constraints:: "not" comment => "Evaluate the negation of string expression in normal form", association => a("is a possible body constraint for","promise_types::classes","can have body constraints"); body_constraints:: "not" association => a("is a body constraint of type","class","has possible body constraints"), comment => "Evaluate the negation of string expression in normal form"; promise_types:: "reports"; body_constraints:: "lastseen" comment => "Integer time threshold in hours since current peers were last seen, report absence", association => a("is a possible body constraint for","promise_types::reports","can have body constraints"); body_constraints:: "lastseen" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Integer time threshold in hours since current peers were last seen, report absence"; promise_types:: "reports"; body_constraints:: "intermittency" comment => "Real number threshold [0,1] of intermittency about current peers, report above", association => a("is a possible body constraint for","promise_types::reports","can have body constraints"); body_constraints:: "intermittency" association => a("is a body constraint of type","real","has possible body constraints"), comment => "Real number threshold [0,1] of intermittency about current peers, report above"; promise_types:: "reports"; body_constraints:: "showstate" comment => "List of services about which status reports should be reported to standard output", association => a("is a possible body constraint for","promise_types::reports","can have body constraints"); body_constraints:: "showstate" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of services about which status reports should be reported to standard output"; "showstate" association => a("is a list of type","slist","is used in"); promise_types:: "reports"; body_constraints:: "printfile" comment => "Quote part of a file to standard output", association => a("is a possible body constraint for","promise_types::reports","can have body constraints"); "number_of_lines" comment => "Integer maximum number of lines to print from selected file", association => a("is a possible sub-body constraint for","printfile","may have sub-body constraints"); body_constraints:: "number_of_lines" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Integer maximum number of lines to print from selected file"; "file_to_print" comment => "Path name to the file that is to be sent to standard output", association => a("is a possible sub-body constraint for","printfile","may have sub-body constraints"); body_constraints:: "file_to_print" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Path name to the file that is to be sent to standard output"; promise_types:: "reports"; body_constraints:: "friend_pattern" comment => "Regular expression to keep selected hosts from the friends report list", association => a("is a possible body constraint for","promise_types::reports","can have body constraints"); body_constraints:: "friend_pattern" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression to keep selected hosts from the friends report list"; promise_types:: "reports"; body_constraints:: "report_to_file" comment => "The path and filename to which output should be appended", association => a("is a possible body constraint for","promise_types::reports","can have body constraints"); body_constraints:: "report_to_file" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The path and filename to which output should be appended"; promise_types:: "*"; body_constraints:: "action" comment => "Output behaviour", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); "action_policy" comment => "Whether to repair or report about non-kept promises", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "action_policy" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Whether to repair or report about non-kept promises"; "ifelapsed" comment => "Number of minutes before next allowed assessment of promise", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "ifelapsed" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Number of minutes before next allowed assessment of promise"; "expireafter" comment => "Number of minutes before a repair action is interrupted and retried", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "expireafter" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Number of minutes before a repair action is interrupted and retried"; "log_string" comment => "A message to be written to the log when a promise verification leads to a repair", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "log_string" association => a("is a body constraint of type","string","has possible body constraints"), comment => "A message to be written to the log when a promise verification leads to a repair"; "log_level" comment => "The reporting level sent to syslog", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "log_level" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The reporting level sent to syslog"; "log_kept" comment => "This should be filename of a file to which log_string will be saved, if undefined it goes to syslog", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "log_kept" association => a("is a body constraint of type","string","has possible body constraints"), comment => "This should be filename of a file to which log_string will be saved, if undefined it goes to syslog"; "log_repaired" comment => "This should be filename of a file to which log_string will be saved, if undefined it goes to syslog", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "log_repaired" association => a("is a body constraint of type","string","has possible body constraints"), comment => "This should be filename of a file to which log_string will be saved, if undefined it goes to syslog"; "log_failed" comment => "This should be filename of a file to which log_string will be saved, if undefined it goes to syslog", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "log_failed" association => a("is a body constraint of type","string","has possible body constraints"), comment => "This should be filename of a file to which log_string will be saved, if undefined it goes to syslog"; "audit" comment => "true/false switch for detailed audit records of this promise", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "audit" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false switch for detailed audit records of this promise"; "background" comment => "true/false switch for parallelizing the promise repair", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "background" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false switch for parallelizing the promise repair"; "report_level" comment => "The reporting level for standard output", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "report_level" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The reporting level for standard output"; "measurement_class" comment => "If set performance will be measured and recorded under this identifier", association => a("is a possible sub-body constraint for","action","may have sub-body constraints"); body_constraints:: "measurement_class" association => a("is a body constraint of type","string","has possible body constraints"), comment => "If set performance will be measured and recorded under this identifier"; promise_types:: "*"; body_constraints:: "classes" comment => "Signalling behaviour", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); "promise_repaired" comment => "A list of classes to be defined", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "promise_repaired" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of classes to be defined"; "promise_repaired" association => a("is a list of type","slist","is used in"); "repair_failed" comment => "A list of classes to be defined", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "repair_failed" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of classes to be defined"; "repair_failed" association => a("is a list of type","slist","is used in"); "repair_denied" comment => "A list of classes to be defined", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "repair_denied" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of classes to be defined"; "repair_denied" association => a("is a list of type","slist","is used in"); "repair_timeout" comment => "A list of classes to be defined", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "repair_timeout" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of classes to be defined"; "repair_timeout" association => a("is a list of type","slist","is used in"); "promise_kept" comment => "A list of classes to be defined", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "promise_kept" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of classes to be defined"; "promise_kept" association => a("is a list of type","slist","is used in"); "persist_time" comment => "A number of minutes the specified classes should remain active", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "persist_time" association => a("is a body constraint of type","int","has possible body constraints"), comment => "A number of minutes the specified classes should remain active"; "timer_policy" comment => "Whether a persistent class restarts its counter when rediscovered", association => a("is a possible sub-body constraint for","classes","may have sub-body constraints"); body_constraints:: "timer_policy" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Whether a persistent class restarts its counter when rediscovered"; promise_types:: "*"; body_constraints:: "ifvarclass" comment => "Extended classes ANDed with context", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); body_constraints:: "ifvarclass" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Extended classes ANDed with context"; promise_types:: "*"; body_constraints:: "handle" comment => "A unique id-tag string for referring to this as a promisee elsewhere", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); body_constraints:: "handle" association => a("is a body constraint of type","string","has possible body constraints"), comment => "A unique id-tag string for referring to this as a promisee elsewhere"; promise_types:: "*"; body_constraints:: "depends_on" comment => "A list of promise handles that this promise builds on or depends on somehow (for knowledge management)", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); body_constraints:: "depends_on" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of promise handles that this promise builds on or depends on somehow (for knowledge management)"; "depends_on" association => a("is a list of type","slist","is used in"); promise_types:: "*"; body_constraints:: "comment" comment => "A comment about this promise's real intention that follows through the program", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); body_constraints:: "comment" association => a("is a body constraint of type","string","has possible body constraints"), comment => "A comment about this promise's real intention that follows through the program"; promise_types:: "*"; body_constraints:: "select_region" comment => "Limit edits to a demarked region of the file", association => a("is a possible body constraint for","promise_types::*","can have body constraints"); "select_start" comment => "Regular expression matching start of edit region", association => a("is a possible sub-body constraint for","select_region","may have sub-body constraints"); body_constraints:: "select_start" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression matching start of edit region"; "select_end" comment => "Regular expression matches end of edit region from start", association => a("is a possible sub-body constraint for","select_region","may have sub-body constraints"); body_constraints:: "select_end" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression matches end of edit region from start"; promise_types:: "commands"; body_constraints:: "args" comment => "Alternative string of arguments for the command (concatenated with promiser string)", association => a("is a possible body constraint for","promise_types::commands","can have body constraints"); body_constraints:: "args" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Alternative string of arguments for the command (concatenated with promiser string)"; promise_types:: "commands"; body_constraints:: "contain" comment => "Containment options for the execution process", association => a("is a possible body constraint for","promise_types::commands","can have body constraints"); "useshell" comment => "noshell/useshell/powershell embed the command in the given shell environment (noshell)", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "useshell" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "noshell/useshell/powershell embed the command in the given shell environment (noshell)"; "umask" comment => "The umask value for the child process", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "umask" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The umask value for the child process"; "exec_owner" comment => "The user name or id under which to run the process", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "exec_owner" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The user name or id under which to run the process"; "exec_group" comment => "The group name or id under which to run the process", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "exec_group" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The group name or id under which to run the process"; "exec_timeout" comment => "Timeout in seconds for command completion", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "exec_timeout" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Timeout in seconds for command completion"; "chdir" comment => "Directory for setting current/base directory for the process", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "chdir" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Directory for setting current/base directory for the process"; "chroot" comment => "Directory of root sandbox for process", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "chroot" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Directory of root sandbox for process"; "preview" comment => "true/false preview command when running in dry-run mode (with -n)", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "preview" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false preview command when running in dry-run mode (with -n)"; "no_output" comment => "true/false discard all output from the command", association => a("is a possible sub-body constraint for","contain","may have sub-body constraints"); body_constraints:: "no_output" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false discard all output from the command"; promise_types:: "commands"; body_constraints:: "module" comment => "true/false whether to expect the cfengine module protocol", association => a("is a possible body constraint for","promise_types::commands","can have body constraints"); body_constraints:: "module" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to expect the cfengine module protocol"; promise_types:: "databases"; body_constraints:: "database_server" comment => "Credentials for connecting to a local/remote database server", association => a("is a possible body constraint for","promise_types::databases","can have body constraints"); "db_server_owner" comment => "User name for database connection", association => a("is a possible sub-body constraint for","database_server","may have sub-body constraints"); body_constraints:: "db_server_owner" association => a("is a body constraint of type","string","has possible body constraints"), comment => "User name for database connection"; "db_server_password" comment => "Clear text password for database connection", association => a("is a possible sub-body constraint for","database_server","may have sub-body constraints"); body_constraints:: "db_server_password" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Clear text password for database connection"; "db_server_host" comment => "Hostname or address for connection to database, blank means localhost", association => a("is a possible sub-body constraint for","database_server","may have sub-body constraints"); body_constraints:: "db_server_host" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Hostname or address for connection to database, blank means localhost"; "db_server_type" comment => "The dialect of the database server", association => a("is a possible sub-body constraint for","database_server","may have sub-body constraints"); body_constraints:: "db_server_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The dialect of the database server"; "db_server_connection_db" comment => "The name of an existing database to connect to in order to create/manage other databases", association => a("is a possible sub-body constraint for","database_server","may have sub-body constraints"); body_constraints:: "db_server_connection_db" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The name of an existing database to connect to in order to create/manage other databases"; promise_types:: "databases"; body_constraints:: "database_type" comment => "The type of database that is to be manipulated", association => a("is a possible body constraint for","promise_types::databases","can have body constraints"); body_constraints:: "database_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The type of database that is to be manipulated"; promise_types:: "databases"; body_constraints:: "database_operation" comment => "The nature of the promise - to be or not to be", association => a("is a possible body constraint for","promise_types::databases","can have body constraints"); body_constraints:: "database_operation" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The nature of the promise - to be or not to be"; promise_types:: "databases"; body_constraints:: "database_columns" comment => "A list of column definitions to be promised by SQL databases", association => a("is a possible body constraint for","promise_types::databases","can have body constraints"); body_constraints:: "database_columns" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of column definitions to be promised by SQL databases"; "database_columns" association => a("is a list of type","slist","is used in"); promise_types:: "databases"; body_constraints:: "database_rows" comment => "An ordered list of row values to be promised by SQL databases", association => a("is a possible body constraint for","promise_types::databases","can have body constraints"); body_constraints:: "database_rows" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "An ordered list of row values to be promised by SQL databases"; "database_rows" association => a("is a list of type","slist","is used in"); promise_types:: "databases"; body_constraints:: "registry_exclude" comment => "A list of regular expressions to ignore in key/value verification", association => a("is a possible body constraint for","promise_types::databases","can have body constraints"); body_constraints:: "registry_exclude" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of regular expressions to ignore in key/value verification"; "registry_exclude" association => a("is a list of type","slist","is used in"); promise_types:: "files"; body_constraints:: "file_select" comment => "Choose which files select in a search", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "leaf_name" comment => "List of regexes that match an acceptable name", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "leaf_name" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of regexes that match an acceptable name"; "leaf_name" association => a("is a list of type","slist","is used in"); "path_name" comment => "List of pathnames to match acceptable target", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "path_name" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of pathnames to match acceptable target"; "path_name" association => a("is a list of type","slist","is used in"); "search_mode" comment => "A list of mode masks for acceptable file permissions", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "search_mode" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of mode masks for acceptable file permissions"; "search_mode" association => a("is a list of type","slist","is used in"); "search_size" comment => "Integer range of file sizes", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "search_size" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Integer range of file sizes"; "search_owners" comment => "List of acceptable user names or ids for the file, or regexes to match", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "search_owners" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of acceptable user names or ids for the file, or regexes to match"; "search_owners" association => a("is a list of type","slist","is used in"); "search_groups" comment => "List of acceptable group names or ids for the file, or regexes to match", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "search_groups" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of acceptable group names or ids for the file, or regexes to match"; "search_groups" association => a("is a list of type","slist","is used in"); "search_bsdflags" comment => "String of flags for bsd file system flags expected set", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "search_bsdflags" association => a("is a body constraint of type","string","has possible body constraints"), comment => "String of flags for bsd file system flags expected set"; "ctime" comment => "Range of change times (ctime) for acceptable files", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "ctime" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of change times (ctime) for acceptable files"; "mtime" comment => "Range of modification times (mtime) for acceptable files", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "mtime" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of modification times (mtime) for acceptable files"; "atime" comment => "Range of access times (atime) for acceptable files", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "atime" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of access times (atime) for acceptable files"; "exec_regex" comment => "Matches file if this regular expression matches any full line returned by the command", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "exec_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Matches file if this regular expression matches any full line returned by the command"; "exec_program" comment => "Execute this command on each file and match if the exit status is zero", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "exec_program" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Execute this command on each file and match if the exit status is zero"; "file_types" comment => "List of acceptable file types from menu choices", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "file_types" association => a("is a body constraint of type","(option list)","has possible body constraints"), comment => "List of acceptable file types from menu choices"; "issymlinkto" comment => "List of regular expressions to match file objects", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "issymlinkto" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of regular expressions to match file objects"; "issymlinkto" association => a("is a list of type","slist","is used in"); "file_result" comment => "Logical expression combining classes defined by file search criteria", association => a("is a possible sub-body constraint for","file_select","may have sub-body constraints"); body_constraints:: "file_result" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Logical expression combining classes defined by file search criteria"; promise_types:: "files"; body_constraints:: "copy_from" comment => "Criteria for copying file from a source", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "source" comment => "Reference source file from which to copy", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "source" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Reference source file from which to copy"; "servers" comment => "List of servers in order of preference from which to copy", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "servers" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of servers in order of preference from which to copy"; "servers" association => a("is a list of type","slist","is used in"); "portnumber" comment => "Port number to connect to on server host", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "portnumber" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Port number to connect to on server host"; "copy_backup" comment => "Menu option policy for file backup/version control", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "copy_backup" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option policy for file backup/version control"; "stealth" comment => "true/false whether to preserve time stamps on copied file", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "stealth" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to preserve time stamps on copied file"; "preserve" comment => "true/false whether to preserve file permissions on copied file", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "preserve" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to preserve file permissions on copied file"; "linkcopy_patterns" comment => "List of patterns matching symbolic links that should be replaced with copies", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "linkcopy_patterns" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of patterns matching symbolic links that should be replaced with copies"; "linkcopy_patterns" association => a("is a list of type","slist","is used in"); "copylink_patterns" comment => "List of patterns matching files that should be linked instead of copied", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "copylink_patterns" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of patterns matching files that should be linked instead of copied"; "copylink_patterns" association => a("is a list of type","slist","is used in"); "compare" comment => "Menu option policy for comparing source and image file attributes", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "compare" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option policy for comparing source and image file attributes"; "link_type" comment => "Menu option for type of links to use when copying", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "link_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option for type of links to use when copying"; "type_check" comment => "true/false compare file types before copying and require match", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "type_check" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false compare file types before copying and require match"; "force_update" comment => "true/false force copy update always", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "force_update" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false force copy update always"; "force_ipv4" comment => "true/false force use of ipv4 on ipv6 enabled network", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "force_ipv4" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false force use of ipv4 on ipv6 enabled network"; "copy_size" comment => "Integer range of file sizes that may be copied", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "copy_size" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Integer range of file sizes that may be copied"; "trustkey" comment => "true/false trust public keys from remote server if previously unknown", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "trustkey" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false trust public keys from remote server if previously unknown"; "encrypt" comment => "true/false use encrypted data stream to connect to remote host", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "encrypt" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false use encrypted data stream to connect to remote host"; "verify" comment => "true/false verify transferred file by hashing after copy (resource penalty)", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "verify" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false verify transferred file by hashing after copy (resource penalty)"; "purge" comment => "true/false purge files on client that do not match files on server when depth_search", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "purge" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false purge files on client that do not match files on server when depth_search"; "check_root" comment => "true/false check permissions on the root directory when depth_search", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "check_root" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false check permissions on the root directory when depth_search"; "findertype" comment => "Menu option for default finder type on MacOSX", association => a("is a possible sub-body constraint for","copy_from","may have sub-body constraints"); body_constraints:: "findertype" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option for default finder type on MacOSX"; promise_types:: "files"; body_constraints:: "link_from" comment => "Criteria for linking file from a source", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "source" comment => "The source file to which the link should point", association => a("is a possible sub-body constraint for","link_from","may have sub-body constraints"); body_constraints:: "source" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The source file to which the link should point"; "link_type" comment => "The type of link used to alias the file", association => a("is a possible sub-body constraint for","link_from","may have sub-body constraints"); body_constraints:: "link_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The type of link used to alias the file"; "copy_patterns" comment => "A set of patterns that should be copied ansd synchronized instead of linked", association => a("is a possible sub-body constraint for","link_from","may have sub-body constraints"); body_constraints:: "copy_patterns" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A set of patterns that should be copied ansd synchronized instead of linked"; "copy_patterns" association => a("is a list of type","slist","is used in"); "when_no_source" comment => "Behaviour when the source file to link to does not exist", association => a("is a possible sub-body constraint for","link_from","may have sub-body constraints"); body_constraints:: "when_no_source" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Behaviour when the source file to link to does not exist"; "link_children" comment => "true/false whether to link all directory's children to source originals", association => a("is a possible sub-body constraint for","link_from","may have sub-body constraints"); body_constraints:: "link_children" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to link all directory's children to source originals"; "when_linking_children" comment => "Policy for overriding existing files when linking directories of children", association => a("is a possible sub-body constraint for","link_from","may have sub-body constraints"); body_constraints:: "when_linking_children" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Policy for overriding existing files when linking directories of children"; promise_types:: "files"; body_constraints:: "perms" comment => "Criteria for setting permissions on a file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "mode" comment => "File permissions (like posix chmod)", association => a("is a possible sub-body constraint for","perms","may have sub-body constraints"); body_constraints:: "mode" association => a("is a body constraint of type","string","has possible body constraints"), comment => "File permissions (like posix chmod)"; "owners" comment => "List of acceptable owners or user ids, first is change target", association => a("is a possible sub-body constraint for","perms","may have sub-body constraints"); body_constraints:: "owners" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of acceptable owners or user ids, first is change target"; "owners" association => a("is a list of type","slist","is used in"); "groups" comment => "List of acceptable groups of group ids, first is change target", association => a("is a possible sub-body constraint for","perms","may have sub-body constraints"); body_constraints:: "groups" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of acceptable groups of group ids, first is change target"; "groups" association => a("is a list of type","slist","is used in"); "rxdirs" comment => "true/false add execute flag for directories if read flag is set", association => a("is a possible sub-body constraint for","perms","may have sub-body constraints"); body_constraints:: "rxdirs" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false add execute flag for directories if read flag is set"; "bsdflags" comment => "List of menu options for bsd file system flags to set", association => a("is a possible sub-body constraint for","perms","may have sub-body constraints"); body_constraints:: "bsdflags" association => a("is a body constraint of type","(option list)","has possible body constraints"), comment => "List of menu options for bsd file system flags to set"; promise_types:: "files"; body_constraints:: "changes" comment => "Criteria for change management", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "hash" comment => "Hash files for change detection", association => a("is a possible sub-body constraint for","changes","may have sub-body constraints"); body_constraints:: "hash" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Hash files for change detection"; "report_changes" comment => "Specify criteria for change warnings", association => a("is a possible sub-body constraint for","changes","may have sub-body constraints"); body_constraints:: "report_changes" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Specify criteria for change warnings"; "update_hashes" comment => "Update hash values immediately after change warning", association => a("is a possible sub-body constraint for","changes","may have sub-body constraints"); body_constraints:: "update_hashes" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Update hash values immediately after change warning"; promise_types:: "files"; body_constraints:: "delete" comment => "Criteria for deleting files", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "dirlinks" comment => "Menu option policy for dealing with symbolic links to directories during deletion", association => a("is a possible sub-body constraint for","delete","may have sub-body constraints"); body_constraints:: "dirlinks" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option policy for dealing with symbolic links to directories during deletion"; "rmdirs" comment => "true/false whether to delete empty directories during recursive deletion", association => a("is a possible sub-body constraint for","delete","may have sub-body constraints"); body_constraints:: "rmdirs" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to delete empty directories during recursive deletion"; promise_types:: "files"; body_constraints:: "rename" comment => "Criteria for renaming files", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "newname" comment => "The desired name for the current file", association => a("is a possible sub-body constraint for","rename","may have sub-body constraints"); body_constraints:: "newname" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The desired name for the current file"; "disable_suffix" comment => "The suffix to add to files when disabling (.cfdisabled)", association => a("is a possible sub-body constraint for","rename","may have sub-body constraints"); body_constraints:: "disable_suffix" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The suffix to add to files when disabling (.cfdisabled)"; "disable" comment => "true/false automatically rename and remove permissions", association => a("is a possible sub-body constraint for","rename","may have sub-body constraints"); body_constraints:: "disable" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false automatically rename and remove permissions"; "rotate" comment => "Maximum number of file rotations to keep", association => a("is a possible sub-body constraint for","rename","may have sub-body constraints"); body_constraints:: "rotate" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Maximum number of file rotations to keep"; "disable_mode" comment => "The permissions to set when a file is disabled", association => a("is a possible sub-body constraint for","rename","may have sub-body constraints"); body_constraints:: "disable_mode" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The permissions to set when a file is disabled"; promise_types:: "files"; body_constraints:: "repository" comment => "Name of a repository for versioning", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "repository" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Name of a repository for versioning"; promise_types:: "files"; body_constraints:: "edit_line" comment => "Line editing model for file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "edit_line" association => a("is a body constraint of type","(ext bundle)","has possible body constraints"), comment => "Line editing model for file"; promise_types:: "files"; body_constraints:: "edit_xml" comment => "XML editing model for file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "edit_xml" association => a("is a body constraint of type","(ext bundle)","has possible body constraints"), comment => "XML editing model for file"; promise_types:: "files"; body_constraints:: "edit_defaults" comment => "Default promise details for file edits", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "edit_backup" comment => "Menu option for backup policy on edit changes", association => a("is a possible sub-body constraint for","edit_defaults","may have sub-body constraints"); body_constraints:: "edit_backup" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option for backup policy on edit changes"; "max_file_size" comment => "Do not edit files bigger than this number of bytes", association => a("is a possible sub-body constraint for","edit_defaults","may have sub-body constraints"); body_constraints:: "max_file_size" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Do not edit files bigger than this number of bytes"; "empty_file_before_editing" comment => "Baseline memory model of file to zero/empty before commencing promised edits", association => a("is a possible sub-body constraint for","edit_defaults","may have sub-body constraints"); body_constraints:: "empty_file_before_editing" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Baseline memory model of file to zero/empty before commencing promised edits"; promise_types:: "files"; body_constraints:: "depth_search" comment => "Criteria for file depth searches", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "include_dirs" comment => "List of regexes of directory names to include in depth search", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "include_dirs" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of regexes of directory names to include in depth search"; "include_dirs" association => a("is a list of type","slist","is used in"); "exclude_dirs" comment => "List of regexes of directory names NOT to include in depth search", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "exclude_dirs" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of regexes of directory names NOT to include in depth search"; "exclude_dirs" association => a("is a list of type","slist","is used in"); "include_basedir" comment => "true/false include the start/root dir of the search results", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "include_basedir" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false include the start/root dir of the search results"; "depth" comment => "Maximum depth level for search", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "depth" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Maximum depth level for search"; "xdev" comment => "true/false exclude directories that are on different devices", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "xdev" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false exclude directories that are on different devices"; "traverse_links" comment => "true/false traverse symbolic links to directories (false)", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "traverse_links" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false traverse symbolic links to directories (false)"; "rmdeadlinks" comment => "true/false remove links that point to nowhere", association => a("is a possible sub-body constraint for","depth_search","may have sub-body constraints"); body_constraints:: "rmdeadlinks" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false remove links that point to nowhere"; promise_types:: "files"; body_constraints:: "touch" comment => "true/false whether to touch time stamps on file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "touch" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to touch time stamps on file"; promise_types:: "files"; body_constraints:: "create" comment => "true/false whether to create non-existing file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "create" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to create non-existing file"; promise_types:: "files"; body_constraints:: "move_obstructions" comment => "true/false whether to move obstructions to file-object creation", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "move_obstructions" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether to move obstructions to file-object creation"; promise_types:: "files"; body_constraints:: "transformer" comment => "Shell command (with full path) used to transform current file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "transformer" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Shell command (with full path) used to transform current file"; promise_types:: "files"; body_constraints:: "pathtype" comment => "Menu option for interpreting promiser file object", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); body_constraints:: "pathtype" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option for interpreting promiser file object"; promise_types:: "files"; body_constraints:: "acl" comment => "Criteria for access control lists on file", association => a("is a possible body constraint for","promise_types::files","can have body constraints"); "acl_method" comment => "Editing method for access control list", association => a("is a possible sub-body constraint for","acl","may have sub-body constraints"); body_constraints:: "acl_method" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Editing method for access control list"; "acl_type" comment => "Access control list type for the affected file system", association => a("is a possible sub-body constraint for","acl","may have sub-body constraints"); body_constraints:: "acl_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Access control list type for the affected file system"; "acl_default" comment => "How to apply default (inheritable) access control list", association => a("is a possible sub-body constraint for","acl","may have sub-body constraints"); body_constraints:: "acl_default" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "How to apply default (inheritable) access control list"; "aces" comment => "Native settings for access control entry", association => a("is a possible sub-body constraint for","acl","may have sub-body constraints"); body_constraints:: "aces" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Native settings for access control entry"; "aces" association => a("is a list of type","slist","is used in"); "default_aces" comment => "Native settings for access control entry", association => a("is a possible sub-body constraint for","acl","may have sub-body constraints"); body_constraints:: "default_aces" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Native settings for access control entry"; "default_aces" association => a("is a list of type","slist","is used in"); promise_types:: "insert_lines"; body_constraints:: "location" comment => "Specify where in a file an insertion will be made", association => a("is a possible body constraint for","promise_types::insert_lines","can have body constraints"); "select_line_matching" comment => "Regular expression for matching file line location", association => a("is a possible sub-body constraint for","location","may have sub-body constraints"); body_constraints:: "select_line_matching" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression for matching file line location"; "before_after" comment => "Menu option, point cursor before of after matched line", association => a("is a possible sub-body constraint for","location","may have sub-body constraints"); body_constraints:: "before_after" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option, point cursor before of after matched line"; "first_last" comment => "Menu option, choose first or last occurrence of match in file", association => a("is a possible sub-body constraint for","location","may have sub-body constraints"); body_constraints:: "first_last" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option, choose first or last occurrence of match in file"; promise_types:: "insert_lines"; body_constraints:: "insert_type" comment => "Type of object the promiser string refers to (default literal)", association => a("is a possible body constraint for","promise_types::insert_lines","can have body constraints"); body_constraints:: "insert_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Type of object the promiser string refers to (default literal)"; promise_types:: "insert_lines"; body_constraints:: "insert_select" comment => "Insert only if lines pass filter criteria", association => a("is a possible body constraint for","promise_types::insert_lines","can have body constraints"); "insert_if_startwith_from_list" comment => "Insert line if it starts with a string in the list", association => a("is a possible sub-body constraint for","insert_select","may have sub-body constraints"); body_constraints:: "insert_if_startwith_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Insert line if it starts with a string in the list"; "insert_if_startwith_from_list" association => a("is a list of type","slist","is used in"); "insert_if_not_startwith_from_list" comment => "Insert line if it DOES NOT start with a string in the list", association => a("is a possible sub-body constraint for","insert_select","may have sub-body constraints"); body_constraints:: "insert_if_not_startwith_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Insert line if it DOES NOT start with a string in the list"; "insert_if_not_startwith_from_list" association => a("is a list of type","slist","is used in"); "insert_if_match_from_list" comment => "Insert line if it fully matches a regex in the list", association => a("is a possible sub-body constraint for","insert_select","may have sub-body constraints"); body_constraints:: "insert_if_match_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Insert line if it fully matches a regex in the list"; "insert_if_match_from_list" association => a("is a list of type","slist","is used in"); "insert_if_not_match_from_list" comment => "Insert line if it DOES NOT fully match a regex in the list", association => a("is a possible sub-body constraint for","insert_select","may have sub-body constraints"); body_constraints:: "insert_if_not_match_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Insert line if it DOES NOT fully match a regex in the list"; "insert_if_not_match_from_list" association => a("is a list of type","slist","is used in"); "insert_if_contains_from_list" comment => "Insert line if a regex in the list match a line fragment", association => a("is a possible sub-body constraint for","insert_select","may have sub-body constraints"); body_constraints:: "insert_if_contains_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Insert line if a regex in the list match a line fragment"; "insert_if_contains_from_list" association => a("is a list of type","slist","is used in"); "insert_if_not_contains_from_list" comment => "Insert line if a regex in the list DOES NOT match a line fragment", association => a("is a possible sub-body constraint for","insert_select","may have sub-body constraints"); body_constraints:: "insert_if_not_contains_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Insert line if a regex in the list DOES NOT match a line fragment"; "insert_if_not_contains_from_list" association => a("is a list of type","slist","is used in"); promise_types:: "insert_lines"; body_constraints:: "expand_scalars" comment => "Expand any unexpanded variables", association => a("is a possible body constraint for","promise_types::insert_lines","can have body constraints"); body_constraints:: "expand_scalars" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Expand any unexpanded variables"; promise_types:: "field_edits"; body_constraints:: "edit_field" comment => "Edit line-based file as matrix of fields", association => a("is a possible body constraint for","promise_types::field_edits","can have body constraints"); "field_separator" comment => "The regular expression used to separate fields in a line", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "field_separator" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The regular expression used to separate fields in a line"; "select_field" comment => "Integer index of the field required 1..n", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "select_field" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Integer index of the field required 1..n"; "value_separator" comment => "Character separator for subfields inside the selected field", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "value_separator" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Character separator for subfields inside the selected field"; "field_value" comment => "Set field value to a fixed value", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "field_value" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Set field value to a fixed value"; "field_operation" comment => "Menu option policy for editing subfields", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "field_operation" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option policy for editing subfields"; "extend_fields" comment => "true/false add new fields at end of line if necessary to complete edit", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "extend_fields" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false add new fields at end of line if necessary to complete edit"; "allow_blank_fields" comment => "true/false allow blank fields in a line (do not purge)", association => a("is a possible sub-body constraint for","edit_field","may have sub-body constraints"); body_constraints:: "allow_blank_fields" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false allow blank fields in a line (do not purge)"; promise_types:: "replace_patterns"; body_constraints:: "replace_with" comment => "Search-replace pattern", association => a("is a possible body constraint for","promise_types::replace_patterns","can have body constraints"); "replace_value" comment => "Value used to replace regular expression matches in search", association => a("is a possible sub-body constraint for","replace_with","may have sub-body constraints"); body_constraints:: "replace_value" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Value used to replace regular expression matches in search"; "occurrences" comment => "Menu option to replace all occurrences or just first (NB the latter is non-convergent)", association => a("is a possible sub-body constraint for","replace_with","may have sub-body constraints"); body_constraints:: "occurrences" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option to replace all occurrences or just first (NB the latter is non-convergent)"; promise_types:: "delete_lines"; body_constraints:: "not_matching" comment => "true/false negate match criterion", association => a("is a possible body constraint for","promise_types::delete_lines","can have body constraints"); body_constraints:: "not_matching" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false negate match criterion"; promise_types:: "delete_lines"; body_constraints:: "delete_select" comment => "Delete only if lines pass filter criteria", association => a("is a possible body constraint for","promise_types::delete_lines","can have body constraints"); "delete_if_startwith_from_list" comment => "Delete line if it starts with a string in the list", association => a("is a possible sub-body constraint for","delete_select","may have sub-body constraints"); body_constraints:: "delete_if_startwith_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Delete line if it starts with a string in the list"; "delete_if_startwith_from_list" association => a("is a list of type","slist","is used in"); "delete_if_not_startwith_from_list" comment => "Delete line if it DOES NOT start with a string in the list", association => a("is a possible sub-body constraint for","delete_select","may have sub-body constraints"); body_constraints:: "delete_if_not_startwith_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Delete line if it DOES NOT start with a string in the list"; "delete_if_not_startwith_from_list" association => a("is a list of type","slist","is used in"); "delete_if_match_from_list" comment => "Delete line if it fully matches a regex in the list", association => a("is a possible sub-body constraint for","delete_select","may have sub-body constraints"); body_constraints:: "delete_if_match_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Delete line if it fully matches a regex in the list"; "delete_if_match_from_list" association => a("is a list of type","slist","is used in"); "delete_if_not_match_from_list" comment => "Delete line if it DOES NOT fully match a regex in the list", association => a("is a possible sub-body constraint for","delete_select","may have sub-body constraints"); body_constraints:: "delete_if_not_match_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Delete line if it DOES NOT fully match a regex in the list"; "delete_if_not_match_from_list" association => a("is a list of type","slist","is used in"); "delete_if_contains_from_list" comment => "Delete line if a regex in the list match a line fragment", association => a("is a possible sub-body constraint for","delete_select","may have sub-body constraints"); body_constraints:: "delete_if_contains_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Delete line if a regex in the list match a line fragment"; "delete_if_contains_from_list" association => a("is a list of type","slist","is used in"); "delete_if_not_contains_from_list" comment => "Delete line if a regex in the list DOES NOT match a line fragment", association => a("is a possible sub-body constraint for","delete_select","may have sub-body constraints"); body_constraints:: "delete_if_not_contains_from_list" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Delete line if a regex in the list DOES NOT match a line fragment"; "delete_if_not_contains_from_list" association => a("is a list of type","slist","is used in"); promise_types:: "interfaces"; body_constraints:: "tcp_ip" comment => "Interface tcp/ip properties", association => a("is a possible body constraint for","promise_types::interfaces","can have body constraints"); "ipv4_address" comment => "IPv4 address for the interface", association => a("is a possible sub-body constraint for","tcp_ip","may have sub-body constraints"); body_constraints:: "ipv4_address" association => a("is a body constraint of type","string","has possible body constraints"), comment => "IPv4 address for the interface"; "ipv4_netmask" comment => "Netmask for the interface", association => a("is a possible sub-body constraint for","tcp_ip","may have sub-body constraints"); body_constraints:: "ipv4_netmask" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Netmask for the interface"; "ipv6_address" comment => "IPv6 address for the interface", association => a("is a possible sub-body constraint for","tcp_ip","may have sub-body constraints"); body_constraints:: "ipv6_address" association => a("is a body constraint of type","string","has possible body constraints"), comment => "IPv6 address for the interface"; promise_types:: "methods"; body_constraints:: "usebundle" comment => "Specify the name of a bundle to run as a parameterized method", association => a("is a possible body constraint for","promise_types::methods","can have body constraints"); body_constraints:: "usebundle" association => a("is a body constraint of type","(ext bundle)","has possible body constraints"), comment => "Specify the name of a bundle to run as a parameterized method"; promise_types:: "packages"; body_constraints:: "package_policy" comment => "Criteria for package installation/upgrade on the current system", association => a("is a possible body constraint for","promise_types::packages","can have body constraints"); body_constraints:: "package_policy" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Criteria for package installation/upgrade on the current system"; promise_types:: "packages"; body_constraints:: "package_method" comment => "Criteria for installation and verification", association => a("is a possible body constraint for","promise_types::packages","can have body constraints"); "package_changes" comment => "Menu option - whether to group packages into a single aggregate command", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_changes" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Menu option - whether to group packages into a single aggregate command"; "package_file_repositories" comment => "A list of machine-local directories to search for packages", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_file_repositories" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "A list of machine-local directories to search for packages"; "package_file_repositories" association => a("is a list of type","slist","is used in"); "package_list_command" comment => "Command to obtain a list of installed packages", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_list_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to obtain a list of installed packages"; "package_list_version_regex" comment => "Regular expression with one backreference to extract package version string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_list_version_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract package version string"; "package_list_name_regex" comment => "Regular expression with one backreference to extract package name string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_list_name_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract package name string"; "package_list_arch_regex" comment => "Regular expression with one backreference to extract package architecture string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_list_arch_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract package architecture string"; "package_patch_list_command" comment => "Command to obtain a list of available patches or updates", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_patch_list_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to obtain a list of available patches or updates"; "package_patch_version_regex" comment => "Regular expression with one backreference to extract update version string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_patch_version_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract update version string"; "package_patch_name_regex" comment => "Regular expression with one backreference to extract update name string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_patch_name_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract update name string"; "package_patch_arch_regex" comment => "Regular expression with one backreference to extract update architecture string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_patch_arch_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract update architecture string"; "package_patch_installed_regex" comment => "Regular expression which matches packages that are already installed", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_patch_installed_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression which matches packages that are already installed"; "package_version_regex" comment => "Regular expression with one backreference to extract package version string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_version_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract package version string"; "package_name_regex" comment => "Regular expression with one backreference to extract package name string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_name_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract package name string"; "package_arch_regex" comment => "Regular expression with one backreference to extract package architecture string", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_arch_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression with one backreference to extract package architecture string"; "package_installed_regex" comment => "Regular expression which matches packages that are already installed", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_installed_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression which matches packages that are already installed"; "package_add_command" comment => "Command to install a package to the system", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_add_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to install a package to the system"; "package_delete_command" comment => "Command to remove a package from the system", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_delete_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to remove a package from the system"; "package_update_command" comment => "Command to update to the latest version a currently installed package", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_update_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to update to the latest version a currently installed package"; "package_patch_command" comment => "Command to update to the latest patch release of an installed package", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_patch_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to update to the latest patch release of an installed package"; "package_verify_command" comment => "Command to verify the correctness of an installed package", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_verify_command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Command to verify the correctness of an installed package"; "package_noverify_regex" comment => "Regular expression to match verification failure output", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_noverify_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression to match verification failure output"; "package_noverify_returncode" comment => "Integer return code indicating package verification failure", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_noverify_returncode" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Integer return code indicating package verification failure"; "package_name_convention" comment => "This is how the package manager expects the file to be referred to, e.g. $(name).$(arch)", association => a("is a possible sub-body constraint for","package_method","may have sub-body constraints"); body_constraints:: "package_name_convention" association => a("is a body constraint of type","string","has possible body constraints"), comment => "This is how the package manager expects the file to be referred to, e.g. $(name).$(arch)"; promise_types:: "packages"; body_constraints:: "package_version" comment => "Version reference point for determining promised version", association => a("is a possible body constraint for","promise_types::packages","can have body constraints"); body_constraints:: "package_version" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Version reference point for determining promised version"; promise_types:: "packages"; body_constraints:: "package_architectures" comment => "Select the architecture for package selection", association => a("is a possible body constraint for","promise_types::packages","can have body constraints"); body_constraints:: "package_architectures" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "Select the architecture for package selection"; "package_architectures" association => a("is a list of type","slist","is used in"); promise_types:: "packages"; body_constraints:: "package_select" comment => "A criterion for first acceptable match relative to \"package_version\"", association => a("is a possible body constraint for","promise_types::packages","can have body constraints"); body_constraints:: "package_select" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "A criterion for first acceptable match relative to \"package_version\""; promise_types:: "processes"; body_constraints:: "signals" comment => "A list of menu options representing signals to be sent to a process", association => a("is a possible body constraint for","promise_types::processes","can have body constraints"); body_constraints:: "signals" association => a("is a body constraint of type","(option list)","has possible body constraints"), comment => "A list of menu options representing signals to be sent to a process"; promise_types:: "processes"; body_constraints:: "process_stop" comment => "A command used to stop a running process", association => a("is a possible body constraint for","promise_types::processes","can have body constraints"); body_constraints:: "process_stop" association => a("is a body constraint of type","string","has possible body constraints"), comment => "A command used to stop a running process"; promise_types:: "processes"; body_constraints:: "process_count" comment => "Criteria for constraining the number of processes matching other criteria", association => a("is a possible body constraint for","promise_types::processes","can have body constraints"); "match_range" comment => "Integer range for acceptable number of matches for this process", association => a("is a possible sub-body constraint for","process_count","may have sub-body constraints"); body_constraints:: "match_range" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Integer range for acceptable number of matches for this process"; "in_range_define" comment => "List of classes to define if the matches are in range", association => a("is a possible sub-body constraint for","process_count","may have sub-body constraints"); body_constraints:: "in_range_define" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of classes to define if the matches are in range"; "in_range_define" association => a("is a list of type","slist","is used in"); "out_of_range_define" comment => "List of classes to define if the matches are out of range", association => a("is a possible sub-body constraint for","process_count","may have sub-body constraints"); body_constraints:: "out_of_range_define" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of classes to define if the matches are out of range"; "out_of_range_define" association => a("is a list of type","slist","is used in"); promise_types:: "processes"; body_constraints:: "process_select" comment => "Criteria for matching processes in the system process table", association => a("is a possible body constraint for","promise_types::processes","can have body constraints"); "process_owner" comment => "List of regexes matching the user of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "process_owner" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of regexes matching the user of a process"; "process_owner" association => a("is a list of type","slist","is used in"); "pid" comment => "Range of integers matching the process id of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "pid" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the process id of a process"; "ppid" comment => "Range of integers matching the parent process id of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "ppid" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the parent process id of a process"; "pgid" comment => "Range of integers matching the parent group id of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "pgid" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the parent group id of a process"; "rsize" comment => "Range of integers matching the resident memory size of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "rsize" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the resident memory size of a process"; "vsize" comment => "Range of integers matching the virtual memory size of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "vsize" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the virtual memory size of a process"; "status" comment => "Regular expression matching the status field of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "status" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression matching the status field of a process"; "ttime_range" comment => "Range of integers matching the total elapsed time of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "ttime_range" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the total elapsed time of a process"; "stime_range" comment => "Range of integers matching the start time of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "stime_range" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the start time of a process"; "command" comment => "Regular expression matching the command/cmd field of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "command" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression matching the command/cmd field of a process"; "tty" comment => "Regular expression matching the tty field of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "tty" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression matching the tty field of a process"; "priority" comment => "Range of integers matching the priority field (PRI/NI) of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "priority" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the priority field (PRI/NI) of a process"; "threads" comment => "Range of integers matching the threads (NLWP) field of a process", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "threads" association => a("is a body constraint of type","irange [int,int]","has possible body constraints"), comment => "Range of integers matching the threads (NLWP) field of a process"; "process_result" comment => "Boolean class expression returning the logical combination of classes set by a process selection test", association => a("is a possible sub-body constraint for","process_select","may have sub-body constraints"); body_constraints:: "process_result" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Boolean class expression returning the logical combination of classes set by a process selection test"; promise_types:: "processes"; body_constraints:: "restart_class" comment => "A class to be set if the process is not running, so that a command: rule can be referred to restart the process", association => a("is a possible body constraint for","promise_types::processes","can have body constraints"); body_constraints:: "restart_class" association => a("is a body constraint of type","string","has possible body constraints"), comment => "A class to be set if the process is not running, so that a command: rule can be referred to restart the process"; promise_types:: "storage"; body_constraints:: "mount" comment => "Criteria for mounting foreign file systems", association => a("is a possible body constraint for","promise_types::storage","can have body constraints"); "mount_type" comment => "Protocol type of remote file system", association => a("is a possible sub-body constraint for","mount","may have sub-body constraints"); body_constraints:: "mount_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Protocol type of remote file system"; "mount_source" comment => "Path of remote file system to mount", association => a("is a possible sub-body constraint for","mount","may have sub-body constraints"); body_constraints:: "mount_source" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Path of remote file system to mount"; "mount_server" comment => "Hostname or IP or remote file system server", association => a("is a possible sub-body constraint for","mount","may have sub-body constraints"); body_constraints:: "mount_server" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Hostname or IP or remote file system server"; "mount_options" comment => "List of option strings to add to the file system table (\"fstab\")", association => a("is a possible sub-body constraint for","mount","may have sub-body constraints"); body_constraints:: "mount_options" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of option strings to add to the file system table (\"fstab\")"; "mount_options" association => a("is a list of type","slist","is used in"); "edit_fstab" comment => "true/false add or remove entries to the file system table (\"fstab\")", association => a("is a possible sub-body constraint for","mount","may have sub-body constraints"); body_constraints:: "edit_fstab" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false add or remove entries to the file system table (\"fstab\")"; "unmount" comment => "true/false unmount a previously mounted filesystem", association => a("is a possible sub-body constraint for","mount","may have sub-body constraints"); body_constraints:: "unmount" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false unmount a previously mounted filesystem"; promise_types:: "storage"; body_constraints:: "volume" comment => "Criteria for monitoring/probing mounted volumes", association => a("is a possible body constraint for","promise_types::storage","can have body constraints"); "check_foreign" comment => "true/false verify storage that is mounted from a foreign system on this host", association => a("is a possible sub-body constraint for","volume","may have sub-body constraints"); body_constraints:: "check_foreign" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false verify storage that is mounted from a foreign system on this host"; "freespace" comment => "Absolute or percentage minimum disk space that should be available before warning", association => a("is a possible sub-body constraint for","volume","may have sub-body constraints"); body_constraints:: "freespace" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Absolute or percentage minimum disk space that should be available before warning"; "sensible_size" comment => "Minimum size in bytes that should be used on a sensible-looking storage device", association => a("is a possible sub-body constraint for","volume","may have sub-body constraints"); body_constraints:: "sensible_size" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Minimum size in bytes that should be used on a sensible-looking storage device"; "sensible_count" comment => "Minimum number of files that should be defined on a sensible-looking storage device", association => a("is a possible sub-body constraint for","volume","may have sub-body constraints"); body_constraints:: "sensible_count" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Minimum number of files that should be defined on a sensible-looking storage device"; "scan_arrivals" comment => "true/false generate pseudo-periodic disk change arrival distribution", association => a("is a possible sub-body constraint for","volume","may have sub-body constraints"); body_constraints:: "scan_arrivals" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false generate pseudo-periodic disk change arrival distribution"; promise_types:: "access"; body_constraints:: "admit" comment => "List of host names or IP addresses to grant access to file objects", association => a("is a possible body constraint for","promise_types::access","can have body constraints"); body_constraints:: "admit" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of host names or IP addresses to grant access to file objects"; "admit" association => a("is a list of type","slist","is used in"); promise_types:: "access"; body_constraints:: "deny" comment => "List of host names or IP addresses to deny access to file objects", association => a("is a possible body constraint for","promise_types::access","can have body constraints"); body_constraints:: "deny" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of host names or IP addresses to deny access to file objects"; "deny" association => a("is a list of type","slist","is used in"); promise_types:: "access"; body_constraints:: "maproot" comment => "List of host names or IP addresses to grant full read-privilege on the server", association => a("is a possible body constraint for","promise_types::access","can have body constraints"); body_constraints:: "maproot" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of host names or IP addresses to grant full read-privilege on the server"; "maproot" association => a("is a list of type","slist","is used in"); promise_types:: "access"; body_constraints:: "ifencrypted" comment => "true/false whether the current file access promise is conditional on the connection from the client being encrypted", association => a("is a possible body constraint for","promise_types::access","can have body constraints"); body_constraints:: "ifencrypted" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "true/false whether the current file access promise is conditional on the connection from the client being encrypted"; promise_types:: "access"; body_constraints:: "resource_type" comment => "The type of object being granted access. The default is access to files.", association => a("is a possible body constraint for","promise_types::access","can have body constraints"); body_constraints:: "resource_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The type of object being granted access. The default is access to files."; promise_types:: "roles"; body_constraints:: "authorize" comment => "List of public-key user names that are allowed to activate the promised class during remote agent activation", association => a("is a possible body constraint for","promise_types::roles","can have body constraints"); body_constraints:: "authorize" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of public-key user names that are allowed to activate the promised class during remote agent activation"; "authorize" association => a("is a list of type","slist","is used in"); promise_types:: "topics"; body_constraints:: "association" comment => "Declare associated topics", association => a("is a possible body constraint for","promise_types::topics","can have body constraints"); "forward_relationship" comment => "Name of forward association between promiser topic and associates", association => a("is a possible sub-body constraint for","association","may have sub-body constraints"); body_constraints:: "forward_relationship" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Name of forward association between promiser topic and associates"; "backward_relationship" comment => "Name of backward/inverse association from associates to promiser topic", association => a("is a possible sub-body constraint for","association","may have sub-body constraints"); body_constraints:: "backward_relationship" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Name of backward/inverse association from associates to promiser topic"; "associates" comment => "List of associated topics by this forward relationship", association => a("is a possible sub-body constraint for","association","may have sub-body constraints"); body_constraints:: "associates" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of associated topics by this forward relationship"; "associates" association => a("is a list of type","slist","is used in"); promise_types:: "topics"; body_constraints:: "comment" comment => "Retained comment about this promise's real intention", association => a("is a possible body constraint for","promise_types::topics","can have body constraints"); body_constraints:: "comment" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Retained comment about this promise's real intention"; promise_types:: "occurrences"; body_constraints:: "represents" comment => "List of subtopics that explains the type(s) of information represented by the occurrence", association => a("is a possible body constraint for","promise_types::occurrences","can have body constraints"); body_constraints:: "represents" association => a("is a body constraint of type","slist","has possible body constraints"), comment => "List of subtopics that explains the type(s) of information represented by the occurrence"; "represents" association => a("is a list of type","slist","is used in"); promise_types:: "occurrences"; body_constraints:: "representation" comment => "How to interpret the promiser string e.g. actual data or reference to data", association => a("is a possible body constraint for","promise_types::occurrences","can have body constraints"); body_constraints:: "representation" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "How to interpret the promiser string e.g. actual data or reference to data"; promise_types:: "occurrences"; body_constraints:: "web_root" comment => "Base URL of the occurrence when rendered as a web-URL (replaces path_root)", association => a("is a possible body constraint for","promise_types::occurrences","can have body constraints"); body_constraints:: "web_root" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Base URL of the occurrence when rendered as a web-URL (replaces path_root)"; promise_types:: "occurrences"; body_constraints:: "path_root" comment => "Base path of the occurrence when locating file (replaced by web_root)", association => a("is a possible body constraint for","promise_types::occurrences","can have body constraints"); body_constraints:: "path_root" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Base path of the occurrence when locating file (replaced by web_root)"; promise_types:: "measurements"; body_constraints:: "stream_type" comment => "The datatype being collected.", association => a("is a possible body constraint for","promise_types::measurements","can have body constraints"); body_constraints:: "stream_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The datatype being collected."; promise_types:: "measurements"; body_constraints:: "data_type" comment => "The datatype being collected.", association => a("is a possible body constraint for","promise_types::measurements","can have body constraints"); body_constraints:: "data_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "The datatype being collected."; promise_types:: "measurements"; body_constraints:: "history_type" comment => "Whether the data can be seen as a time-series or just an isolated value", association => a("is a possible body constraint for","promise_types::measurements","can have body constraints"); body_constraints:: "history_type" association => a("is a body constraint of type","(menu option)","has possible body constraints"), comment => "Whether the data can be seen as a time-series or just an isolated value"; promise_types:: "measurements"; body_constraints:: "units" comment => "The engineering dimensions of this value or a note about its intent used in plots", association => a("is a possible body constraint for","promise_types::measurements","can have body constraints"); body_constraints:: "units" association => a("is a body constraint of type","string","has possible body constraints"), comment => "The engineering dimensions of this value or a note about its intent used in plots"; promise_types:: "measurements"; body_constraints:: "match_value" comment => "Criteria for extracting the measurement from a datastream", association => a("is a possible body constraint for","promise_types::measurements","can have body constraints"); "select_line_matching" comment => "Regular expression for matching line location", association => a("is a possible sub-body constraint for","match_value","may have sub-body constraints"); body_constraints:: "select_line_matching" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression for matching line location"; "select_line_number" comment => "Read from the n-th line of the output (fixed format)", association => a("is a possible sub-body constraint for","match_value","may have sub-body constraints"); body_constraints:: "select_line_number" association => a("is a body constraint of type","int","has possible body constraints"), comment => "Read from the n-th line of the output (fixed format)"; "extraction_regex" comment => "Regular expression that should contain a single backreference for extracting a value", association => a("is a possible sub-body constraint for","match_value","may have sub-body constraints"); body_constraints:: "extraction_regex" association => a("is a body constraint of type","string","has possible body constraints"), comment => "Regular expression that should contain a single backreference for extracting a value"; "action"; "classes"; "ifvarclass"; "handle"; "depends_on"; "comment"; "select_region"; functions:: "accessedbefore" comment => "True if arg1 was accessed before arg2 (atime)", association => a("returns data-type","class","is returned by function"); "accumulated" comment => "Convert an accumulated amount of time into a system representation", association => a("returns data-type","int","is returned by function"); "ago" comment => "Convert a time relative to now to an integer system representation", association => a("returns data-type","int","is returned by function"); "canonify" comment => "Convert an abitrary string into a legal class name", association => a("returns data-type","string","is returned by function"); "changedbefore" comment => "True if arg1 was changed before arg2 (ctime)", association => a("returns data-type","class","is returned by function"); "classify" comment => "True if the canonicalization of the argument is a currently defined class", association => a("returns data-type","class","is returned by function"); "classmatch" comment => "True if the regular expression matches any currently defined class", association => a("returns data-type","class","is returned by function"); "execresult" comment => "Execute named command and assign output to variable", association => a("returns data-type","string","is returned by function"); "fileexists" comment => "True if the named file can be accessed", association => a("returns data-type","class","is returned by function"); "filesexist" comment => "True if the named list of files can ALL be accessed", association => a("returns data-type","class","is returned by function"); "getindices" comment => "Get a list of keys to the array whose id is the argument and assign to variable", association => a("returns data-type","slist","is returned by function"); "getgid" comment => "Return the integer group id of the named group on this host", association => a("returns data-type","int","is returned by function"); "getuid" comment => "Return the integer user id of the named user on this host", association => a("returns data-type","int","is returned by function"); "groupexists" comment => "True if group or numerical id exists on this host", association => a("returns data-type","class","is returned by function"); "hash" comment => "Return the hash of arg1, type arg2 and assign to a variable", association => a("returns data-type","string","is returned by function"); "hashmatch" comment => "Compute the hash of arg1, of type arg2 and test if it matches the value in arg 3", association => a("returns data-type","class","is returned by function"); "hostrange" comment => "True if the current host lies in the range of enumerated hostnames specified", association => a("returns data-type","class","is returned by function"); "hostinnetgroup" comment => "True if the current host is in the named netgroup", association => a("returns data-type","class","is returned by function"); "iprange" comment => "True if the current host lies in the range of IP addresses specified", association => a("returns data-type","class","is returned by function"); "irange" comment => "Define a range of integer values for cfengine internal use", association => a("returns data-type","irange [int,int]","is returned by function"); "isdir" comment => "True if the named object is a directory", association => a("returns data-type","class","is returned by function"); "isgreaterthan" comment => "True if arg1 is numerically greater than arg2, else compare strings like strcmp", association => a("returns data-type","class","is returned by function"); "islessthan" comment => "True if arg1 is numerically less than arg2, else compare strings like NOT strcmp", association => a("returns data-type","class","is returned by function"); "islink" comment => "True if the named object is a symbolic link", association => a("returns data-type","class","is returned by function"); "isnewerthan" comment => "True if arg1 is newer (modified later) than arg2 (mtime)", association => a("returns data-type","class","is returned by function"); "isplain" comment => "True if the named object is a plain/regular file", association => a("returns data-type","class","is returned by function"); "isvariable" comment => "True if the named variable is defined", association => a("returns data-type","class","is returned by function"); "lastnode" comment => "Extract the last of a separated string, e.g. filename from a path", association => a("returns data-type","string","is returned by function"); "ldaparray" comment => "Extract all values from an ldap record", association => a("returns data-type","class","is returned by function"); "ldaplist" comment => "Extract all named values from multiple ldap records", association => a("returns data-type","slist","is returned by function"); "ldapvalue" comment => "Extract the first matching named value from ldap", association => a("returns data-type","string","is returned by function"); "now" comment => "Convert the current time into system representation", association => a("returns data-type","int","is returned by function"); "on" comment => "Convert an exact date/time to an integer system representation", association => a("returns data-type","int","is returned by function"); "peers" comment => "Get a list of peers (not including ourself) from the partition to which we belong", association => a("returns data-type","slist","is returned by function"); "peerleader" comment => "Get the assigned peer-leader of the partition to which we belong", association => a("returns data-type","string","is returned by function"); "peerleaders" comment => "Get a list of peer leaders from the named partitioning", association => a("returns data-type","slist","is returned by function"); "randomint" comment => "Generate a random integer between the given limits", association => a("returns data-type","int","is returned by function"); "readfile" comment => "Read max number of bytes from named file and assign to variable", association => a("returns data-type","string","is returned by function"); "readintarray" comment => "Read an array of integers from a file and assign the dimension to a variable", association => a("returns data-type","int","is returned by function"); "readintlist" comment => "Read and assign a list variable from a file of separated ints", association => a("returns data-type","ilist","is returned by function"); "readrealarray" comment => "Read an array of real numbers from a file and assign the dimension to a variable", association => a("returns data-type","int","is returned by function"); "readreallist" comment => "Read and assign a list variable from a file of separated real numbers", association => a("returns data-type","rlist","is returned by function"); "readstringarray" comment => "Read an array of strings from a file and assign the dimension to a variable", association => a("returns data-type","int","is returned by function"); "readstringlist" comment => "Read and assign a list variable from a file of separated strings", association => a("returns data-type","slist","is returned by function"); "readtcp" comment => "Connect to tcp port, send string and assign result to variable", association => a("returns data-type","string","is returned by function"); "regarray" comment => "True if arg1 matches any item in the associative array with id=arg2", association => a("returns data-type","class","is returned by function"); "regcmp" comment => "True if arg2 is a regular expression matching arg1", association => a("returns data-type","class","is returned by function"); "registryvalue" comment => "Returns a value for an MS-Win registry key,value pair", association => a("returns data-type","string","is returned by function"); "regline" comment => "True if arg2 is a regular expression matching a line in file arg1", association => a("returns data-type","class","is returned by function"); "reglist" comment => "True if arg2 matches any item in the list with id=arg1", association => a("returns data-type","class","is returned by function"); "regldap" comment => "True if arg6 is a regular expression matching a value item in an ldap search", association => a("returns data-type","class","is returned by function"); "remotescalar" comment => "Read a scalar value from a remote cfengine server", association => a("returns data-type","string","is returned by function"); "returnszero" comment => "True if named shell command has exit status zero", association => a("returns data-type","class","is returned by function"); "rrange" comment => "Define a range of real numbers for cfengine internal use", association => a("returns data-type","rrange [real,real]","is returned by function"); "selectservers" comment => "Select tcp servers which respond correctly to a query and return their number, set array of names", association => a("returns data-type","int","is returned by function"); "splayclass" comment => "True if the first argument's time-slot has arrived, according to a policy in arg2", association => a("returns data-type","class","is returned by function"); "splitstring" comment => "Convert a string in arg1 into a list of max arg3 strings by splitting on a regular expression in arg2", association => a("returns data-type","slist","is returned by function"); "strcmp" comment => "True if the two strings match exactly", association => a("returns data-type","class","is returned by function"); "usemodule" comment => "Execute cfengine module script and set class if successful", association => a("returns data-type","class","is returned by function"); "userexists" comment => "True if user name or numerical id exists on this host", association => a("returns data-type","class","is returned by function"); topics: bundles:: "update"; contexts:: "any"; promisers:: "master_location" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "master_location" association => a("makes promise of type","promise_types::vars","promises have been made by"); "master_location" association => a("makes promises","promise_unit_update_cf_13","is a promise made by"); promise_types:: "vars" association => a("is employed in bundle","update","employs promises of type"); promises:: "promise_unit_update_cf_13" comment => "(Uncommented promise of type vars made by: master_location..)"; "promise_unit_update_cf_13" association => a("is activated by class context","any","activates promises"); "promise_unit_update_cf_13" association => a("is a promise of type","vars","has current exemplars"); occurrences: promise_unit_update_cf_13:: "promises.cf.html#promise_unit_update_cf_13" comment => "A promise of type vars made by: master_location", represents => { "any", "vars" }; any:: "promises.cf.html#promise_unit_update_cf_13" represents => { "promise", "master_location", "vars" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; string:: "promises.cf.html#promise_unit_update_cf_13" represents => { "used in promise", "promise_unit_update_cf_13" }; topics: bundles:: "update"; contexts:: "any"; promisers:: "pservers" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "pservers" association => a("makes promise of type","promise_types::vars","promises have been made by"); "pservers" association => a("makes promises","promise_unit_update_cf_15","is a promise made by"); promise_types:: "vars" association => a("is employed in bundle","update","employs promises of type"); promises:: "promise_unit_update_cf_15" comment => "IP address to locate your policy host."; "promise_unit_update_cf_15" association => a("is activated by class context","any","activates promises"); "promise_unit_update_cf_15" association => a("is a promise of type","vars","has current exemplars"); occurrences: promise_unit_update_cf_15:: "promises.cf.html#promise_unit_update_cf_15" comment => "IP address to locate your policy host.", represents => { "any", "vars" }; any:: "promises.cf.html#promise_unit_update_cf_15" represents => { "promise", "pservers", "vars" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; int:: "promises.cf.html#promise_unit_update_cf_15" represents => { "used in promise", "promise_unit_update_cf_15" }; comment:: "promises.cf.html#promise_unit_update_cf_15" represents => { "used in promise", "promise_unit_update_cf_15" }; "IP address to locate your policy host." representation => "literal", represents => { "promise_unit_update_cf_15" }; promise_unit_update_cf_15:: "IP address to locate your policy host." representation => "literal", represents => { "comment" }; topics: bundles:: "update"; contexts:: "!have_ppkeys"; promisers:: "/var/cfengine/bin/cf-key" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "/var/cfengine/bin/cf-key" association => a("makes promise of type","promise_types::commands","promises have been made by"); "/var/cfengine/bin/cf-key" association => a("makes promises","promise_unit_update_cf_31","is a promise made by"); promise_types:: "commands" association => a("is employed in bundle","update","employs promises of type"); promises:: "promise_unit_update_cf_31" comment => "(Uncommented promise of type commands made by: /var/cfengine/bin/cf-key..)"; "promise_unit_update_cf_31" association => a("is activated by class context","!have_ppkeys","activates promises"); "promise_unit_update_cf_31" association => a("is a promise of type","commands","has current exemplars"); occurrences: promise_unit_update_cf_31:: "promises.cf.html#promise_unit_update_cf_31" comment => "A promise of type commands made by: /var/cfengine/bin/cf-key", represents => { "!have_ppkeys", "commands" }; _have_ppkeys:: "promises.cf.html#promise_unit_update_cf_31" represents => { "promise", "/var/cfengine/bin/cf-key", "commands" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; topics: bundles:: "update"; contexts:: "xx"; promisers:: "/var/cfengine/inputs" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "/var/cfengine/inputs" association => a("makes promise of type","promise_types::files","promises have been made by"); "/var/cfengine/inputs" association => a("makes promises","update_policy","is a promise made by"); promise_types:: "files" association => a("is employed in bundle","update","employs promises of type"); promises:: "update_policy" comment => "(Uncommented promise of type files made by: /var/cfengine/inputs..)"; "update_policy" association => a("is activated by class context","xx","activates promises"); "update_policy" association => a("is a promise of type","files","has current exemplars"); occurrences: update_policy:: "promises.cf.html#update_policy" comment => "A promise of type files made by: /var/cfengine/inputs", represents => { "xx", "files" }; xx:: "promises.cf.html#update_policy" represents => { "promise", "/var/cfengine/inputs", "files" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; handle:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; perms:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; mode:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; copy_from:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; source:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; compare:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; trustkey:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; servers:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; depth_search:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; depth:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; action:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; ifelapsed:: "promises.cf.html#update_policy" represents => { "used in promise", "update_policy" }; topics: bundles:: "update"; contexts:: "xx"; promisers:: "/var/cfengine/bin" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "/var/cfengine/bin" association => a("makes promise of type","promise_types::files","promises have been made by"); "/var/cfengine/bin" association => a("makes promises","promise_unit_update_cf_47","is a promise made by"); promise_types:: "files" association => a("is employed in bundle","update","employs promises of type"); promises:: "promise_unit_update_cf_47" comment => "(Uncommented promise of type files made by: /var/cfengine/bin..)"; "promise_unit_update_cf_47" association => a("is activated by class context","xx","activates promises"); "promise_unit_update_cf_47" association => a("is a promise of type","files","has current exemplars"); occurrences: promise_unit_update_cf_47:: "promises.cf.html#promise_unit_update_cf_47" comment => "A promise of type files made by: /var/cfengine/bin", represents => { "xx", "files" }; xx:: "promises.cf.html#promise_unit_update_cf_47" represents => { "promise", "/var/cfengine/bin", "files" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; perms:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; mode:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; copy_from:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; source:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; compare:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; trustkey:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; servers:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; depth_search:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; depth:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; action:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; ifelapsed:: "promises.cf.html#promise_unit_update_cf_47" represents => { "used in promise", "promise_unit_update_cf_47" }; topics: bundles:: "update"; contexts:: "any|bootstrap_mode.policy_host"; promisers:: "I am the policy host - i.e. with ipv4 address $(policy_server[0])" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "I am the policy host - i.e. with ipv4 address $(policy_server[0])" association => a("makes promise of type","promise_types::reports","promises have been made by"); "I am the policy host - i.e. with ipv4 address $(policy_server[0])" association => a("makes promises","promise_unit_update_cf_56","is a promise made by"); promise_types:: "reports" association => a("is employed in bundle","update","employs promises of type"); promises:: "promise_unit_update_cf_56" comment => "(Uncommented promise of type reports made by: I am the policy host - i...)"; "promise_unit_update_cf_56" association => a("is activated by class context","any|bootstrap_mode.policy_host","activates promises"); "promise_unit_update_cf_56" association => a("is a promise of type","reports","has current exemplars"); occurrences: promise_unit_update_cf_56:: "promises.cf.html#promise_unit_update_cf_56" comment => "A promise of type reports made by: I am the policy host - i.e. with ipv4 address $(policy_server[0])", represents => { "any|bootstrap_mode.policy_host", "reports" }; any_bootstrap_mode_policy_host:: "promises.cf.html#promise_unit_update_cf_56" represents => { "promise", "I am the policy host - i.e. with ipv4 address $(policy_server[0])", "reports" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; topics: bundles:: "update"; contexts:: "nofile"; promisers:: "found file" association => a("occurs in bundle","bundles::update","bundle contains promiser"); "found file" association => a("makes promise of type","promise_types::reports","promises have been made by"); "found file" association => a("makes promises","promise_unit_update_cf_60","is a promise made by"); promise_types:: "reports" association => a("is employed in bundle","update","employs promises of type"); promises:: "promise_unit_update_cf_60" comment => "(Uncommented promise of type reports made by: found file..)"; "promise_unit_update_cf_60" association => a("is activated by class context","nofile","activates promises"); "promise_unit_update_cf_60" association => a("is a promise of type","reports","has current exemplars"); occurrences: promise_unit_update_cf_60:: "promises.cf.html#promise_unit_update_cf_60" comment => "A promise of type reports made by: found file", represents => { "nofile", "reports" }; nofile:: "promises.cf.html#promise_unit_update_cf_60" represents => { "promise", "found file", "reports" }; update:: "promises.cf.html#bundle_update" represents => { "bundle reference" }; } cfengine-3.6.2/examples/warnifline.cf0000664000175100017510000000321412243421446017306 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Warn if line matched # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/var/cfengine/inputs/.*" edit_line => DeleteLinesMatching(".*cfenvd.*"), action => WarnOnly; } ######################################################## bundle edit_line DeleteLinesMatching(regex) { delete_lines: "$(regex)" action => WarnOnly; } ######################################################## body action WarnOnly { action_policy => "warn"; } cfengine-3.6.2/examples/mergedata.cf0000644000175100017510000000760412316547775017125 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test", "test2" }; } bundle agent test { vars: "d1" data => parsejson('{ "a": [1,2,3], "b": [] }'); "d2" data => parsejson('{ "b": [4,5,6] }'); "d3" data => parsejson('[4,5,6]'); "list1" slist => { "element1", "element2" }; "array1[mykey]" slist => { "array_element1", "array_element2" }; "array2[otherkey]" string => "hello"; "merged_d1_d2" data => mergedata("d1", "d2"); "merged_d1_d3" data => mergedata("d1", "d3"); "merged_d3_list1" data => mergedata("d3", "list1"); "merged_d1_array1" data => mergedata("d1", "array1"); "merged_d2_array2" data => mergedata("d2", "array2"); "merged_d1_d2_str" string => format("merging %S with %S produced %S", d1, d2, merged_d1_d2); "merged_d1_d3_str" string => format("merging %S with %S produced %S", d1, d3, merged_d1_d3); "merged_d3_list1_str" string => format("merging %S with %S produced %S", d3, list1, merged_d3_list1); "merged_d1_array1_str" string => format("merging %S with %s produced %S", d1, array1, merged_d1_array1); "merged_d2_array2_str" string => format("merging %S with %s produced %S", d2, array2, merged_d2_array2); reports: "$(merged_d1_d2_str)"; "$(merged_d1_d3_str)"; "$(merged_d3_list1_str)"; "$(merged_d1_array1_str)"; "$(merged_d2_array2_str)"; } bundle agent test2 { vars: "a" data => parsejson('{ "a": "1" }'), meta => { "mymerge" }; "b" data => parsejson('{ "b": "2" }'), meta => { "mymerge" }; "c" data => parsejson('{ "c": "3" }'), meta => { "mymerge" }; "d" data => parsejson('{ "d": "4" }'), meta => { "mymerge" }; "todo" slist => variablesmatching(".*", "mymerge"); methods: "go" usebundle => cmerge(@(todo)); # a, b, c, d reports: "$(this.bundle): merged containers with cmerge = $(cmerge.all_str)"; } # note this bundle is in the standard library, in lib/3.6/bundles.cf bundle agent cmerge(varlist) { vars: "all" data => parsejson('[]'), policy => "free"; "all" data => mergedata(all, $(varlist)), policy => "free"; "all_str" string => format("%S", all), policy => "free"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: merging {"a":[1,2,3],"b":[]} with {"b":[4,5,6]} produced {"a":[1,2,3],"b":[4,5,6]} #@ R: merging {"a":[1,2,3],"b":[]} with [4,5,6] produced {"a":[1,2,3],"b":[],"0":4,"1":5,"2":6} #@ R: merging [4,5,6] with { "element1", "element2" } produced [4,5,6,"element1","element2"] #@ R: merging {"a":[1,2,3],"b":[]} with array1 produced {"a":[1,2,3],"b":[],"mykey":["array_element1","array_element2"]} #@ R: merging {"b":[4,5,6]} with array2 produced {"b":[4,5,6],"otherkey":"hello"} #@ R: test2: merged containers with cmerge = {"a":"1","b":"2","c":"3","d":"4"} #@ ``` #+end_src cfengine-3.6.2/examples/registry_cache.cf0000664000175100017510000000324512243421446020147 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { # "registry_cache" # "registry_restore" }; } ######################################### bundle agent registry_cache { databases: windows:: "HKEY_LOCAL_MACHINE\SOFTWARE\Adobe" database_operation => "cache", database_type => "ms_registry", comment => "Save correct registry settings for Adobe products"; } ######################################### bundle agent registry_restore { databases: windows:: "HKEY_LOCAL_MACHINE\SOFTWARE\Adobe" database_operation => "restore", database_type => "ms_registry", comment => "Make sure Adobe products have correct registry settings"; } cfengine-3.6.2/examples/Makefile.in0000664000175100017510000004631512412324464016714 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = examples DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(dist_examples_SCRIPTS) $(dist_examples_DATA) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(examplesdir)" \ "$(DESTDIR)$(examplesdir)" SCRIPTS = $(dist_examples_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_examples_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ examplesdir = $(docdir)/examples dist_examples_DATA = $(srcdir)/*.cf dist_examples_SCRIPTS = remake_outputs.pl FAKE_WORKDIR = /tmp/fake-cfengine-workdir MAINTAINERCLEANFILES = Makefile.in mdate-sh all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign examples/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-dist_examplesSCRIPTS: $(dist_examples_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_examples_SCRIPTS)'; test -n "$(examplesdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(examplesdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(examplesdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(examplesdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(examplesdir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_examplesSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_examples_SCRIPTS)'; test -n "$(examplesdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(examplesdir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-dist_examplesDATA: $(dist_examples_DATA) @$(NORMAL_INSTALL) @list='$(dist_examples_DATA)'; test -n "$(examplesdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(examplesdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(examplesdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(examplesdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(examplesdir)" || exit $$?; \ done uninstall-dist_examplesDATA: @$(NORMAL_UNINSTALL) @list='$(dist_examples_DATA)'; test -n "$(examplesdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(examplesdir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: 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 $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(examplesdir)" "$(DESTDIR)$(examplesdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi 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." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_examplesDATA \ install-dist_examplesSCRIPTS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_examplesDATA \ uninstall-dist_examplesSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-dist_examplesDATA install-dist_examplesSCRIPTS \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am \ uninstall-dist_examplesDATA uninstall-dist_examplesSCRIPTS # only re-run the outputs for examples that already have an example_output block remake: perl ./remake_outputs.pl $(shell grep -l example_output $(dist_examples_DATA)) recheck: perl ./remake_outputs.pl -c $(shell grep -l example_output $(dist_examples_DATA)) recheck_verbose: perl ./remake_outputs.pl -v -c $(shell grep -l example_output $(dist_examples_DATA)) # 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: cfengine-3.6.2/examples/package_apt.cf0000664000175100017510000000523412243421446017413 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # to see list of packages type "apt-cache pkgnames" # to see list of installed packages type "dpkg --get-selections" # # Package managment # body common control { bundlesequence => { "packages" }; } body agent control { environment => { "DEBIAN_FRONTEND=noninteractive" }; } ############################################# bundle agent packages { vars: # Test the simplest case -- leave everything to the yum smart manager "match_package" slist => { "apache2" # "apache2-mod_php5", # "apache2-prefork", # "php5" }; packages: "$(match_package)" package_policy => "add", package_method => apt; } ############################################# body package_method apt { any:: # ii acpi 0.09-3ubuntu1 package_changes => "bulk"; package_list_command => "/usr/bin/dpkg -l"; package_list_name_regex => "ii\s+([^\s]+).*"; package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*"; # package_list_arch_regex => "none"; package_installed_regex => ".*"; # all reported are installed #package_name_convention => "$(name)_$(version)_$(arch)"; package_name_convention => "$(name)"; # Use these only if not using a separate version/arch string # package_version_regex => ""; # package_name_regex => ""; # package_arch_regex => ""; package_add_command => "/usr/bin/apt-get --yes install"; package_delete_command => "/usr/bin/apt-get --yes remove"; package_update_command => "/usr/bin/apt-get --yes dist-upgrade"; #package_verify_command => "/bin/rpm -V"; } cfengine-3.6.2/examples/inventory_cpu.cf0000664000175100017510000000132212243421446020052 0ustar00a10038a1003800000000000000# Demo on how to extract the first "model name" field from /proc/cpuinfo # into a variable. # Can be used for inventory information in CFEngine Nova and above. body common control { bundlesequence => { "inventory" }; } ### bundle common inventory { vars: "cpuinfo" string => execresult("/bin/grep \"model name\" /proc/cpuinfo", "noshell"); got_model_name:: "cpu" string => "$(myarray[1])"; classes: "got_model_name" expression => regextract( "model\s+name\s+:\s+([^\n]*)\n?.*", "$(cpuinfo)", "myarray" ); reports: got_model_name:: "model name is \"$(myarray[1])\""; !got_model_name:: "Did not match CPU model name"; } cfengine-3.6.2/examples/activedirectory_showuser.cf0000664000175100017510000000272712243421446022317 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # List users from Active Directory through LDAP # Note: Anonymous LDAP binding must be allowed, and the Anonymous user # must have read access to CN=Users and CN=theusername # Run the agent in verbose mode to see the data bundle agent ldap { classes: "gotdata" expression => ldaparray( "myarray", "ldap://cf-win2003", "CN=Test Pilot,CN=Users,DC=domain,DC=cf-win2003", "(name=*)", "subtree", "none"); reports: gotdata:: "Got user data"; !gotdata:: "Did not get user data"; } cfengine-3.6.2/examples/server_copy_remote.cf0000664000175100017510000000674712243421446021101 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-v] (on remote-host.example.org) # cf-agent -f runtest_2.cf (on host 1.2.3.4) # # Notice that the same file configures all parts of cfengine # even though different parts are read by different hosts and agents ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/tmp/testcopy" perms => system, copy_from => mycopy("/src/document","remote-host.example.org"), depth_search => recurse("inf"); } ######################################################## body perms system { mode => "0444"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body copy_from mycopy(from,server) { source => "$(from)"; #portnumber => "6789"; servers => { "$(server)" , "failover1" }; copy_backup => "true"; #/false/timestamp stealth => "true"; #/on/false/off preserve => "true"; linkcopy_patterns => { ".*fish.*" }; copylink_patterns => { "non-local.*"}; xdev => "true"; # /on/false/off compare => "mtime"; # ctime/mtime/checksum/sum/byte/binary/any link_type => "absolute"; # /symbolic/relative/hard etc type_check => "true"; force_update => "false"; force_ipv4 => "false"; copy_size => irange("0","50000"); trustkey => "true"; encrypt => "true"; verify => "true"; purge => "false"; findertype => "MacOSX"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "1.2.3.4" , "::1" }; allowallconnects => { "1.2.3.4" , "::1" }; trustkeysfrom => { "1.2.3.4" , "::1" }; # allowusers } ######################################################### bundle server access_rules() { access: # Grant access to the remote client to access the source docs "/src" admit => { "1.2.3.4" }; } cfengine-3.6.2/examples/remove_deadlinks.cf0000664000175100017510000000331512243421446020465 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Test dead link removal # ####################################################### body common control { bundlesequence => { "example" }; } ############################################ bundle agent example { files: "/home/mark/tmp/test_to" -> "someone" depth_search => recurse("inf"), perms => modestuff, action => tell_me; } ############################################ body depth_search recurse(d) { rmdeadlinks => "true"; depth => "$(d)"; } ############################################ body perms modestuff { mode => "o-w"; } ############################################ body action tell_me { report_level => "inform"; } cfengine-3.6.2/examples/isdir.cf0000644000175100017510000000253012316547775016277 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "isdir" expression => isdir("/"); reports: isdir:: "Directory exists.."; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Directory exists.. #@ ``` #+end_src cfengine-3.6.2/examples/edit_replace_string.cf0000664000175100017510000000413712243421446021163 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # File editing # # Normal ordering: # - delete # - replace | colum_edit # - insert # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/tmp/replacestring" create => "true", edit_line => myedit("second"); } ######################################################## bundle edit_line myedit(parameter) { vars: "edit_variable" string => "private edit variable is $(parameter)"; replace_patterns: # replace shell comments with C comments "puppet" replace_with => With("cfengine 3"); } ######################################## # Bodies ######################################## body replace_with With(x) { replace_value => "$(x)"; occurrences => "first"; } ######################################## body select_region MySection(x) { select_start => "\[$(x)\]"; select_end => "\[.*\]"; } cfengine-3.6.2/examples/edit_setvar.cf0000664000175100017510000000353512243421446017467 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Edit variable = value in a text file # ####################################################### body common control { bundlesequence => { "example" }; } ####################################################### bundle agent example { vars: "v[variable_1]" string => "value_1"; "v[variable_2]" string => "value_2"; files: "/tmp/test_setvar" edit_line => setvars_v1("testsetvar.v"); } ####################################################### # For the library ####################################################### bundle edit_line setvars_v1(contexted_array_name) { vars: "parameter_name" slist => getindices("$(contexted_array_name)"); delete_lines: "$(parameter_name).*"; insert_lines: "$(parameter_name) = $($(contexted_array_name)[$(parameter_name)])"; } cfengine-3.6.2/examples/env.cf0000664000175100017510000000031012243421446015732 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "one" }; } body agent control { environment => { "A=123", "B=456", "PGK_PATH=/tmp"}; } bundle agent one { commands: "/usr/bin/env"; } cfengine-3.6.2/examples/file_owner_list_template.cf0000664000175100017510000000306712243421446022235 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # List substitution in bodies # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { vars: "usernames" slist => { "one", "two", "three" }; files: "/home/mark/tmp/test_plain" perms => users("@(usernames)"), create => "true"; } ######################################################### body perms users(x) { mode => "0640"; owners => { @(x) }; } cfengine-3.6.2/examples/loops.cf0000664000175100017510000000267312243421446016314 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { vars: "component" slist => { "cf-monitord", "cf-serverd", "cf-execd" }; "array[cf-monitord]" string => "The monitor"; "array[cf-serverd]" string => "The server"; "array[cf-execd]" string => "The executor, not executioner"; reports: "/bin/echo $(component) is $(array[$(component)])"; } cfengine-3.6.2/examples/report_diffs.cf0000664000175100017510000000341612243421446017642 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Change detect with diff reporting # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/tmp/testfile" -> "me" changes => report; } ######################################################### body changes report { report_changes => "all"; report_diffs => "true"; update_hashes => "true"; } ######################################################### body reporter control { reports => { "file_changes", }; build_directory => "$(sys.workdir)/reports"; report_output => "html"; style_sheet => "cf_enterprise.css"; } cfengine-3.6.2/examples/fileperms.cf0000664000175100017510000000250112243421446017134 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "main" }; } ######################################################### bundle agent main { files: "/tmp/foo" perms => p("at","0750"); } ######################################################### body perms p(user,mode) { owners => { "$(user)" }; mode => "$(mode)"; } cfengine-3.6.2/examples/mount_fs.cf0000664000175100017510000000272012243421446017003 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # cfengine 3 # # cf-agent -f ./cftest.cf -K # body common control { bundlesequence => { "mounts" }; } # bundle agent mounts { storage: "/mnt" mount => nfs("slogans.iu.hio.no","/home"); } ###################################################################### body mount nfs(server,source) { mount_type => "nfs"; mount_source => "$(source)"; mount_server => "$(server)"; #mount_options => { "rw" }; edit_fstab => "true"; unmount => "true"; } cfengine-3.6.2/examples/getregistry.cf0000644000175100017510000000232712316547775017541 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "reg" }; } bundle agent reg { vars: windows:: "value" string => registryvalue("HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine","value3"); reports: "Value extracted: $(value)"; } cfengine-3.6.2/examples/chdir.cf0000664000175100017510000000240112243421446016236 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### body contain cd(dir) { chdir => "${dir}"; useshell => "useshell"; } bundle agent example { commands: "/bin/pwd" contain => cd("/tmp"); } cfengine-3.6.2/examples/linking.cf0000664000175100017510000000424012243421446016603 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # File editing # # Normal ordering: # - delete # - replace | colum_edit # - insert # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: # Make a copy of the password file "/home/mark/tmp/passwd" link_from => linkdetails("/etc/passwd"), move_obstructions => "true"; "/home/mark/tmp/linktest" link_from => linkchildren("/usr/local/sbin"); #child links } ######################################################### body link_from linkdetails(tofile) { source => "$(tofile)"; link_type => "symlink"; when_no_source => "force"; # kill } ######################################################### body link_from linkchildren(tofile) { source => "$(tofile)"; link_type => "symlink"; when_no_source => "force"; # kill link_children => "true"; when_linking_children => "if_no_such_file"; # "override_file"; } cfengine-3.6.2/examples/classvar_convergence.cf0000664000175100017510000000271212243421446021346 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "tryclasses_1" }; } ################################# bundle agent tryclasses_1 { vars: "x" string => "one"; "y" slist => { "linux", "Friday" }; classes: "three" and => { "$(x)", "two" }; "four" or => { @(y) }; "one" expression => "any"; "two" expression => "any"; reports: three:: "Evaluated true"; four:: "List substitution works"; } ################################# cfengine-3.6.2/examples/commands.cf0000664000175100017510000000240712243421446016754 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "my_commands" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent my_commands { commands: Sunday.Hr04.Min05_10.myhost:: "/usr/bin/update_db"; any:: "/etc/mysql/start" contain => setuid("mysql"); } cfengine-3.6.2/examples/iprange.cf0000664000175100017510000000256212243421446016602 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "adhoc_group_1" expression => iprange("192.168.1.50-140"); "adhoc_group_2" expression => iprange("192.168.1.0/24"); reports: adhoc_group_1:: "Some numerology"; adhoc_group_2:: "The masked warriors"; } cfengine-3.6.2/examples/isnewerthan.cf0000644000175100017510000000316112316547775017515 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ touch -t '200102031234.56' /tmp/earlier #@ touch -t '200202031234.56' /tmp/later #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "do_it" and => { isnewerthan("/tmp/later","/tmp/earlier"), "cfengine" }; reports: do_it:: "/tmp/later is older than /tmp/earlier"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /tmp/later is older than /tmp/earlier #@ ``` #+end_src cfengine-3.6.2/examples/isexecutable.cf0000644000175100017510000000256312316547775017650 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "yes" expression => isexecutable("/bin/ls"); reports: yes:: "/bin/ls is an executable file"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /bin/ls is an executable file #@ ``` #+end_src cfengine-3.6.2/examples/unpack_method_calls.cf0000644000175100017510000000136612316547775021172 0ustar00a10038a1003800000000000000#+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "todo" slist => { "call_1,a,b", "call_2,x,y", "call_2,p,q" }; methods: "call" usebundle => unpack($(todo)); } bundle agent unpack(list) { vars: "split" slist => splitstring($(list), ",", "100"); "method" string => nth("split", "0"); "param1" string => nth("split", "1"); "param2" string => nth("split", "2"); methods: "relay" usebundle => $(method)($(param1), $(param2)); } bundle agent call_1(p1, p2) { reports: "$(this.bundle): called with parameters $(p1) and $(p2)"; } bundle agent call_2(p1, p2) { reports: "$(this.bundle): called with parameters $(p1) and $(p2)"; } #+end_src cfengine-3.6.2/examples/definitions.cf0000664000175100017510000000541612243421446017471 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Testing some variable/class definitions - note scope # # Use browser -f promise_output_agent.html to view # body common control { bundlesequence => { "mycommon", "assign" }; } ########################################################### bundle common mycommon { classes: "global_class" expression => "any"; "another_global" xor => { "any", "linux", "solaris"}; } ########################################################### bundle agent assign { vars: "scalar" int => "16k"; # "xxx" string => readfile( "/home/mark/tmp/testfile" , "33" ); "ran" int => randomint(4,88); # "yyy" slist => { readstringlist("/home/mark/tmp/testlist","#[a-zA-Z0-9 ]*","[^a-zA-Z0-9]",15,4000) }; # "zzz" slist => { readstringlist("/home/mark/tmp/testlist2","#[^\n]*",",",5,4000) }; # "aaa" ilist => { readintlist("/home/mark/tmp/testilist","#[a-zA-Z0-9 ]*",",",10,4000) }; "dim_array" int => readstringarray("array_name","/etc/passwd","#[^\n]*",":",10,4000); classes: # Standard aliasing "myclass" or => { "solaris", "linux" }; # got_array is a class that says whether the read was successful # array_name[] is the lval # Create a distribution "my_dist" dist => { "10", "20", "30", "40" }; # # Now like "alerts" in cf2 # reports: "Dimension of passwd array $(dim_array)"; "Read item from list: $(yyy)"; # Any kind of rule can define classes on exit "Read this file: [$(xxx)] ..." classes => persist("alertclass","20"); } ###################################################################### body classes persist(class,time) { promise_repaired => { "$(class)" }; persist_time => "$(time)"; timer_policy => "absolute"; } cfengine-3.6.2/examples/storage.cf0000664000175100017510000000270212243421446016615 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # cfengine 3 # # cf-agent -f ./cftest.cf -K # body common control { bundlesequence => { "storage" }; } # bundle agent storage { storage: "/usr" volume => mycheck("11G"); "/" volume => mycheck("60%"); } ###################################################################### body volume mycheck(free) # reusable template { check_foreign => "false"; freespace => "$(free)"; sensible_size => "10000"; sensible_count => "2"; } cfengine-3.6.2/examples/package_msi_file.cf0000664000175100017510000000406312243421446020415 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # MSI package managment using file name # body common control { bundlesequence => { "packages" }; } ############################################# bundle agent packages { vars: "match_package" slist => { "7zip-4.65-x86_64.msi" }; packages: "$(match_package)" package_policy => "add", package_method => msi_fmatch; } ############################################# body package_method msi_fmatch { package_changes => "individual"; package_file_repositories => { "$(sys.workdir)\software_updates\windows", "s:\su" }; package_installed_regex => ".*"; package_name_regex => "^(\S+)-(\d+\.?)+"; package_version_regex => "^\S+-((\d+\.?)+)"; package_arch_regex => "^\S+-(\d+\.?)+(^.+)"; package_name_convention => "$(name)-$(version)-$(arch).msi"; package_add_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i"; package_update_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i"; package_delete_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x"; } cfengine-3.6.2/examples/tidy_all_files.cf0000664000175100017510000000414212243421446020134 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Deleting files, like cf2 tidy age=0 r=inf # ####################################################### body common control { any:: bundlesequence => { "example" }; } ############################################ bundle agent example { files: "/home/mark/tmp/test_to" delete => tidyfiles, file_select => zero_age, depth_search => recurse("inf"); # Now delete the parent. "/home/mark/tmp/testcopy" delete => tidyfiles; } ######################################################### body depth_search recurse(d) { #include_basedir => "true"; depth => "$(d)"; } ######################################################### body delete tidyfiles { dirlinks => "delete"; rmdirs => "true"; } ######################################################### body file_select zero_age # # we can build old "include", "exclude", and "ignore" # from these as standard patterns - these bodies can # form a library of standard patterns # { mtime => irange(ago(1,0,0,0,0,0),now); file_result => "mtime"; } cfengine-3.6.2/examples/remake_outputs.pl0000755000175100017510000001321312352022221020230 0ustar00a10038a1003800000000000000#!/usr/bin/perl use warnings; use strict; use Data::Dumper; use Getopt::Long; use File::Basename; use Sys::Hostname; $|=1; # autoflush my %options = ( check => 0, verbose => 0, veryverbose => 0, help => 0, cfagent => "../cf-agent/cf-agent", workdir => "/tmp", ); GetOptions(\%options, "help|h!", "check|c!", "cfagent=s", "workdir=s", "verbose|v!", "veryverbose!", ); if ($options{help}) { print <; close $fh; my $copy = $data; if ($data =~ m/#\+begin_src cfengine3\n(.+?)\n#\+end_src/s) { my $example = $1; my $prep; if ($data =~ m/#\+begin_src prep\n(.+?)\n#\+end_src/s) { $prep = [split "\n", $1]; } $data =~ s/(#\+begin_src example_output( no_check)?\n)(.*?)(#\+end_src)/$1 . rewrite_output($file, $prep, $example, $3) . $4/es; if (!defined($2) && $data ne $copy) { print "$file: output differs from original..."; if ($options{check}) { $rc = 1; print "\n"; next; } open my $fh, '>', $file or warn "Could not open $file: $!"; print $fh $data; close $fh; print "new output written!\n"; } } else { warn "No example to run was found in $file, skipping"; } } exit $rc; sub rewrite_output { my $file = shift @_; my $prep = shift @_; my $example = shift @_; my $old_output = shift @_; my $new_output = run_example($file, $prep, $example); if (equal_outputs($old_output, $new_output, $file)) { return $old_output; } if (defined $new_output && length $new_output > 0) { $new_output =~ s/^/#@ /mg; $new_output = "#@ ```\n$new_output#@ ```\n"; } return $new_output; } sub equal_outputs { # strip out date, e.g. '2013-12-16T20:48:24+0200' my $x = shift @_; my $y = shift @_; my $file = shift @_; my ($tempfile, $base) = get_tempfile($file); $x =~ s/^#@ ```\s+//mg; $y =~ s/^#@ ```\s+//mg; $x =~ s/^(#@ )//mg; $x =~ s/^[-0-9T:+]+\s+//mg; $y =~ s/^(#@ )//mg; $y =~ s/^[-0-9T:+]+\s+//mg; $x =~ s/.*RANDOM.*//mg; $y =~ s/.*RANDOM.*//mg; if ($x ne $y) { open my $fha, '>', "$tempfile.a" or die "Could not write to diff output $tempfile.a: $!"; print $fha $x; close $fha; open my $fhb, '>', "$tempfile.b" or die "Could not write to diff output $tempfile.b: $!"; print $fhb $y; close $fhb; system("diff -u $tempfile.a $tempfile.b") if $options{verbose}; return 0; } return 1; } sub get_tempfile { my $file = shift @_; my $base = basename($file); my $tempfile = "$options{workdir}/$base"; mkdir $options{workdir} unless -e $options{workdir}; return ($tempfile, $base); } sub run_example { my $file = shift @_; my $prep = shift @_ || []; my $example = shift @_; my ($tempfile, $base) = get_tempfile($file); open my $fh, '>', $tempfile or die "Could not write to $tempfile: $!"; print $fh $example; close $fh; chmod 0600, $tempfile; foreach (@$prep) { s/^#@ //; # skip Markdown markup like ``` next unless m/^\w/; s/FILE/$tempfile/g; s/\$HOSTNAME/hostname()/ge; print "processing $file: Running prep '$_'" if $options{verbose}; system($_); } $ENV{EXAMPLE} = $base; $ENV{CFENGINE_COLOR} = 0; my $cmd = "$options{cfagent} -D_cfe_output_testing -nKf $tempfile 2>&1"; open my $ofh, '-|', $cmd; my $output = join '', <$ofh>; close $ofh; print "Test file: $file\nCommand: $cmd\n\nNEW OUTPUT: [[[$output]]]\n\n\n" if $options{verbose}; return $output; } cfengine-3.6.2/examples/hub.cf0000664000175100017510000000431212243421446015726 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Remote value from hub # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-d2] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { vars: "remote_value" string => hubknowledge("monitoring"); reports: "Global knowledge: $(remote_value)"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; allowusers => { "mark" }; } ######################################################### bundle server access_rules() { access: "discovered value" handle => "monitoring", resource_type => "literal", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/active_directory.cf0000664000175100017510000000523312243421446020512 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################################### # active_directory.cf - Extract Data From Windows Domain Controllers # # NOTE: Since we don't supply any credentials in this policy file, # the Domain Controller must allow anonymous bind. Also, # the user "NT AUTHORITY\ANONYMOUS LOGON" must be granted access # to the resources we want to read. # ######################################################################### bundle agent active_directory { vars: # NOTE: Edit this to your domain, e.g. "corp", may also need more DC's after it "domain_name" string => "cftesting"; "user_name" string => "Guest"; # NOTE: We can also extract data from remote Domain Controllers dummy.DomainController:: "domain_controller" string => "localhost"; "userlist" slist => ldaplist( "ldap://$(domain_controller)", "CN=Users,DC=$(domain_name),DC=com", "(objectClass=user)", "sAMAccountName", "subtree", "none"); classes: dummy.DomainController:: "gotuser" expression => ldaparray( "userinfo", "ldap://$(domain_controller)", "CN=$(user_name),CN=Users,DC=$(domain_name),DC=com", "(name=*)", "subtree", "none"); reports: dummy.DomainController:: "Username is \"$(userlist)\""; dummy.gotuser:: "Got user data; $(userinfo[name]) has logged on $(userinfo[logonCount]) times"; } cfengine-3.6.2/examples/file_change_detection.cf0000664000175100017510000000404712243421446021437 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple backgrounding # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## body agent control { agentaccess => { "mark", "root" }; } ######################################################## bundle agent example { files: "/home/mark/tmp" -> "me" changes => tripwire, depth_search => recurse("inf"), action => background; "/home/mark/LapTop/words" -> "you" changes => tripwire, depth_search => recurse("inf"); } ######################################################### body changes tripwire { hash => "md5"; report_changes => "content"; update_hashes => "true"; } ######################################################### body action background { background => "true"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/sum.cf0000644000175100017510000000275212316547775015777 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "adds_to_six" ilist => { "1", "2", "3" }; "six" real => sum("adds_to_six"); "adds_to_zero" rlist => { "1.0", "2", "-3e0" }; "zero" real => sum("adds_to_zero"); reports: "six is $(six), zero is $(zero)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: six is 6.000000, zero is 0.000000 #@ ``` #+end_src cfengine-3.6.2/examples/Makefile.am0000664000175100017510000000106212411001073016654 0ustar00a10038a1003800000000000000examplesdir = $(docdir)/examples dist_examples_DATA = $(srcdir)/*.cf dist_examples_SCRIPTS = remake_outputs.pl FAKE_WORKDIR=/tmp/fake-cfengine-workdir MAINTAINERCLEANFILES = Makefile.in mdate-sh # only re-run the outputs for examples that already have an example_output block remake: perl ./remake_outputs.pl $(shell grep -l example_output $(dist_examples_DATA)) recheck: perl ./remake_outputs.pl -c $(shell grep -l example_output $(dist_examples_DATA)) recheck_verbose: perl ./remake_outputs.pl -v -c $(shell grep -l example_output $(dist_examples_DATA)) cfengine-3.6.2/examples/acl_secret.cf0000664000175100017510000000273712243421446017265 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "acls" }; } ######################################### bundle agent acls { files: windows:: "c:\Secret" acl => win, depth_search => include_base, comment => "Secure the secret directory from unauthorized access"; } ######################################### body acl win { acl_method => "overwrite"; aces => { "user:Administrator:rwx" }; } ######################################### body depth_search include_base { include_basedir => "true"; } cfengine-3.6.2/examples/namespace2.cf0000664000175100017510000000067612243421446017177 0ustar00a10038a1003800000000000000 body file control { namespace => "name2"; } bundle agent mymethod(one,two) { files: "/tmp/$(one)$(two)" create => "true", edit_line => makefile, perms => name1:settings; reports: "test $(one) $(two) in $(this.namespace)_$(this.bundle)"; } bundle edit_line makefile { insert_lines: "THIS IS NAME2"; reports: "makefile in name 2"; } body perms settings { mode => "666"; } cfengine-3.6.2/examples/failsafe.cf0000664000175100017510000000235512243421446016727 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Failsafe file # body common control { # Reads default # /var/cfengine/inputs/promises.cf # /var/cfengine/inputs/failsafe.cf bundlesequence => { "update" }; inputs => { "update.cf" # a simple recovery file too? }; } cfengine-3.6.2/examples/create_filedir.cf0000664000175100017510000000372412243421446020117 0ustar00a10038a1003800000000000000# Copyright (C) CFEngine AS # This file is part of CFEngine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of CFEngine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test create files # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/home/mark/tmp/test_plain" #@ The promiser specifies the path and name of the file. perms => system, create => "true"; #@ The `perms` attribute sets the file permissions as defined in the `system` #@ body below. The `create` attribute makes sure that the files exists. If it #@ doesn't, CFEngine will create it. "/home/mark/tmp/test_dir/." perms => system, create => "true"; #@ The trailing `/.` in the filename tells CFEngine that the promiser is a #@ directory. } ######################################################### body perms system { mode => "0640"; } #@ This body sets permissions to "0640" ######################################################### cfengine-3.6.2/examples/orchestrate_dragon_load_balancer.cf0000664000175100017510000001607712243421446023666 0ustar00a10038a1003800000000000000############################################################ # # Chinese Dragon Dancing on a Star # # This method works with either Community or Enterprise. # and uses named signals # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # # Start a switch file /tmp/switch_file with # host1 ON # host2 ON # host3 ON etc ############################################################ body common control { bundlesequence => { "dragon_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################################ bundle agent dragon_symphony { methods: # We have to seed the beginning by creating the dragon # /tmp/dragon_localhost "dragon" usebundle => upgrade_host("localhost","host1","chapter1"); "dragon" usebundle => upgrade_host("host1","host2","chapter2"); "dragon" usebundle => upgrade_host("host2","host3","chapter3"); "dragon" usebundle => upgrade_host("host3","host4","chapter4"), classes => if_ok("finale"); finale:: "dragon" usebundle => restore_final("host4"), comment => "Restore all the deactivated satellites"; reports: finale:: "The dragon is slain!!!" printfile => visitors_book("/tmp/shoo_dragon_host4"); "And the switch state is..." printfile => visitors_book("/tmp/switch_file"); } ############################################################ # Define the ############################################################ bundle agent chapter1(x) { # Do something significant here reports: host1:: " ----> Breathing fire on $(x)"; } ################################ bundle agent chapter2(x) { # Do something significant here reports: host2:: " ----> Breathing fire on $(x)"; } ################################ bundle agent chapter3(x) { # Do something significant here reports: host3:: " ----> Breathing fire on $(x)"; } ################################ bundle agent chapter4(x) { # Do something significant here reports: host4:: " ----> Breathing fire on $(x)"; } ############################################################ # Orchestration wrappers ############################################################ bundle agent upgrade_host(predecessor,satellite,method) { # This is a wrapper for the orchestration will be acted on # first by the dragon's lair and then by the satellite vars: "dragons_lair" string => "host0"; files: # We start in the dragon's lair .. "/tmp/unleash_dragon" comment => "Unleash the dragon", rename => to("/tmp/enter_the_dragon"), classes => if_repaired("dispatch_dragon_$(satellite)"), ifvarclass => "$(dragons_lair)"; # if we are the dragon's lair, welcome the dragon back, shooed from the satellite "/tmp/enter_the_dragon" comment => "Returning from a visit to a satellite", copy_from => secure_cp("/tmp/shoo_dragon_$(predecessor)","$(predecessor)"), classes => if_repaired("dispatch_dragon_$(satellite)"), ifvarclass => "$(dragons_lair)"; # If we are a satellite, receive the dragon from its lair "/tmp/enter_the_dragon" comment => "Wait for our cue or relay/conductor baton", copy_from => secure_cp("/tmp/dragon_$(satellite)","$(dragons_lair)"), classes => if_repaired("cue_action_on_$(satellite)"), ifvarclass => "$(satellite)"; methods: "check in at home" comment => "Edit the load balancer?", usebundle => next_host("$(satellite)","$(predecessor)"), classes => if_repaired("send_the_dragon_to_$(satellite)"), ifvarclass => "dispatch_dragon_$(satellite)"; "dragon visits" comment => "One off activity that the nodes carry out while the dragon visits", usebundle => $(method)("$(satellite)"), classes => if_repaired("send_the_dragon_back_from_$(satellite)"), ifvarclass => "cue_action_on_$(satellite)"; files: # hub/lair hub signs the book too and schedules the dragon for next satellite "/tmp/dragon_$(satellite)" create => "true", comment => "Add our signature to the dragon's tail", edit_line => sign_visitor_book("Dragon returned from $(predecessor)"), ifvarclass => "send_the_dragon_to_$(satellite)"; # Satellite signs the book and shoos dragon for hub to collect "/tmp/shoo_dragon_$(satellite)" create => "true", comment => "Add our signature to the dragon's tail", edit_line => sign_visitor_book("Dragon visited $(satellite) and did: $(method)"), ifvarclass => "send_the_dragon_back_from_$(satellite)"; reports: "Done $(satellite)", ifvarclass => "$(satellite)"; } ############################################################ bundle agent next_host(name,pred) { files: "/tmp/enter_the_dragon" comment => "Add our signature to the dragon's tail", edit_line => append_if_no_line("Switch new dragon's target $(name)"); # Edit the switch file "/tmp/switch_file" comment => "Restore whatever is missing and comment out", edit_line => restore_and_comment("$(name)","$(pred)"), classes => if_repaired("reload_switch_$(name)"); reports: !problem:: "Returned from $(pred), heading out to $(name)"; " X Restoring $(pred) and switching new dragon's target $(name)" ifvarclass => "reload_switch_$(name)"; } ############################################################ bundle agent restore_final(name) { files: host0:: "/tmp/switch_file" comment => "Restore whatever is missing and comment out", edit_line => restore_and_comment("NONE","$(name)"), classes => if_repaired("reload_switch"); reports: reload_switch:: " X Restoring $(name) to tidy up loose ends"; } ############################################################ bundle edit_line sign_visitor_book(s) { insert_lines: "/tmp/enter_the_dragon" comment => "Import the current visitor's book", insert_type => "file"; "$(s)" comment => "Append this string to the visitor's book"; } # bundle edit_line restore_and_comment(name,pred) { replace_patterns: "$(name) ON" replace_with => value("$(name) OFF"), comment => "Uncomment the predecessor to reactivate"; "$(pred) OFF" replace_with => value("$(pred) ON"), comment => "Comment out the new host", classes => if_repaired("show_switch_$(name)"); reports: !problem:: "The state of the switch was:", printfile => visitors_book("/tmp/switch_file"), ifvarclass => "show_switch_$(name)"; } ############################################################ bundle server access_rules() { access: "/tmp" admit => { "127.0.0.1" }; "did.*" resource_type => "context", admit => { "127.0.0.1" }; } ############################################################ body printfile visitors_book(file) { file_to_print => "$(file)"; number_of_lines => "100"; } cfengine-3.6.2/examples/disable.cf0000664000175100017510000000237712243421446016564 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "my_disable" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent my_disable { files: "/home/mark/tmp/test_create" rename => disable; "/home/mark/tmp/rotate_my_log" rename => rotate("4"); } cfengine-3.6.2/examples/win_schedule.cf0000664000175100017510000000415412243421446017625 0ustar00a10038a1003800000000000000######################################################################### # # scheduling.cf - Command Execution Scheduling # # NOTE: Commands can be executed based on any class expression. # Examples include execution of other commands (sequencing), # time, OS, hostname or the outcome of another promise. # If a shell wrapper is not needed, removing it will increase # security and performance. # ######################################################################### bundle agent system_scheduling { vars: # Command definitions are given in cmd[index]. # The dependencies of the commands are dep_cmd[index], as boolean class expressions. # Comments are given as comment_cmd[index] "cmd[1]" string => "$(sys.cf_key)"; "dep_cmd[1]" string => "cmd2_success"; "comment_cmd[1]" string => "Check that a Cfengine key is generated if command 2 has run (dummy)"; windows:: "cmd[2]" string => "\"$(sys.winsysdir)\shutdown.exe\" /r /c \"Cfengine automatic restart\" /t 120"; "dep_cmd[2]" string => "Monday.Hr05.Min00_05"; "comment_cmd[2]" string => "Restart windows every week"; "cmd[3]" string => "$(sys.winsysdir)\cscript.exe \"$(sys.workdir)\script1.vbs\" //Nologo > \"$(sys.workdir)\script1_out.txt\""; "dep_cmd[3]" string => "Hr05.Min05_10"; "comment_cmd[3]" string => "Run a script and save its output for later reference (needs to be run in shell)"; !windows:: "cmd[2]" string => "/bin/echo Hello World!"; "dep_cmd[2]" string => "Hr12.Min00_05"; "comment_cmd[2]" string => "Print a message (dummy)"; any:: "cmd_index" slist => getindices("cmd"); commands: # Runs a command if its dependencies are satisfied "$(cmd[$(cmd_index)])" classes => if_repaired("cmd$(cmd_index)_success"), ifvarclass => "$(dep_cmd[$(cmd_index)])", contain => in_shell, comment => "$(comment_cmd[$(cmd_index)])"; } cfengine-3.6.2/examples/edit_column_files.cf0000664000175100017510000000522212243421446020635 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # File editing # # Normal ordering: # - delete # - replace | colum_edit # - insert # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "bun" }; } ######################################################## bundle agent bun { vars: "userset" slist => { "one", "two", "three" }; files: # Make a copy of the password file "/home/mark/tmp/passwd" create => "true", edit_line => set_user_field("mark","6","/home/dir"); "/home/mark/tmp/group" create => "true", edit_line => append_user_field("wheel","4","@(bun.userset)"); } ######################################################## bundle edit_line set_user_field(user,field,val) { field_edits: "$(user).*" # Set field of the file to parameter edit_field => col(":","$(field)","$(val)","set"); } ######################################################## bundle edit_line append_user_field(user,field,allusers) { vars: "val" slist => { @(allusers) }; field_edits: "$(user).*" # Set field of the file to parameter edit_field => col(":","$(field)","$(val)","alphanum"); } ######################################## # Bodies ######################################## body edit_field col(split,col,newval,method) { field_separator => "$(split)"; select_field => "$(col)"; value_separator => ","; field_value => "$(newval)"; field_operation => "$(method)"; extend_fields => "true"; allow_blank_fields => "true"; } cfengine-3.6.2/examples/hostrange.cf0000664000175100017510000000241012243421446017137 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "compute_nodes" expression => hostrange("cpu-","01-32"); reports: compute_nodes:: "No computer is a cluster"; } cfengine-3.6.2/examples/monitord.cf0000664000175100017510000000246212243421446017007 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################### body monitor control { #version => "1.2.3.4"; forgetrate => "0.7"; histograms => "true"; tcpdump => "false"; tcpdumpcommand => "/usr/sbin/tcpdump -i eth1 -n -t -v"; # on linux linux:: # sensor => readfile("/proc/cpu/temperature"); } cfengine-3.6.2/examples/groupexists.cf0000644000175100017510000000301412332665147017547 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "gname" expression => groupexists("sys"); "gid" expression => groupexists("0"); reports: gname:: "Group exists by name"; gid:: "Group exists by id"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Group exists by name #@ R: Group exists by id #@ ``` #+end_src cfengine-3.6.2/examples/win_emergency.cf0000664000175100017510000000350412243421446020005 0ustar00a10038a1003800000000000000######################################################################### # # win_emergency.cf - Emergency Policy To Close Potential Security Holes # # NOTE: The class "emergency" may be set automatically by Cfengine # based on some criteria, or it may be explicitly set by a remote # execution of cf-agent through cf-runagent (if this is allowed # by the server control policy). # ######################################################################### bundle agent win_emergency { vars: "disable_services" slist => { "RemoteRegistry" # Windows Remote Management }; "secure_files" slist => { "C:\Secret", "$(sys.workdir)\secret.txt" }; "close_ports" slist => { "6510", "9300" }; commands: emergency:: "\"$(sys.winsysdir)\netsh.exe\"" args => "firewall add portopening ALL $(close_ports) \"Port $(close_ports)\" DISABLE", comment => "Close firewall ports on emergency"; databases: emergency:: "HKEY_LOCAL_MACHINE\SOFTWARE\Cfengine AS\Cfengine" database_operation => "create", database_rows => { "emergency,REG_SZ,This is an emergency!" } , database_type => "ms_registry", comment => "Create emergency policy registry settings"; files: emergency:: "$(secure_files)" acl => strict, comment => "Secure important file access on emergency"; services: emergency:: "$(disable_services)" service_policy => "disable", comment => "Disable security-relevant services on emergency"; } cfengine-3.6.2/examples/userexists.cf0000644000175100017510000000256412316547775017412 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "ok" expression => userexists("root"); reports: ok:: "Root exists"; !ok:: "Root does not exist"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Root exists #@ ``` #+end_src cfengine-3.6.2/examples/epimenides.cf0000664000175100017510000000224312243421446017273 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "g" }; } bundle common g { vars: "head" string => "Swallow my ${tail}"; "tail" string => "behind my "; reports: "Go $(head)"; } cfengine-3.6.2/examples/string_split.cf0000644000175100017510000000334112316547775017707 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "split1" slist => string_split("one:two:three", ":", "10"); "split2" slist => string_split("one:two:three", ":", "1"); "split3" slist => string_split("alpha:xyz:beta", "xyz", "10"); reports: "split1: $(split1)"; # will list "one", "two", and "three" "split2: $(split2)"; # will list "one:two:three" "split3: $(split3)"; # will list "alpha:" and ":beta" } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: split1: one #@ R: split1: two #@ R: split1: three #@ R: split2: one:two:three #@ R: split3: alpha: #@ R: split3: :beta #@ ``` #+end_src cfengine-3.6.2/examples/changedbefore.cf0000664000175100017510000000240212243421446017722 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "do_it" and => { changedbefore("/tmp/earlier","/tmp/later") }; reports: do_it:: "Earlier than later!"; } cfengine-3.6.2/examples/hostswithclass.cf0000664000175100017510000000056512243421446020240 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "example" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent example { vars: am_policy_hub:: "host_list" slist => hostswithclass( "debian", "name" ); files: am_policy_hub:: "/tmp/master_config.cfg" edit_line => insert_lines("host=$(host_list)"), create => "true"; } cfengine-3.6.2/examples/reporttofile.cf0000664000175100017510000000221612243421446017667 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } # bundle agent example { reports: "$(sys.date),This is a report" report_to_file => "/tmp/test_log"; } cfengine-3.6.2/examples/parsestringarray.cf0000664000175100017510000000111712243421446020550 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { test("/tmp/test.txt") }; } bundle agent example(f) { vars: ####################################### # Define data inline for convenience ####################################### "table" string => "one: a two: b three: c"; ####################################### "dim" int => parsestringarray( "items", "$(table)", "\s*#[^\n]*", ":", "1000", "200000" ); "keys" slist => getindices("items"); reports: "$(keys)"; } cfengine-3.6.2/examples/getuid.cf0000644000175100017510000000250012316547775016443 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "uid" int => getuid("root"); reports: "root's uid is $(uid)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: root's uid is 0 #@ ``` #+end_src cfengine-3.6.2/examples/variablesmatching.cf0000644000175100017510000000332212316547775020650 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "all" slist => variablesmatching(".*"); "v" slist => variablesmatching("default:sys.cf_version.*"); reports: "Variables matching 'default:sys.cf_version.*' = $(v)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Variables matching 'default:sys.cf_version.*' = default:sys.cf_version_major #@ R: Variables matching 'default:sys.cf_version.*' = default:sys.cf_version_patch #@ R: Variables matching 'default:sys.cf_version.*' = default:sys.cf_version #@ R: Variables matching 'default:sys.cf_version.*' = default:sys.cf_version_minor #@ ``` #+end_src cfengine-3.6.2/examples/service_disable.cf0000664000175100017510000000246512243421446020302 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "winservice" }; } ########################################################### bundle agent winservice { vars: "bad_services" slist => { "Alerter", "ClipSrv" }; services: windows:: "$(bad_services)" service_policy => "disable", comment => "Disable services that create security issues"; } cfengine-3.6.2/examples/sql_table_structure.cf0000664000175100017510000000201712411001073021221 0ustar00a10038a1003800000000000000# # Database promises are introduced in CFEngine Community edition 3.3.0 # body common control { bundlesequence => { "databases" }; } bundle agent databases { databases: "cfengine_db/users" database_operation => "create", database_type => "sql", database_columns => { "username,varchar,50", "password,varchar,80", "email,varchar,20", }, database_server => local_mysql("root", ""); } body database_server local_mysql(username, password) { db_server_owner => "$(username)"; db_server_password => "$(password)"; db_server_host => "localhost"; db_server_type => "mysql"; db_server_connection_db => "mysql"; } body database_server local_postgresql(username, password) { db_server_owner => "$(username)"; db_server_password => "$(password)"; db_server_host => "localhost"; db_server_type => "postgres"; db_server_connection_db => "postgres"; } cfengine-3.6.2/examples/execd.cf0000664000175100017510000000244512243421446016245 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "cf_null" }; } body executor control { mailto => "MARK@iu.hio.no"; mailfrom => "cfengine@domain.tld"; smtpserver => "MAIL-out.hio.no"; mailmaxlines => "50"; schedule => { "Min00_05", "Min30_35" }; exec_command => "/var/cfengine/bin/cf-agent"; } cfengine-3.6.2/examples/product.cf0000644000175100017510000000270612316547775016652 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "series" rlist => { "1.1", "2.2", "3.3", "5.5", "7.7" }; "prod" real => product("series"); "sum" real => sum("series"); reports: "Product result: $(prod) > $(sum)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Product result: 338.207100 > 19.800000 #@ ``` #+end_src cfengine-3.6.2/examples/defaults.cf0000664000175100017510000000424512243421446016764 0ustar00a10038a1003800000000000000 # Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Default values for variables and parameters, introduced 3.4.0 # body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { defaults: # We can have default values even if variables are not defined at all. # This is equivalent to a variable definition, so not particularly useful. "X" string => "I am a default value"; "Y" slist => { "I am a default list item 1", "I am a default list item 2" }; methods: # More useful, defaults if parameters are passed to a param bundle "example" usebundle => mymethod("","bbb"); reports: "The default value of X is $(X)"; "The default value of Y is $(Y)"; } ########################################################### bundle agent mymethod(a,b) { vars: "no_return" string => "ok"; # readfile("/dont/exist","123"); defaults: "a" string => "AAAAAAAAA", if_match_regex => ""; "b" string => "BBBBBBBBB", if_match_regex => ""; "no_return" string => "no such file"; reports: "The value of a is $(a)"; "The value of b is $(b)"; "The value of no_return is $(no_return)"; } cfengine-3.6.2/examples/users_type.cf0000664000175100017510000000163312400110676017350 0ustar00a10038a1003800000000000000### Users main BEGIN ### bundle agent main { vars: "users" slist => { "jack", "john" }; "skel" string => "/etc/skel"; users: !windows:: "$(users)" policy => "present", home_dir => "/home/$(users)", home_bundle => home_skel($(users), $(skel)); } ### Users main END ### ### Home Bundle BEGIN ### bundle agent home_skel(user, skel) # @brief Initalize a users home directory with the contents of skel # @param user The users home directory to create # @param skel The directory to seed the users home with { files: "/home/$(user)/." create => "true", copy_from => seed_cp($(skel)), depth_search => recurse("inf"); } ### Home Bundle END ### ### Locked User BEGIN ### bundle agent service_accounts { vars: "users" slist => { "apache", "libuuid" }; users: !windows:: "$(users)" policy => "locked"; } ### Locked User END ### cfengine-3.6.2/examples/package_rpm.cf0000664000175100017510000000464512243421446017432 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Package managment # body common control { bundlesequence => { "packages" }; } ############################################# bundle agent packages { vars: "exact_package" slist => { "apache2", "kernel-default" }; "version[OpenOffice_org-hyphen]" string => "1.2.3"; "version[kernel-default]" string => "2.6.27.7-9.1"; packages: "$(exact_package)" package_policy => "verify", package_method => rpm, package_select => ">=", package_architectures => { "x86_64" }, package_version => "$(version[$(exact_package)])"; } ############################################# body package_method rpm { any:: package_changes => "individual"; package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; # Remember to escape special characters like | package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s|]+).*"; package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s|]+).*"; package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; package_installed_regex => "i.*"; package_name_convention => "$(name).$(arch)"; package_add_command => "/bin echo /bin/rpm -i "; package_delete_command => "/bin/rpm -e --nodeps"; package_verify_command => "/bin/rpm -V"; package_noverify_regex => ".*[^\s].*"; #package_noverify_returncode => "-1"; } cfengine-3.6.2/examples/controlclasses.cf0000664000175100017510000000351612243421446020213 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. bundle common categories { classes: "myclass1" expression => "any"; "myclass2" expression => "any"; vars: "common" slist => { "update.cf", }; "extra1" slist => { "reasons to be cheerful, part 1", }; "extra2" slist => { "reasons to be cheerful, part 2", }; "in_any" slist => { "update.cf", }; "in1" slist => { "in1/in1.cf", }; "in1" slist => { "in2/in1.cf", }; } body common control { myclass1:: bundlesequence => { @(categories.common), "extra1" }; inputs => { @(categories.in1), @(categories.in_any) }; myclass2:: bundlesequence => { @(categories.common), "extra2" }; inputs => { @(categories.in1), @(categories.in_any) }; } bundle edit_line name { reports: "xxx"; } cfengine-3.6.2/examples/isplain.cf0000644000175100017510000000275012316547775016630 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "fileisplain" expression => isplain("/etc/passwd"); "dirisnotplain" not => isplain("/"); reports: fileisplain:: "/etc/passwd is plain.."; dirisnotplain:: "/ is not plain.."; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /etc/passwd is plain.. #@ R: / is not plain.. #@ ``` #+end_src cfengine-3.6.2/examples/copy_edit.cf0000664000175100017510000000525312243421446017134 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Copy and edit convergently # ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { vars: "source" string => "/tmp"; "dest" string => "/tmp"; files: "/$(dest)/staging-file" comment => "Copy from source to buffer", copy_from => cp("$(source)/source-template"), classes => satisfied("copy_ok"); copy_ok:: "/$(dest)/final-file" comment => "Build a file template and expand keys", edit_line => myedits("/$(dest)/staging-file"), edit_defaults => empty; } ######################################################### body copy_from cp(from) { source => "$(from)"; compare => "mtime"; type_check => "true"; } ######################################################## bundle edit_line myedits(f) { insert_lines: "$(f)" comment => "Populate empty file", insert_type => "file"; replace_patterns: "TEMPLATE_HOST_KEY" comment => "Replace a place-marker with the name of this host", replace_with => rp("$(sys.host)"); } ######################################################## body replace_with rp(x) { replace_value => "$(x)"; occurrences => "all"; } ######################################################### body classes satisfied(x) { promise_repaired => { "$(x)" }; persist_time => "0"; } ####################################################### body edit_defaults empty { empty_file_before_editing => "true"; } cfengine-3.6.2/examples/join.cf0000644000175100017510000000410212316547775016121 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "mylist" slist => { "one", "two", "three", "four", "five" }; "datalist" data => parsejson('[1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three",]'); "mylist_str" string => format("%S", mylist); "datalist_str" string => format("%S", datalist); "myscalar" string => join("->", mylist); "datascalar" string => join("->", datalist); reports: "Concatenated $(mylist_str): $(myscalar)"; "Concatenated $(datalist_str): $(datascalar)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Concatenated { "one", "two", "three", "four", "five" }: one->two->three->four->five #@ R: Concatenated [1,2,3,"one","two","three","long string","four","fix","six","one","two","three"]: 1->2->3->one->two->three->long string->four->fix->six->one->two->three #@ ``` #+end_src cfengine-3.6.2/examples/package_freebsd.cf0000664000175100017510000000432612243421446020242 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Package managment # body common control { bundlesequence => { "packages" }; } ############################################# body agent control { environment => { "PACKAGESITE=ftp://freebsd-src.es.net/pub/FreeBSD/ports/i386/packages-7.2-release/All/" }; } ############################################# bundle agent packages { vars: # Test the simplest case -- leave everything to the yum smart manager "match_package" slist => { "wget-1.11.4" }; packages: "$(match_package)" package_policy => "add", package_method => freebsd; } ############################################# body package_method freebsd { any:: package_changes => "individual"; # Could use rpm for this package_list_command => "/usr/sbin/pkg_info"; # Remember to escape special characters like | package_list_name_regex => "([^-]+).*"; package_list_version_regex => "[^-]+-([^\s]+).*"; package_name_regex => "([^-]+).*"; package_version_regex => "[^-]+-([^\s]+).*"; package_installed_regex => ".*"; package_name_convention => "$(name)-$(version)"; package_add_command => "/usr/sbin/pkg_add -r"; package_delete_command => "/usr/sbin/pkg_delete"; } cfengine-3.6.2/examples/edit_insert_lines_silly.cf0000664000175100017510000000363212243421446022073 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Insert a number of lines # ####################################################### body common control { any:: bundlesequence => { "insert" }; } ####################################################### bundle agent insert { vars: "v" slist => { "One potato", "Two potato", "Three potatoe", "Four" }; files: "/tmp/test_insert" create => "true", edit_line => Insert("@(insert.v)"); # edit_defaults => empty; } ####################################################### # For the library ####################################################### bundle edit_line Insert(name) { insert_lines: "$(name)"; } ####################################################### body edit_defaults empty { empty_file_before_editing => "true"; } cfengine-3.6.2/examples/unique.cf0000644000175100017510000000356612316547775016505 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "test_str" string => join(",", "test"); "test_unique" slist => unique("test"); "unique_str" string => join(",", "test_unique"); reports: "The test list is $(test_str)"; "The unique elements of the test list: $(unique_str)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test list is 1,2,3,one,two,three,long string,four,fix,six,one,two,three #@ R: The unique elements of the test list: 1,2,3,one,two,three,long string,four,fix,six #@ ``` #+end_src cfengine-3.6.2/examples/container_iteration.cf0000644000175100017510000000331612352022221021176 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "x" data => parsejson('[ { "one": "a" }, { "two": "b" }, { "three": "c" } ]'); # get the numeric indices of x: 0, 1, 2 "xi" slist => getindices(x); # for each xi, make a variable xpiece_$(xi) so we'll have # xpiece_0, xpiece_1, xpiece_2. Each xpiece will have that # particular element of the list x. "xpiece_$(xi)" string => format("%S", "x[$(xi)]"); reports: "$(xi): $(xpiece_$(xi))"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: 0: {"one":"a"} #@ R: 1: {"two":"b"} #@ R: 2: {"three":"c"} #@ ``` #+end_src cfengine-3.6.2/examples/activedirectory_listusers.cf0000664000175100017510000000302412243421446022464 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # List users from Active Directory through LDAP # Note: Anonymous LDAP binding must be allowed, and the Anonymous user # must have read access to CN=Users bundle agent ldap { vars: "userlist" slist => ldaplist( "ldap://cf-win2003", "CN=Users,DC=domain,DC=cf-win2003", "(objectClass=user)", "sAMAccountName", "subtree", "none"); reports: "Username: \"$(userlist)\""; } cfengine-3.6.2/examples/bundlesmatching.cf0000644000175100017510000000373712316547775020346 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { mefirst }; } bundle common g { vars: "todo" slist => bundlesmatching("default:run.*"); } bundle agent mefirst { methods: # note this is a dynamic bundle sequence! "" usebundle => $(g.todo); } bundle agent run_deprecated { meta: "tags" slist => { "deprecated" }; } bundle agent run_123_456 { vars: "bundles" slist => bundlesmatching(".*"); "deprecated_bundles" slist => bundlesmatching(".*", "deprecated"); "no_bundles" slist => bundlesmatching("891"); reports: "bundles = $(bundles)"; "deprecated bundles = $(deprecated_bundles)"; "no bundles = $(no_bundles)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: bundles = default:run_123_456 #@ R: bundles = default:run_deprecated #@ R: bundles = default:mefirst #@ R: bundles = default:g #@ R: deprecated bundles = default:run_deprecated #@ ``` #+end_src cfengine-3.6.2/examples/orchestrate_dragon.cf0000664000175100017510000001265312243421446021034 0ustar00a10038a1003800000000000000############################################################ # # Chinese Dragon Dancing on a Star # # This method works with either Community or Enterprise. # and uses named signals # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # ############################################################ body common control { bundlesequence => { "dragon_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } ############################################################ bundle agent dragon_symphony { methods: # We have to seed the beginning by creating the dragon # /tmp/dragon_localhost "dragon" usebundle => visit("localhost","host1","chapter1"); "dragon" usebundle => visit("host1","host2","chapter2"); "dragon" usebundle => visit("host2","host3","chapter3"); "dragon" usebundle => visit("host3","host4","chapter4"), classes => if_ok("finale"); reports: finale:: "The dragon is slain:" printfile => visitors_book("/tmp/shoo_dragon_host4"); } ############################################################ # Define the ############################################################ bundle agent chapter1(x) { # Do something significant here reports: host1:: " ----> Breathing fire on $(x)"; } ################################ bundle agent chapter2(x) { # Do something significant here reports: host2:: " ----> Breathing fire on $(x)"; } ################################ bundle agent chapter3(x) { # Do something significant here reports: host3:: " ----> Breathing fire on $(x)"; } ################################ bundle agent chapter4(x) { # Do something significant here reports: host4:: " ----> Breathing fire on $(x)"; } ############################################################ # Orchestration wrappers ############################################################ bundle agent visit(predecessor,satellite,method) { # This is a wrapper for the orchestration will be acted on # first by the dragon's lair and then by the satellite vars: "dragons_lair" string => "host0"; files: # We start in the dragon's lair .. "/tmp/unleash_dragon" comment => "Unleash the dragon", rename => to("/tmp/enter_the_dragon"), classes => if_repaired("dispatch_dragon_$(satellite)"), ifvarclass => "$(dragons_lair)"; # if we are the dragon's lair, welcome the dragon back, shooed from the satellite "/tmp/enter_the_dragon" comment => "Returning from a visit to a satellite", copy_from => secure_cp("/tmp/shoo_dragon_$(predecessor)","$(predecessor)"), classes => if_repaired("dispatch_dragon_$(satellite)"), ifvarclass => "$(dragons_lair)"; # If we are a satellite, receive the dragon from its lair "/tmp/enter_the_dragon" comment => "Wait for our cue or relay/conductor baton", copy_from => secure_cp("/tmp/dragon_$(satellite)","$(dragons_lair)"), classes => if_repaired("cue_action_on_$(satellite)"), ifvarclass => "$(satellite)"; methods: "check in at home" comment => "Edit the load balancer?", usebundle => switch_satellite(" -> Send dragon to $(satellite)"), classes => if_repaired("send_the_dragon_to_$(satellite)"), ifvarclass => "dispatch_dragon_$(satellite)"; "dragon visits" comment => "One off activity that the nodes carry out while the dragon visits", usebundle => $(method)("$(satellite)"), classes => if_repaired("send_the_dragon_back_from_$(satellite)"), ifvarclass => "cue_action_on_$(satellite)"; files: # hub/lair hub signs the book too and schedules the dragon for next satellite "/tmp/dragon_$(satellite)" create => "true", comment => "Add our signature to the dragon's tail", edit_line => sign_visitor_book("Dragon returned from $(predecessor)"), ifvarclass => "send_the_dragon_to_$(satellite)"; # Satellite signs the book and shoos dragon for hub to collect "/tmp/shoo_dragon_$(satellite)" create => "true", comment => "Add our signature to the dragon's tail", edit_line => sign_visitor_book("Dragon visited $(satellite) and did: $(method)"), ifvarclass => "send_the_dragon_back_from_$(satellite)"; reports: "Done $(satellite)"; } ############################################################ bundle agent switch_satellite(name) { files: "/tmp/enter_the_dragon" comment => "Add our signature to the dragon's tail", edit_line => append_if_no_line("Switch new dragon's target $(name)"); reports: " X Switching new dragon's target $(name)"; } ############################################################ bundle edit_line sign_visitor_book(s) { insert_lines: "/tmp/enter_the_dragon" comment => "Import the current visitor's book", insert_type => "file"; "$(s)" comment => "Append this string to the visitor's book"; } ############################################################ bundle server access_rules() { access: "/tmp" admit => { "127.0.0.1" }; "did.*" resource_type => "context", admit => { "127.0.0.1" }; } ############################################################ body printfile visitors_book(file) { file_to_print => "$(file)"; number_of_lines => "100"; } cfengine-3.6.2/examples/module_exec.cf0000664000175100017510000000246212243421446017445 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Test module execution as class function # body common control { bundlesequence => { "example" }; } ################################################################### bundle agent example { classes: "done" or => { usemodule("module:getusers","") }; commands: "/bin/echo promiser text" args => "test $(user)"; } cfengine-3.6.2/examples/process_kill.cf0000664000175100017510000000220012243421446017633 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "kill_process" }; } bundle agent kill_process { processes: "sleep" signals => { "term", "kill" }; } cfengine-3.6.2/examples/package_windows_feature.cf0000664000175100017510000000235712243421446022037 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "example" }; } bundle agent example { packages: Windows_Server_2008_R2:: "Telnet-Client" comment => "Install the telnet client", package_policy => "add", package_method => windows_feature; } body package_method windows_feature # NOTE: Windows feature names are case-sensitive { package_changes => "individual"; package_name_convention => "$(name)"; package_delete_convention => "$(name)"; package_installed_regex => ".*"; package_list_name_regex => "(.*)"; package_list_version_regex => "(.*)"; # FIXME: the listing does not give version, so takes name for version too now package_add_command => "$(sys.winsysdir)\\WindowsPowerShell\\v1.0\\powershell.exe -Command \"Import-Module ServerManager; Add-WindowsFeature -Name\""; package_delete_command => "$(sys.winsysdir)\\WindowsPowerShell\\v1.0\\powershell.exe -Command \"Import-Module ServerManager; Remove-WindowsFeature -confirm:$false -Name\""; package_list_command => "$(sys.winsysdir)\\WindowsPowerShell\\v1.0\\powershell.exe -Command \"Import-Module ServerManager; Get-WindowsFeature | where {$_.installed -eq $True} |foreach {$_.Name}\""; } cfengine-3.6.2/examples/process_restart.cf0000664000175100017510000000266312243421446020401 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "process_restart" }; } ######################################################### bundle agent process_restart { vars: "component" slist => { "cf-monitord", "cf-serverd", "cf-execd" }; processes: "$(component)" restart_class => canonify("start_$(component)"); commands: "/var/cfengine/bin/$(component)" ifvarclass => canonify("start_$(component)"); } cfengine-3.6.2/examples/getindices_and_values.cf0000664000175100017510000000263512243421446021475 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ####################################################### bundle agent example { vars: "v[index_1]" string => "value_1"; "v[index_2]" string => "value_2"; "x" slist => getindices("v"); "y" slist => getvalues("v"); reports: "All indices:"; " Found index: $(x) with value \"$(v[$(x)])\""; "All values:"; " Found value: $(y)"; } cfengine-3.6.2/examples/regextract.cf0000644000175100017510000000326112316547775017337 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: # Extract regex backreferences and put them in an array "ok" expression => regextract( "xx ([^\s]+) ([^\s]+).* xx", "xx one two three four xx", "myarray" ); reports: ok:: "ok - \"$(myarray[0])\" = xx + \"$(myarray[1])\" + \"$(myarray[2])\" + .. + xx"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: ok - "xx one two three four xx" = xx + "one" + "two" + .. + xx #@ ``` #+end_src cfengine-3.6.2/examples/translatepath.cf0000644000175100017510000000270612316547775020044 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "inputs_dir" string => translatepath("/a/b/c/inputs"); reports: windows:: "The path has backslashes: $(inputs_dir)"; !windows:: "The path has slashes: $(inputs_dir)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The path has slashes: /a/b/c/inputs #@ ``` #+end_src cfengine-3.6.2/examples/motd.cf0000664000175100017510000000200312243421446016106 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "edit_motd" }; } bundle agent edit_motd { files: "/etc/motd" edit_line => my_motd, edit_defaults => empty, create => "true"; } #@ The bundle `my_motd` and body `empty` detail what content we want #@ in the file using CFEngine's built-in line-editor. bundle edit_line my_motd { vars: "interfaces_str" string => join(", ","sys.interfaces"); "ipaddresses_str" string => join(", ","sys.ip_addresses"); insert_lines: "Welcome to $(sys.fqhost)! This system is managed by CFEngine. The policy was last updated on $(sys.last_policy_update). The system has $(sys.cpus) cpus. Network interfaces on this system are $(interfaces_str), and the ip-addresses assigned are $(ipaddresses_str)."; } #@ The `my_motd` bundle describes the content we want. body edit_defaults empty { empty_file_before_editing => "true"; } #@ Baseline memory model of file to zero/empty before #@ populating the model using edit_line my_motd cfengine-3.6.2/examples/max-min-mean-variance.cf0000644000175100017510000000500312316547775021235 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: # the behavior will be the same whether you use a data container or a list # "mylist" slist => { "foo", "1", "2", "3000", "bar", "10.20.30.40" }; "mylist" data => parsejson('["foo", "1", "2", "3000", "bar", "10.20.30.40"]'); "mylist_str" string => format("%S", mylist); "max_int" string => max(mylist, "int"); "max_lex" string => max(mylist, "lex"); "max_ip" string => max(mylist, "ip"); "min_int" string => min(mylist, "int"); "min_lex" string => min(mylist, "lex"); "min_ip" string => min(mylist, "ip"); "mean" real => mean(mylist); "variance" real => variance(mylist); reports: "my list is $(mylist_str)"; "mean is $(mean)"; "variance is $(variance) (use eval() to get the standard deviation)"; "max int is $(max_int)"; "max IP is $(max_ip)"; "max lexicographically is $(max_lex)"; "min int is $(min_int)"; "min IP is $(min_ip)"; "min lexicographically is $(min_lex)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: my list is ["foo","1","2","3000","bar","10.20.30.40"] #@ R: mean is 502.200000 #@ R: variance is 1497376.000000 (use eval() to get the standard deviation) #@ R: max int is 3000 #@ R: max IP is 10.20.30.40 #@ R: max lexicographically is foo #@ R: min int is bar #@ R: min IP is 1 #@ R: min lexicographically is 1 #@ ``` #+end_src cfengine-3.6.2/examples/strcmp.cf0000644000175100017510000000261312316547775016477 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "same" expression => strcmp("test","test"); reports: same:: "Strings are equal"; !same:: "Strings are not equal"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Strings are equal #@ ``` #+end_src cfengine-3.6.2/examples/peerleaders.cf0000644000175100017510000000530612352022221017432 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo alpha > /tmp/cfe_hostlist #@ echo beta >> /tmp/cfe_hostlist #@ echo gamma >> /tmp/cfe_hostlist #@ echo "Set HOSTNAME appropriately beforehand" #@ echo $HOSTNAME >> /tmp/cfe_hostlist #@ echo "Delta Delta Delta may I help ya help ya help ya" #@ echo delta1 >> /tmp/cfe_hostlist #@ echo delta2 >> /tmp/cfe_hostlist #@ echo delta3 >> /tmp/cfe_hostlist #@ echo may1.I.help.ya >> /tmp/cfe_hostlist #@ echo may2.I.help.ya >> /tmp/cfe_hostlist #@ echo may3.I.help.ya >> /tmp/cfe_hostlist #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "peers" }; } bundle agent peers { vars: "mygroup" slist => peers("/tmp/cfe_hostlist","#.*",4); "myleader" string => peerleader("/tmp/cfe_hostlist","#.*",4); "all_leaders" slist => peerleaders("/tmp/cfe_hostlist","#.*",4); reports: # note that the current host name is fourth in the host list, so # its peer group is the first 4-host group, minus the host itself. "/tmp/cfe_hostlist mypeer $(mygroup)"; # note that the current host name is fourth in the host list, so # the peer leader is "alpha" "/tmp/cfe_hostlist myleader $(myleader)"; "/tmp/cfe_hostlist another leader $(all_leaders)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /tmp/cfe_hostlist mypeer alpha #@ R: /tmp/cfe_hostlist mypeer beta #@ R: /tmp/cfe_hostlist mypeer gamma #@ R: /tmp/cfe_hostlist myleader alpha #@ R: /tmp/cfe_hostlist another leader alpha #@ R: /tmp/cfe_hostlist another leader delta1 #@ R: /tmp/cfe_hostlist another leader may2.I.help.ya #@ ``` #+end_src cfengine-3.6.2/examples/service_catalogue_separate.cf0000664000175100017510000000117412243421446022523 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "service_catalogue_separate" }; } bundle agent service_catalogue_separate { services: "foo" service_policy => "start", service_method => service_bundle_separate; "bar" service_policy => "stop", service_method => service_bundle_separate; } body service_method service_bundle_separate { service_bundle => $(this.promiser)("$(this.service_policy)"); } bundle agent foo(service_policy) { reports: "we need to ensure $(service_policy) of foo"; } bundle agent bar(service_policy) { reports: "we need to ensure $(service_policy) of bar"; } cfengine-3.6.2/examples/diskfree.cf0000644000175100017510000000275312316547775016770 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "has_space" expression => isgreaterthan($(free), 0); vars: "free" int => diskfree("/tmp"); reports: has_space:: "The filesystem has free space"; !has_space:: "The filesystem has NO free space"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The filesystem has free space #@ ``` #+end_src cfengine-3.6.2/examples/literal_server.cf0000664000175100017510000000576112243421446020203 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Remote value from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-d2] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { vars: "encrypt" string => "yes"; "x" string => "scalar2"; "remote1" string => remotescalar("test_scalar1","127.0.0.1","$(encrypt)"); "remote2" string => remotescalar("test_scalar2","127.0.0.1","$(encrypt)"); "remote3" string => remotescalar("test_scalar3","127.0.0.1","$(encrypt)"); "remote_error" string => remotescalar("test_$(x)","127.0.0.2","$(encrypt)"); reports: "Receive value $(remote1), $(remote2), $(remote3)"; "And an error gives: $(remote_error)"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; allowusers => { "mark" }; } ######################################################### bundle server access_rules() { vars: "localvar" string => "literal string"; access: "Embed a $(localvar) for remote access" handle => "test_scalar1", resource_type => "literal", admit => { "127.0.0.1" }; "Mary had a little lamb whose fleece was white as snow and everywhere that Mary went she wore it lovingly" handle => "test_scalar2", resource_type => "literal", admit => { "127.0.0.1" }; "/etc/passwd" handle => "test_scalar3", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/string_tail.cf0000644000175100017510000000253412316547775017510 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "end" string => string_tail("abc", "1"); # will contain "c" reports: "end of abc = $(end)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: end of abc = c #@ ``` #+end_src cfengine-3.6.2/examples/select_region.cf0000664000175100017510000000363612243421446020002 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { version => "1.2.3"; bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "/tmp/testfile" create => "true", edit_line => myedit("second"); } ######################################################## bundle edit_line myedit(parameter) { vars: "edit_variable" string => "private edit variable is $(parameter)"; replace_patterns: # comment out lines after start "([^#].*)" replace_with => comment, select_region => ToEnd("Start.*"); } ######################################## # Bodies ######################################## body replace_with comment { replace_value => "# $(match.1)"; # backreference 0 occurrences => "all"; # first, last all } ######################################################## body select_region ToEnd(x) { select_start => "$(x)"; } cfengine-3.6.2/examples/data_readstringarray.cf0000644000175100017510000000423212316547775021360 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ echo a,b,c > /tmp/cfe_array #@ echo d,e,f >> /tmp/cfe_array #@ echo g,h,i >> /tmp/cfe_array #@ echo j,k,l >> /tmp/cfe_array #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "bykey" data => data_readstringarray("/tmp/cfe_array","#.*",",",10,400); "byint" data => data_readstringarrayidx("/tmp/cfe_array","#.*",",",10,400); "bykey_str" string => format("%S", bykey); "byint_str" string => format("%S", byint); reports: "By key: $(bykey_str)"; "specific element by key a, offset 0: '$(bykey[a][0])'"; "By int offset: $(byint_str)"; "specific element by int offset 2, 0: '$(byint[2][0])'"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: By key: {"a":["b","c"],"d":["e","f"],"g":["h","i"],"j":["k","l"]} #@ R: specific element by key a, offset 0: 'b' #@ R: By int offset: [["a","b","c"],["d","e","f"],["g","h","i"],["j","k","l"]] #@ R: specific element by int offset 2, 0: 'g' #@ ``` #+end_src cfengine-3.6.2/examples/orchestrate_chain1.cf0000664000175100017510000000503412243421446020720 0ustar00a10038a1003800000000000000############################################################ # # The self-healing tower: Anti-Dominoes # # This method works with Enterprise # # If you want to test this on localhost, just edit /etc/hosts # to add host1 host2 host3 host4 as aliases to localhost # ############################################################ body common control { bundlesequence => { "weak_dependency_symphony" }; inputs => { "libraries/cfengine_stdlib.cf" }; } body server control { allowconnects => { "127.0.0.1" , "::1", @(def.acl) }; allowallconnects => { "127.0.0.1" , "::1", @(def.acl) }; } ############################################################ bundle agent weak_dependency_symphony { methods: # We have to seed the beginning by creating the tower # /tmp/tower_localhost host1:: "tower" usebundle => tier1, classes => publish_ok("ok_O"); host2:: "tower" usebundle => tier2, classes => publish_ok("ok_1"); host3:: "tower" usebundle => tier3, classes => publish_ok("ok_2"); host4:: "tower" usebundle => tier4, classes => publish_ok("ok_f"); classes: ok_O:: # Wait for the methods, report on host1 only "check1" expression => remoteclassesmatching("ok.*","host2","yes","a"); "check2" expression => remoteclassesmatching("ok.*","host3","yes","a"); "check3" expression => remoteclassesmatching("ok.*","host4","yes","a"); reports: ok_O:: "tier 1 is ok"; a_ok_1:: "tier 2 is ok"; a_ok_2:: "tier 3 is ok"; a_ok_f:: "tier 4 is ok"; ok_O&a_ok_1&a_ok_2&a_ok_f:: "The Tower is standing"; !(ok_O&a_ok_1&a_ok_2&a_ok_f):: "The Tower is down"; } ############################################################ bundle agent tier1 { files: "/tmp/something_to_do_1" create => "true"; } bundle agent tier2 { files: "/tmp/something_to_do_2" create => "true"; } bundle agent tier3 { files: "/tmp/something_to_do_3" create => "true"; } bundle agent tier4 { files: "/tmp/something_to_do_4" create => "true"; } ############################################################ bundle server access_rules() { access: "ok.*" resource_type => "context", admit => { "127.0.0.1" }; } ############################################################ body classes publish_ok(x) { promise_repaired => { "$(x)" }; promise_kept => { "$(x)" }; cancel_notkept => { "$(x)" }; persist_time => "2"; } cfengine-3.6.2/examples/service_catalogue.cf0000664000175100017510000000251612243421446020640 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "service_catalogue" }; } bundle agent service_catalogue { services: "syslog" service_policy => "start"; "www" service_policy => "stop"; } bundle agent standard_services(service, state) { vars: debian:: "startcommand[www]" string => "/etc/init.d/apache2 start"; "stopcommand[www]" string => "/etc/init.d/apache2 stop"; "processname[www]" string => "apache2"; "startcommand[syslog]" string => "/etc/init.d/rsyslog start"; "stopcommand[syslog]" string => "/etc/init.d/rsyslog stop"; "processname[syslog]" string => "rsyslogd"; classes: "start" expression => strcmp("start","$(state)"); "stop" expression => strcmp("stop","$(state)"); processes: start:: ".*$(processname[$(service)]).*" comment => "Verify that the service appears in the process table", restart_class => "restart_$(service)"; stop:: ".*$(processname[$(service)]).*" comment => "Verify that the service does not appear in the process table", process_stop => "$(stopcommand[$(service)])", signals => { "term", "kill"}; commands: "$(startcommand[$(service)])" comment => "Execute command to restart the $(service) service", ifvarclass => "restart_$(service)"; } cfengine-3.6.2/examples/measure_log.cf0000664000175100017510000000137612243421446017461 0ustar00a10038a1003800000000000000#cop measurements,example ####################################################### # # Test file: log scanner # ####################################################### # # Look for a file in /var/cfengine/state/line_counter_measure.log # bundle monitor watch { measurements: "/home/mark/tmp/file" handle => "line_counter", stream_type => "file", data_type => "counter", match_value => scan_log("MYLINE.*"), history_type => "log", action => sample_rate("0"); } ########################################################## body match_value scan_log(x) { select_line_matching => "^$(x)$"; track_growing_file => "true"; } body action sample_rate(x) { ifelapsed => "$(x)"; expireafter => "10"; } cfengine-3.6.2/examples/namespace_var_meta.cf0000664000175100017510000000047512400110676020763 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "main" }; version => "0.1"; inputs => { "namespace_var_meta2.cf"}; } bundle agent main { classes: "abc" expression => "any"; methods: "bla" usebundle => fred:example; reports: "remote var: $(fred:example.bundle_version)"; } cfengine-3.6.2/examples/copylinks.cf0000664000175100017510000000404212243421446017163 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy with link/copy exceptions # ######################################################## ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { files: "/home/mark/tmp/test_to" copy_from => mycopy("/home/mark/tmp/test_from"), perms => system, move_obstructions => "true", depth_search => recurse("inf"); } ######################################################### body perms system { mode => "0644"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body copy_from mycopy(from) { source => "$(from)"; #copylink_patterns => { ".*" }; # copy all links linkcopy_patterns => { ".*" }; # copy all links #copy_backup => "timestamp"; } cfengine-3.6.2/examples/selectservers.cf0000664000175100017510000000370612243421446020047 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Testing some variable/class definitions - note scope # # Use browser -f promise_output_agent.html to view # body common control { bundlesequence => { "test" }; } ########################################################### bundle agent example { vars: "hosts" slist => { "slogans.iu.hio.no", "eternity.iu.hio.no", "nexus.iu.hio.no" }; # selectservers(hostlist,port,sendstr,regex_on_reply,maxbytesread_reply,array_name "up_servers" int => selectservers("@(hosts)","80","","","100","alive_servers"); classes: "someone_alive" expression => isgreaterthan("$(up_servers)","0"); "i_am_a_server" expression => regarray("up_servers","$(host)|$(fqhost)"); reports: someone_alive:: "Number of active servers $(up_servers)" action => always; "First server $(alive_servers[0]) fails over to $(alive_servers[1])"; } ############################################################# body action always { ifelapsed => "0"; } cfengine-3.6.2/examples/depends_on.cf0000664000175100017510000000027612243421446017273 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "one" }; } bundle agent one { reports: "two" depends_on => { "handle_one" }; "one" handle => "handle_one"; } cfengine-3.6.2/examples/readtcp.cf0000644000175100017510000000271212352022221016557 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "my80" string => readtcp("myserver.com","80","GET /index.html HTTP/1.1$(const.r)$(const.n)Host: myserver.com$(const.r)$(const.n)$(const.r)$(const.n)",20); classes: "server_ok" expression => regcmp("[^\n]*200 OK.*\n.*","$(my80)"); reports: server_ok:: "Server is alive"; !server_ok:: "Server is not responding - got $(my80)"; } #+end_src cfengine-3.6.2/examples/ip2host.cf0000644000175100017510000000313012316547775016552 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "reverse_lookup" }; } bundle agent reverse_lookup { vars: "local4" string => ip2host("127.0.0.1"); # this will be localhost on some systems, ip6-localhost on others... "local6" string => ip2host("::1"); reports: _cfe_output_testing:: "we got local4" ifvarclass => isvariable("local4"); !_cfe_output_testing:: "local4 is $(local4)"; "local6 is $(local6)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: we got local4 #@ ``` #+end_src cfengine-3.6.2/examples/edit_xml.cf0000644000175100017510000000517012316547775016775 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ############################################################################### #+begin_src cfengine3 # for more info: http://cfengine.com/docs/master/reference-promise-types-edit_xml.html body common control { bundlesequence => { run }; inputs => { "$(sys.libdir)/files.cf" }; } bundle agent run { vars: "file" string => "$(this.promise_filename).txt"; methods: "rm" usebundle => rmxml; "make" usebundle => makexml; "use" usebundle => maintainxml; "report" usebundle => reportxml; } bundle agent rmxml { files: "$(run.file)" delete => tidy; } bundle agent makexml { files: "$(run.file)" comment => "Create xml file", create => "true", edit_defaults => empty, edit_xml => xml_insert_tree_nopath('cfe_alias'); } bundle agent reportxml { vars: "data" string => readfile($(run.file), 4k); reports: "Final XML is $(data)"; # R: Final XML is # newhosttextnewalias } bundle agent maintainxml { files: "$(run.file)" comment => "Maintain xml file: set the Alias node", create => "false", edit_xml => xml_set_value("newalias","/Host/Alias"); "$(run.file)" comment => "Maintain xml file: replace a Host node with a name attribute = cfe_host", create => "false", edit_xml => xml_set_value("newhosttext","/Host[@name='cfe_host']"); "$(run.file)" comment => "Maintain xml file: replace a Host node's name attribute", create => "false", edit_xml => xml_set_attribute("name", "newhostname", "/Host"); } #+end_src cfengine-3.6.2/examples/string_head.cf0000644000175100017510000000254412316547775017461 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "start" string => string_head("abc", "1"); # will contain "a" reports: "start of abc = $(start)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: start of abc = a #@ ``` #+end_src cfengine-3.6.2/examples/meta.cf0000664000175100017510000000314412243421446016100 0ustar00a10038a1003800000000000000 # Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Default values for variables and parameters, introduced 3.4.0 # body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { meta: "bundle_version" string => "1.2.3"; "works_with_cfengine" string => "3.4.0"; vars: "testvar" string => "x"; reports: "Not a local variable: $(bundle_version)"; "Not a local variable: $(other_bundle.something)"; "Meta data (variable): $(example_meta.bundle_version)"; } bundle agent other_bundle { vars: "something" string => "I am defined in another bundle"; } cfengine-3.6.2/examples/getusers.cf0000644000175100017510000000301712316547775017027 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "allusers" slist => getusers("",""); "root_list" slist => { "root" }; # this will get just the root users out of the full user list "justroot" slist => intersection(allusers, root_list); reports: "Found just the root user: $(justroot)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found just the root user: root #@ ``` #+end_src cfengine-3.6.2/examples/deletelines.cf0000664000175100017510000000411312243421446017444 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } bundle agent example { files: "/tmp/resolv.conf" # test on "/tmp/resolv.conf" # create => "true", edit_line => resolver, edit_defaults => def; } ####################################################### # For the library ####################################################### bundle edit_line resolver { vars: "search" slist => { "search iu.hio.no cfengine.com", "nameserver 128.39.89.10" }; delete_lines: "search.*"; insert_lines: "$(search)" location => end; } ####################################################### body edit_defaults def { empty_file_before_editing => "false"; edit_backup => "false"; max_file_size => "100000"; } ######################################################## body location start { # If not line to match, applies to whole text body before_after => "before"; } ######################################################## body location end { # If not line to match, applies to whole text body before_after => "after"; } cfengine-3.6.2/examples/service_start.cf0000664000175100017510000000111612243421446020024 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "example" }; } ############################################# bundle agent example { services: "Themes" service_policy => "start", service_dependencies => { "Alerter" }, service_method => exmethod; } ############################################# body service_method exmethod { service_type => "windows"; service_args => "-f \"the file with spaces.cf\" --some-args"; service_autostart_policy => "boot_time"; service_dependence_chain => "start_parent_services"; } cfengine-3.6.2/examples/edit_insert_lines.cf0000664000175100017510000000363412243421446020661 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Insert a number of lines # ####################################################### body common control { any:: bundlesequence => { "insert" }; } ####################################################### bundle agent insert { vars: "v" string => " One potato Two potato Three potatoe Four "; files: "/tmp/test_insert" create => "true", edit_line => Insert("$(insert.v)"), edit_defaults => empty; } ####################################################### # For the library ####################################################### bundle edit_line Insert(name) { insert_lines: "Begin$(const.n)$(name)$(const.n)End"; } ####################################################### body edit_defaults empty { empty_file_before_editing => "false"; } cfengine-3.6.2/examples/exec_in_sequence.cf0000664000175100017510000000367712243421446020467 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test execution # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { vars: "size" int => "46k"; "rand" int => randomint("33","$(size)"); commands: "/bin/echo" args => "Hello world - $(size)/$(rand)", contain => standard, classes => cdefine("followup","alert"); followup:: "/bin/ls" contain => standard; reports: alert:: "What happened?"; } ###################################################################### body contain standard { exec_owner => "mark"; useshell => "useshell"; } ###################################################################### body classes cdefine(class,alert) { promise_repaired => { "$(class)" }; repair_failed => { "$(alert)" }; } cfengine-3.6.2/examples/services_win.cf0000664000175100017510000000253512243421446017655 0ustar00a10038a1003800000000000000######################################################################### # # win_services.cf - Windows Service Management # ######################################################################### bundle agent win_services { vars: # NOTE: Use "Service Name" (not "Display Name"); # Administrative Tools -> Services -> Double Click on one to see its name "bad_services" slist => { "RemoteRegistry" }; Windows_Server_2003_R2:: "autostart_services" slist => { "Alerter", "W32Time" # Windows Time }; Windows_Server_2008:: "autostart_services" slist => { "MpsSvc", # Windows Firewall "W32Time" # Windows Time }; services: "$(bad_services)" service_policy => "disable", service_method => force_deps, comment => "Disable services that create security issues"; Windows_Server_2003_R2|Windows_Server_2008:: "$(autostart_services)" service_policy => "start", service_method => bootstart, comment => "Make sure important services are running and set to start at boot time"; } cfengine-3.6.2/examples/acl_generic.cf0000664000175100017510000000271212243421446017405 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "acls" }; } ######################################### bundle agent acls { files: "/media/flash/acl/test_dir" depth_search => include_base, acl => test; } ######################################### body acl test { acl_type => "generic"; aces => {"user:bob:rwx", "group:staff:rx", "all:r"}; } ######################################### body depth_search include_base { include_basedir => "true"; } cfengine-3.6.2/examples/method_var.cf0000664000175100017510000000142512243421446017302 0ustar00a10038a1003800000000000000# # Demonstrates the use of variables to call bundles. # We can then filter variables on classes, for example. # body common control { bundlesequence => { "example" }; } ########################################### bundle agent test { vars: "run_bundles" slist => { "test_one", "test_two" }; "run_a_bundle" string => "test_three"; methods: "any" usebundle => "$(run_bundles)"; "any" usebundle => "$(run_a_bundle)"; } ########################################### bundle agent test_one { reports: "in test_one"; } ########################################### bundle agent test_two { reports: "in test_two"; } ########################################### bundle agent test_three { reports: "in test_three"; } cfengine-3.6.2/examples/syslog.cf0000664000175100017510000000225212243421446016471 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "one" }; } bundle agent one { files: "/tmp/xyz" create => "true", action => log; } body action log { log_level => "inform"; } cfengine-3.6.2/examples/software_update_version_yum.cf0000664000175100017510000000351012243421446023002 0ustar00a10038a1003800000000000000# # Schedule software update for yum-based distributions (e.g. RedHat, CentOS) # Will only update to the given package_version assumed to be found in the yum repository. # If installed version is the same as package_version or newer, no action is taken. # body common control { bundlesequence => { "system_software" }; } bundle agent system_software { classes: "update_hosts" expression => "host1|host2"; "update_schedule" expression => "Day27.Hr02.Min00_05"; packages: update_hosts.update_schedule:: "bash" comment => "Make sure bash package is updated to right version", handle => "package_bash_update", package_version => "3.2-32.el5", package_architectures => { "x86_64" }, package_policy => "addupdate", package_select => ">=", package_method => yum_version; } body package_method yum_version { package_changes => "bulk"; package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; package_patch_list_command => "/usr/bin/yum check-update"; package_list_name_regex => "^(\S+?)\s\S+?\s\S+$"; package_list_version_regex => "^\S+?\s(\S+?)\s\S+$"; package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$"; package_installed_regex => ".*"; package_name_convention => "$(name)-$(version).$(arch)"; package_patch_installed_regex => "^\s.*"; package_patch_name_regex => "([^.]+).*"; package_patch_version_regex => "[^\s]\s+([^\s]+).*"; package_patch_arch_regex => "[^.]+\.([^\s]+).*"; package_add_command => "/usr/bin/yum -y install"; package_update_command => "/usr/bin/yum -y update"; package_delete_command => "/bin/rpm -e --nodeps --allmatches"; package_verify_command => "/bin/rpm -V"; } cfengine-3.6.2/examples/string_upcase.cf0000644000175100017510000000254212316547775020036 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "upcase" string => string_upcase("abc"); # will contain "ABC" reports: "upcased abc: $(upcase)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: upcased abc: ABC #@ ``` #+end_src cfengine-3.6.2/examples/menu.cf0000664000175100017510000000415512243421446016121 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-d2] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } # cf-runagent -q bundle agent example { files: } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; allowusers => { "mark", "root" }; } ######################################################### bundle server access_rules() { access: "delta" resource_type => "query", admit => { "127.0.0.1" }; "full" resource_type => "query", admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/string_downcase.cf0000644000175100017510000000255612316547775020366 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "downcase" string => string_downcase("ABC"); # will contain "abc" reports: "downcased ABC = $(downcase)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: downcased ABC = abc #@ ``` #+end_src cfengine-3.6.2/examples/abort.cf0000664000175100017510000000325712243421446016266 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #[%+%] body common control { bundlesequence => { "example" }; } body agent control { abortbundleclasses => { "invalid" }; } #[%-%] ########################################### #[%+%] bundle agent example { vars: #"userlist" slist => { "mark", "john" }; # contains all valid entries "userlist" slist => { "mark", "john", "thomas" }; # contains one invalid entry classes: "invalid" not => regcmp("[a-z][a-z][a-z][a-z]","$(userlist)"); # The class 'invalid' is set if the user name does not # contain exactly four un-capitalized letters (bundle # execution will be aborted if set) reports: !invalid:: "User name $(userlist) is valid at 4 letters"; } cfengine-3.6.2/examples/badpromise.cf0000664000175100017510000000256312243421446017303 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # This is an example of malformed promise file. If you pass it through # cf-promises, syntax checker should complain. # body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { dummy: "help" -> "me"; reports: same:: "Strings are equal"; !same:: "Strings are not equal"; } cfengine-3.6.2/examples/irange.cf0000664000175100017510000000307712243421446016424 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "cleanup" }; } bundle agent cleanup { files: # This will not delete the parent "/home/mark/tmp/testcopy" delete => tidyfiles, file_select => changed_within_1_year, depth_search => recurse; #Now delete the parent. "/home/mark/tmp/testcopy" delete => tidyfiles; } body delete tidyfiles { dirlinks => "delete"; rmdirs => "true"; } body file_select changed_within_1_year { mtime => irange(ago(1,0,0,0,0,0),now); file_result => "mtime"; } body depth_search recurse { depth => "inf"; } cfengine-3.6.2/examples/ago.cf0000644000175100017510000000334712316547775015742 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "testbundle" }; } bundle agent testbundle { processes: ".*" process_count => anyprocs, process_select => proc_finder; reports: any_procs:: "Found processes out of range"; } body process_select proc_finder { # Processes started between 100 years + 5.5 hours and 20 minutes ago stime_range => irange(ago(100,0,0,5,30,0),ago(0,0,0,0,20,0)); process_result => "stime"; } body process_count anyprocs { match_range => "0,0"; out_of_range_define => { "any_procs" }; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Found processes out of range #@ ``` #+end_src cfengine-3.6.2/examples/copy.cf0000664000175100017510000000246212243421446016126 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "copy" }; } bundle agent copy { files: "/tmp/testfile1-cop" copy_from => mycopy("/tmp/testfile1", "gudea"); "/tmp/testfile2-cop" copy_from => mycopy("/tmp/testfile2", "gudea"); } body copy_from mycopy(from,server) { source => "$(from)"; #servers => { "$(server)" }; } cfengine-3.6.2/examples/setvar.cf0000664000175100017510000000336012243421446016456 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "setvars" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent setvars { vars: # want to set these values by the names of their array keys "rhs[lhs1]" string => " Mary had a little pig"; "rhs[lhs2]" string => "Whose Fleece was white as snow"; "rhs[lhs3]" string => "And everywhere that Mary went"; "rhs[net/ipv4/tcp_syncookies]" string => "1"; "rhs[net/ipv4/icmp_echo_ignore_broadcasts]" string => "1"; "rhs[net/ipv4/ip_forward]" string => "0"; # oops, now change pig -> lamb files: "/tmp/system" comment => "Create a file of variable assignments and manage this file", create => "true", edit_line => set_variable_values("setvars.rhs"); } cfengine-3.6.2/examples/regex_win.cf0000664000175100017510000000111612243421446017136 0ustar00a10038a1003800000000000000###################################################################### # Using path regular expressions on Windows (always forward slash) ###################################################################### body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { files: "c:/test/.*.xml" edit_line => add_information(); } ######################################################## bundle edit_line add_information() { insert_lines: "a line", comment => "adding line"; } cfengine-3.6.2/examples/app_baseline.cf0000664000175100017510000000447412243421446017603 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################################### # # app_baseline.cf - Verify Existence of Applications # # NOTE: Sometimes applications are not correctly installed even # though the native package manager reports them to be. # Cfengine can check for application-specific configuration # and act upon or report any anomalies. # ######################################################################### bundle agent app_baseline { methods: windows:: "any" usebundle => detect_adobereader; } ### bundle agent detect_adobereader { vars: windows:: "value1" string => registryvalue("HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Acrobat Reader\9.0\Installer", "ENU_GUID"); "value2" string => registryvalue("HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Acrobat Reader\9.0\Installer", "VersionMax"); "value3" string => registryvalue("HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Acrobat Reader\9.0\Installer", "VersionMin"); classes: windows:: "is_correct" and => { strcmp("$(value1)", "{AC76BA86-7AD7-1033-7B44-A93000000001}"), strcmp("$(value2)", "90003"), islessthan("$(value3)", "10001" ) }; reports: windows.!is_correct:: "Adobe Reader is not correctly deployed - got \"$(value1)\", \"$(value2)\", \"$(value3)\""; } cfengine-3.6.2/examples/accessedbefore.cf0000644000175100017510000000324112332665147020112 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ touch -a -t '200102031234.56' /tmp/earlier #@ touch -a -t '200202031234.56' /tmp/later #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "do_it" expression => accessedbefore("/tmp/earlier","/tmp/later"); reports: do_it:: "The secret changes have been accessed after the reference time"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The secret changes have been accessed after the reference time #@ ``` #+end_src cfengine-3.6.2/examples/filter.cf0000644000175100017510000001173512316547775016461 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "test" }; } bundle agent test { vars: "test" slist => { 1,2,3, "one", "two", "three", "long string", "one", "two", "three", }; "test2" data => parsejson('[1,2,3, "ab", "c"]'); "test_filtergrep" slist => filter("[0-9]", test, "true", "false", 999); "test_exact1" slist => filter("one", test, "false", "false", 999); "test_exact2" slist => filter(".", test, "false", "false", 999); "test_invert" slist => filter("[0-9]", test, "true", "true", 999); "test_max2" slist => filter(".*", test, "true", "false", 2); "test_max0" slist => filter(".*", test, "true", "false", 0); "test_grep" slist => grep("[0-9]", test); "test2_filtergrep" slist => filter("[0-9]", test2, "true", "false", 999); "test2_exact1" slist => filter("one", test2, "false", "false", 999); "test2_exact2" slist => filter(".", test2, "false", "false", 999); "test2_invert" slist => filter("[0-9]", test2, "true", "true", 999); "test2_max2" slist => filter(".*", test2, "true", "false", 2); "test2_max0" slist => filter(".*", test2, "true", "false", 0); "test2_grep" slist => grep("[0-9]", test2); "todo" slist => { "test", "test2", "test_filtergrep", "test_exact1", "test_exact2", "test_invert", "test_max2", "test_max0", "test_grep", "test2_filtergrep", "test2_exact1", "test2_exact2", "test2_invert", "test2_max2", "test2_max0", "test2_grep"}; "$(todo)_str" string => format("%S", $(todo)); "tests" slist => { "test", "test2" }; reports: "The $(tests) list is $($(tests)_str)"; "The grepped list (only single digits from $(tests)) is $($(tests)_grep_str)"; "The filter-grepped list (only single digits from $(tests)) is $($(tests)_grep_str)"; "The filter-exact list, looking for only 'one' in $(tests), is $($(tests)_exact1_str)"; "This list should be empty, the '.' is not literally in the list $(tests): $($(tests)_exact2_str)"; "The filter-invert list, looking for non-digits in $(tests), is $($(tests)_invert_str)"; "The filter-bound list, matching at most 2 items from the whole list $(tests), is $($(tests)_max2_str)"; "This list should be empty because 0 elements of $(tests) were requested: $($(tests)_max0_str)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test list is { "1", "2", "3", "one", "two", "three", "long string", "one", "two", "three" } #@ R: The test2 list is [1,2,3,"ab","c"] #@ R: The grepped list (only single digits from test) is { "1", "2", "3" } #@ R: The grepped list (only single digits from test2) is { "1", "2", "3" } #@ R: The filter-grepped list (only single digits from test) is { "1", "2", "3" } #@ R: The filter-grepped list (only single digits from test2) is { "1", "2", "3" } #@ R: The filter-exact list, looking for only 'one' in test, is { "one", "one" } #@ R: The filter-exact list, looking for only 'one' in test2, is { --empty-list-- } #@ R: This list should be empty, the '.' is not literally in the list test: { --empty-list-- } #@ R: This list should be empty, the '.' is not literally in the list test2: { --empty-list-- } #@ R: The filter-invert list, looking for non-digits in test, is { "one", "two", "three", "long string", "one", "two", "three" } #@ R: The filter-invert list, looking for non-digits in test2, is { "ab", "c" } #@ R: The filter-bound list, matching at most 2 items from the whole list test, is { "1", "2" } #@ R: The filter-bound list, matching at most 2 items from the whole list test2, is { "1", "2" } #@ R: This list should be empty because 0 elements of test were requested: { --empty-list-- } #@ R: This list should be empty because 0 elements of test2 were requested: { --empty-list-- } #@ ``` #+end_src cfengine-3.6.2/examples/global_list_expansion_2.cf0000664000175100017510000000301612243421446021750 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # Show access of external lists. # body common control { bundlesequence => { hardening }; } ######################################################### bundle common va { vars: "tmpdirs" slist => { "/tmp", "/var/tmp", "/usr/tmp" }; } ########################################################## bundle agent hardening { classes: "ok" expression => "any"; vars: "other" slist => { "/tmp", "/var/tmp" }; "x" slist => { @(va.tmpdirs) }; reports: ok:: "Do $(x)"; "Other: $(other)"; } cfengine-3.6.2/examples/neighbourhood_watch.cf0000664000175100017510000000514112243421446021173 0ustar00a10038a1003800000000000000a# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Change detect # ######################################################## body common control { bundlesequence => { "neighbourhood_watch" }; } ######################################################## bundle agent neighbourhood_watch { vars: "neighbours" slist => peers("/var/cfengine/inputs/hostlist","#.*",4); files: # Redundant cross monitoring ....................................... "$(sys.workdir)/nw/$(neighbours)_checksum_digests.db" comment => "Watch our peers remote hash tables and keep a local copy", copy_from => rcp("$(sys.workdir)/checksum_digests.db",$(neighbours)), depends_on => { "grant_hash_tables" }; # Define the actual children to watch over ......................... "/usr/bin" comment => "Watch over the system binaries - changes are mostly updates", changes => lay_trip_wire, depth_search => recurse("inf"), action => measure; } ######################################################### body changes lay_trip_wire { hash => "best"; report_changes => "content"; update_hashes => "yes"; } ######################################################### body copy_from rcp(from,server) { servers => { "$(server)" }; source => "$(from)"; compare => "digest"; encrypt => "false"; } ########################################################## body depth_search recurse(d) { depth => "$(d)"; } body action measure { measurement_class => "$(this.promiser) long job scan of /usr"; } cfengine-3.6.2/examples/process_matching2.cf0000664000175100017510000000311112243421446020556 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test processes # ######################################################## body common control { bundlesequence => { "example" }; } ######################################################## bundle agent example { processes: "sleep" process_count => up("sleep"); reports: sleep_out_of_control:: "Out of control"; } ######################################################## body process_count up(s) { match_range => "5,10"; # or irange("1","10"); out_of_range_define => { "$(s)_out_of_control" }; } cfengine-3.6.2/examples/hashuncomment.cf0000664000175100017510000000352512243421446020026 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ###################################################################### # # Uncomment lines # ###################################################################### body common control { version => "1.2.3"; bundlesequence => { "example" }; } # try this on some test data like # one # two # mark one #mark two ######################################################## bundle agent example { files: "/home/mark/tmp/comment_test" create => "true", edit_line => uncomment_lines_matching("\s*mark.*","#"); } ######################################################## bundle edit_line uncomment_lines_matching(regex,comment) { replace_patterns: "#($(regex))$" replace_with => uncomment; } ######################################################## body replace_with uncomment { replace_value => "$(match.1)"; occurrences => "all"; } cfengine-3.6.2/examples/select_mode.cf0000664000175100017510000000323612243421446017437 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Searching for permissions # ####################################################### body common control { bundlesequence => { "example" }; } ############################################ bundle agent example { files: "/home/mark/tmp/test_from" file_select => by_modes, transformer => "/bin/echo DETECTED $(this.promiser)", depth_search => recurse("inf"); } ############################################ body file_select by_modes { search_mode => { "711" , "666" }; file_result => "mode"; } ############################################ body depth_search recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/classesmatching.cf0000644000175100017510000000431412316547775020337 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { run }; } bundle agent run { vars: "all" slist => classesmatching(".*"); "c" slist => classesmatching("cfengine"); "internal_environment" slist => classesmatching(".*", 'cfe_internal', 'source=environment'); "c_plus_plus" slist => classesmatching("cfengine", "plus"); reports: # you may find this list of all classes interesting but it # produces different output every time, so it's commented out here # "All classes = '$(all)'"; "All classes with the 'cfe_internal' and 'source=environment' tags = '$(internal_environment)'"; "Classes matching 'cfengine' = '$(c)'"; # this should produce no output "Classes matching 'cfengine' with the 'plus' tag = $(c_plus_plus)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: All classes with the 'cfe_internal' and 'source=environment' tags = '_cfe_output_testing' #@ R: All classes with the 'cfe_internal' and 'source=environment' tags = 'opt_dry_run' #@ R: All classes with the 'cfe_internal' and 'source=environment' tags = 'agent' #@ R: Classes matching 'cfengine' = 'cfengine' #@ ``` #+end_src cfengine-3.6.2/examples/report_custom.cf0000664000175100017510000000327312243421446020062 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } bundle agent example { vars: "software" slist => { "gpg", "zip", "rsync" }; classes: "noreport" expression => fileexists("/tmp/report.html"); "have_$(software)" expression => fileexists("/usr/bin/$(software)"); reports: no_report:: " Name of this host is: $(sys.host)
    Type of this host is: $(sys.os)
    " report_to_file => "/tmp/report.html"; # " Host has software $(software)
    " ifvarclass => "have_$(software)", report_to_file => "/tmp/report.html"; # " " report_to_file => "/tmp/report.html"; } cfengine-3.6.2/examples/none.cf0000644000175100017510000000575312316547775016136 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { classes: "none11" expression => none("jebadiah", test1); "none12" expression => none("2", test1); "none21" expression => none("jebadiah", test2); "none22" expression => none("2", test2); vars: "test1" slist => { 1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three", }; "test2" data => parsejson('[1,2,3, "one", "two", "three", "long string", "four", "fix", "six", "one", "two", "three",]'); reports: "The test1 list is $(test1)"; none11:: "none() test1 1 passed"; !none11:: "none() test1 1 failed"; none12:: "none() test1 2 failed"; !none12:: "none() test1 2 passed"; "The test2 list is $(test2)"; none21:: "none() test2 1 passed"; !none21:: "none() test2 1 failed"; none22:: "none() test2 2 failed"; !none22:: "none() test2 2 passed"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: The test1 list is 1 #@ R: The test1 list is 2 #@ R: The test1 list is 3 #@ R: The test1 list is one #@ R: The test1 list is two #@ R: The test1 list is three #@ R: The test1 list is long string #@ R: The test1 list is four #@ R: The test1 list is fix #@ R: The test1 list is six #@ R: none() test1 1 passed #@ R: none() test1 2 passed #@ R: The test2 list is 1 #@ R: The test2 list is 2 #@ R: The test2 list is 3 #@ R: The test2 list is one #@ R: The test2 list is two #@ R: The test2 list is three #@ R: The test2 list is long string #@ R: The test2 list is four #@ R: The test2 list is fix #@ R: The test2 list is six #@ R: none() test2 1 passed #@ R: none() test2 2 passed #@ ``` #+end_src cfengine-3.6.2/examples/acl.cf0000664000175100017510000000341612243421446015713 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "acls" }; } ######################################### bundle agent acls { files: "/media/flash/acl/test_dir" depth_search => include_base, acl => template; } ######################################### body acl template { acl_method => "overwrite"; acl_type => "posix"; acl_default => "access"; aces => { "user:*:r(wwx),-r:allow", "group:*:+rw:allow", "mask:x:allow", "all:r"}; } ######################################### body acl win { acl_method => "overwrite"; acl_type => "ntfs"; acl_default => "nochange"; aces => { "user:Administrator:rw", "group:Bad:rwx(Dpo):deny" }; } ######################################### body depth_search include_base { include_basedir => "true"; } cfengine-3.6.2/examples/guest_environment_kvm.cf0000664000175100017510000000364712411001073021575 0ustar00a10038a1003800000000000000# # Management of KVM/QEMU virtual machines # Assumes you already have a disk image (with an OS installed) for the machine on creation # body common control { bundlesequence => { "kvm_create" }; } bundle agent kvm_create { guest_environments: "my_host_machine" environment_resources => mykvm("my_host_machine", "x86_64", "1", "1048576", "/var/lib/libvirt/images/ubuntu104-64-clone.img"), environment_type => "kvm", environment_state => "create", environment_host => "ubuntu"; } bundle agent kvm_suspend { guest_environments: "my_host_machine" environment_type => "kvm", environment_state => "suspended", environment_host => "ubuntu"; } bundle agent kvm_run { guest_environments: "my_host_machine" environment_type => "kvm", environment_state => "running", environment_host => "ubuntu"; } bundle agent kvm_delete { guest_environments: "my_host_machine" environment_type => "kvm", environment_state => "delete", environment_host => "ubuntu"; } body environment_resources mykvm(name, arch, cpu_count, mem_kb, disk_file) { env_spec => " $(name) $(mem_kb) $(mem_kb) $(cpu_count) hvm destroy restart restart /usr/bin/kvm "; } cfengine-3.6.2/examples/report_state.cf0000664000175100017510000000267012243421446017670 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "report" }; } ########################################################### bundle agent report { reports: "/etc/passwd except $(const.n)" printfile => pr("/etc/passwd","5"), showstate => { "otherprocs", "rootprocs" }; } ###################################################################### body printfile pr(file,lines) { file_to_print => "$(file)"; number_of_lines => "$(lines)"; } cfengine-3.6.2/examples/string_length.cf0000644000175100017510000000256012316547775020037 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "length" int => string_length("abc"); # will contain "3" reports: "length of string abc = $(length)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: length of string abc = 3 #@ ``` #+end_src cfengine-3.6.2/examples/failedcommand.cf0000664000175100017510000000101512243421446017730 0ustar00a10038a1003800000000000000body common control { bundlesequence => { "cmdtest" }; } bundle agent cmdtest { files: "/tmp/test" copy_from => copy("/etc/passwd"); "/tmp/test" classes => example, transformer => "/bin/grep -q lkajfo999999 $(this.promiser)"; reports: hasfailed:: "The files-promise failed!"; } body classes example { failed_returncodes => { "1" }; repair_failed => { "hasfailed" }; } body copy_from copy(file) { source => "$(file)"; } cfengine-3.6.2/examples/createdb.cf0000664000175100017510000000372512243421446016730 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "databases" }; } bundle agent databases { databases: "knowledge_bank/topics" database_operation => "create", database_type => "sql", database_columns => { "demo_name,varchar,256", "demo_comment,varchar,1024", "demo_id,varchar,256", "demo_type,varchar,256", "demo_extra,varchar,26" }, database_server => myserver; } ################################################ body database_server myserver { none:: db_server_owner => "postgres"; db_server_password => ""; db_server_host => "localhost"; db_server_type => "postgres"; db_server_connection_db => "postgres"; any:: db_server_owner => "root"; db_server_password => ""; db_server_host => "localhost"; db_server_type => "mysql"; db_server_connection_db => "mysql"; } cfengine-3.6.2/examples/registryvalue.cf0000644000175100017510000000300112316547775020064 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "reg" }; } bundle agent reg { vars: windows:: "value" string => registryvalue("HKEY_LOCAL_MACHINE\SOFTWARE\CFEngine AS\CFEngine","value3"); !windows:: "value" string => "Sorry, no registry data is available"; reports: "Value extracted: $(value)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Value extracted: Sorry, no registry data is available #@ ``` #+end_src cfengine-3.6.2/examples/null_config.cf0000664000175100017510000000247412243421446017456 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # The starting point for every configuration # ####################################################### body common control { bundlesequence => { "example" }; } ####################################################### bundle agent example { reports: "This is a test bundle"; } cfengine-3.6.2/examples/defaults3.cf0000664000175100017510000000100012243421446017031 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "main" }; } bundle agent main { methods: "example" usebundle => test("one","x","","$(four)"); } bundle agent test(a,b,c,d) { defaults: "a" string => "default a", if_match_regex => ""; "b" string => "default b", if_match_regex => "x"; "c" string => "default c", if_match_regex => ""; "d" string => "default d", if_match_regex => "\$\([a-zA-Z0-9_.]+\)"; reports: "a = '$(a)', b = '$(b)', c = '$(c)' d = '$(d)'"; } cfengine-3.6.2/examples/server_copy_purge.cf0000664000175100017510000000610712243421446020716 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-d2] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { files: "/home/mark/tmp/test_to" comment => "test copy promise", copy_from => mycopy("/home/mark/tmp/test_from","127.0.0.1"), perms => system, depth_search => recurse("inf"), classes => satisfied("copy_ok"); reports: copy_ok:: "Files were copied.."; } ######################################################### body perms system { mode => "0644"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body copy_from mycopy(from,server) { source => "$(from)"; servers => { "$(server)" }; compare => "digest"; verify => "true"; copy_backup => "true"; #/false/timestamp purge => "true"; type_check => "true"; force_ipv4 => "true"; trustkey => "true"; } ######################################################### body classes satisfied(x) { promise_repaired => { "$(x)" }; persist_time => "0"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "/home/mark/tmp" admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/getgid.cf0000644000175100017510000000271012332665147016420 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: linux|solaris|hpux:: "gid" int => getgid("root"); freebsd|darwin|openbsd:: "gid" int => getgid("wheel"); aix:: "gid" int => getgid("system"); reports: "root's gid is $(gid)"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: root's gid is 0 #@ ``` #+end_src cfengine-3.6.2/examples/customize_by_named_list.cf0000664000175100017510000000471112243421446022066 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test - copy from a single directory of spec files # generating multiple directories and special # edits. # ######################################################## body common control { bundlesequence => { "virtualhosts" }; version => "1.2.3"; } ######################################################## bundle agent virtualhosts { vars: "vmbase" string => "/home/mark/tmp/vm"; "source_files" string => "/home/mark/tmp/src"; # list of hosts to create "hostlist" slist => { "host1", "host2", "host3", "host4", "host5", "host6", "host7", "host8", "host9" }; ################### or just a new file to the dir ################ # # "hostlist" slist => { SelectFilesIn("$(source_files)",".*") } # ################################################################## files: "$(vmbase)/$(hostlist)/config_for_$(hostlist).vm" copy_from => buildvm("$(source_files)/template_$(hostlist)"); # # Now edit config .e.g. edit in $(ipadr[$(hostlist)]) for each # } ######################################################### # library template ######################################################### body copy_from buildvm(from) { source => "$(from)"; copy_backup => "true"; #/false/timestamp } cfengine-3.6.2/examples/hashmatch.cf0000664000175100017510000000244412243421446017114 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. body common control { bundlesequence => { "example" }; } ########################################################### bundle agent example { classes: "matches" expression => hashmatch("/etc/passwd","md5","c5068b7c2b1707f8939b283a2758a691"); reports: matches:: "File has correct version"; } cfengine-3.6.2/examples/package_msi_version.cf0000664000175100017510000000367212243421446021170 0ustar00a10038a1003800000000000000# This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. # # MSI package managment using version criteria # body common control { bundlesequence => { "packages" }; } ############################################# bundle agent packages { vars: "match_package" slist => { "7zip" }; packages: "$(match_package)" package_policy => "update", package_select => ">=", package_architectures => { "x86_64" }, package_version => "3.00", package_method => msi_vmatch; } ############################################# body package_method msi_vmatch { package_changes => "individual"; package_file_repositories => { "$(sys.workdir)\software_updates\windows", "s:\su" }; package_installed_regex => ".*"; package_name_convention => "$(name)-$(version)-$(arch).msi"; package_add_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i"; package_update_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /i"; package_delete_command => "\"$(sys.winsysdir)\msiexec.exe\" /qn /x"; } cfengine-3.6.2/examples/execresult.cf0000644000175100017510000000332012332665147017336 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src prep #@ ``` #@ rm -rf /tmp/testhere #@ mkdir -p /tmp/testhere #@ touch /tmp/testhere/a #@ touch /tmp/testhere/b #@ touch /tmp/testhere/c #@ touch /tmp/testhere/d #@ touch /tmp/testhere/e #@ ``` #+end_src ############################################################################### #+begin_src cfengine3 body common control { bundlesequence => { "example" }; } bundle agent example { vars: "my_result" string => execresult("/bin/ls /tmp/testhere","noshell"); reports: "/bin/ls /tmp/testhere returned '$(my_result)'"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: /bin/ls /tmp/testhere returned 'a #@ b #@ c #@ d #@ e' #@ ``` #+end_src cfengine-3.6.2/examples/lastnode.cf0000644000175100017510000000375612316547775017011 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. #+begin_src cfengine3 body common control { bundlesequence => { "yes" }; } bundle agent yes { vars: "path1" string => "/one/two/last1"; "path2" string => "one:two:last2"; "path4" string => "/one/two/"; "last1" string => lastnode("$(path1)","/"); "last2" string => lastnode("$(path2)",":"); "last3" string => lastnode("$(path2)","/"); "last4" string => lastnode("$(path4)","/"); reports: "Last / node in / path '$(path1)' = '$(last1)'"; "Last : node in : path '$(path2)' = '$(last2)'"; "Last / node in : path '$(path2)' = '$(last3)'"; "Last / node in /-terminated path '$(path4)' = '$(last4)'"; } #+end_src ############################################################################### #+begin_src example_output #@ ``` #@ R: Last / node in / path '/one/two/last1' = 'last1' #@ R: Last : node in : path 'one:two:last2' = 'last2' #@ R: Last / node in : path 'one:two:last2' = 'one:two:last2' #@ R: Last / node in /-terminated path '/one/two/' = '' #@ ``` #+end_src cfengine-3.6.2/examples/server_flatcopy_localhost.cf0000664000175100017510000000650412243421446022434 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ######################################################## # # Simple test copy from server connection to cfServer # ######################################################## # # run this as follows: # # cf-serverd -f runtest_1.cf [-d2] # cf-agent -f runtest_2.cf # # Notice that the same file configures all parts of cfengine ######################################################## body common control { bundlesequence => { "example" }; version => "1.2.3"; } ######################################################## bundle agent example { files: "/home/mark/tmp/testflatcopy" comment => "test copy promise", copy_from => mycopy("/home/mark/LapTop/words","127.0.0.1"), perms => system, depth_search => recurse("inf"), classes => satisfied("copy_ok"); "/home/mark/tmp/testcopy/single_file" comment => "test copy promise", copy_from => mycopy("/home/mark/LapTop/Cfengine3/trunk/README","127.0.0.1"), perms => system; reports: copy_ok:: "Files were copied.."; } ######################################################### body perms system { mode => "0644"; } ######################################################### body depth_search recurse(d) { depth => "$(d)"; } ######################################################### body copy_from mycopy(from,server) { source => "$(from)"; servers => { "$(server)" }; compare => "digest"; verify => "true"; copy_backup => "true"; #/false/timestamp purge => "false"; type_check => "true"; force_ipv4 => "true"; trustkey => "true"; collapse_destination_dir => "true"; } ######################################################### body classes satisfied(x) { promise_repaired => { "$(x)" }; persist_time => "0"; } ######################################################### # Server config ######################################################### body server control { allowconnects => { "127.0.0.1" , "::1" }; allowallconnects => { "127.0.0.1" , "::1" }; trustkeysfrom => { "127.0.0.1" , "::1" }; } ######################################################### bundle server access_rules() { access: "/home/mark/LapTop" admit => { "127.0.0.1" }; } cfengine-3.6.2/examples/locate_files_and_compress.cf0000664000175100017510000000323312243421446022337 0ustar00a10038a1003800000000000000# Copyright (C) Cfengine AS # This file is part of Cfengine 3 - written and maintained by Cfengine AS. # 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; version 3. # 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 # To the extent this program is licensed as part of the Enterprise # versions of Cfengine, the applicable Commercial Open Source License # (COSL) may apply to this file if you as a licensee so wish it. See # included file COSL.txt. ####################################################### # # Compressing files # ####################################################### body common control { bundlesequence => { "example" }; } ############################################ bundle agent example { files: "/home/mark/tmp/testcopy" file_select => pdf_files, transformer => "/usr/bin/gzip $(this.promiser)", depth_search => recurse("inf"); } ############################################ body file_select pdf_files { leaf_name => { ".*.pdf" , ".*.fdf" }; file_result => "leaf_name"; } ############################################ body depth_search recurse(d) { depth => "$(d)"; } cfengine-3.6.2/examples/template2.cf0000664000175100017510000000214512243421446017047 0ustar00a10038a1003800000000000000 body common control { bundlesequence => { "example" }; inputs => { "libraries/cfengine_stdlib.cf" }; } bundle agent example { methods: "any" usebundle => get_template("/tmp/sudoers","400"); "any" usebundle => get_template("/tmp/hosts","644"); } ############################################################# bundle agent get_template(final_destination,mode) { vars: # This needs to ne preconfigured to your site "masterfiles" string => "/home/mark/tmp"; "this_template" string => lastnode("$(final_destination)","/"); files: "$(final_destination).staging" comment => "Get template and expand variables for this host", perms => mo("400","root"), copy_from => remote_cp("$(masterfiles)/templates/$(this_template)","$(policy_server)"), action => if_elapsed("60"); "$(final_destination)" comment => "Expand the template", create => "true", edit_line => expand_template("$(final_destination).staging"), edit_defaults => empty, perms => mo("$(mode)","root"), action => if_elapsed("60"); } cfengine-3.6.2/Makefile.am0000664000175100017510000000761512411001073015050 0ustar00a10038a1003800000000000000AUTOMAKE_OPTIONS = foreign MAKEFLAGS = $(if $(filter-out 0,$(V)),,--no-print-directory --quiet) LCOV_FLAGS = $(if $(filter-out 0,$(V)),,-q) SUBDIRS = libcompat libutils libcfnet libenv libpromises \ cf-agent cf-execd cf-key cf-monitord \ cf-promises cf-runagent cf-serverd cf-upgrade ext examples \ tests DIST_SUBDIRS = libcompat libutils libcfnet libenv libpromises cf-agent cf-execd \ cf-key cf-monitord cf-promises cf-runagent cf-serverd cf-upgrade ext \ examples tests # Set explicitly to avoid picking up {nova}/*.m4 DIST_COMMON = README.md Makefile.am Makefile.in configure AUTHORS aclocal.m4 \ ChangeLog INSTALL config.guess config.sub depcomp install-sh \ ltmain.sh missing ylwrap m4/acinclude.m4 m4/libtool.m4 m4/ltoptions.m4 \ m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 m4/cf3_with_library.m4 \ m4/snprintf.m4 m4/old-autoconf.m4 m4/adl_recursive_eval.m4 m4/strndup.m4 \ m4/cf3_check_proper_func.m4 m4/cf3_platforms.m4 m4/cf3_gcc_flags.m4 \ m4/cf3_path_root_prog.m4 configure.ac autogen.sh configure_flags.env.in EXTRA_DIST = ChangeLog INSTALL README.md LICENSE docsdir = $(docdir) docs_DATA = README.md ChangeLog # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \ configure install-sh missing mkinstalldirs depcomp ylwrap \ ltmain.sh mdate-sh # # Pass proper flags to aclocal to pick up Libtool macros # ACLOCAL_AMFLAGS = -I m4 install-data-local: $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/inputs $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/modules $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/outputs $(MKDIR_P) -m 700 $(DESTDIR)$(workdir)/ppkeys # # Code coverage # clean-coverage: find -L $(srcdir) -name '*.gcda' -delete run-coverage: -$(MAKE) check -k collect-coverage: $(LCOV) $(LCOV_FLAGS) --capture --initial --directory . --output-file cfengine-lcov-base.info $(LCOV) $(LCOV_FLAGS) --capture --directory . --output-file cfengine-lcov.info --test-name CFENGINE --no-checksum --compat-libtool $(LCOV) $(LCOV_FLAGS) -a cfengine-lcov-base.info -a cfengine-lcov.info --output-file cfengine-lcov.info $(LCOV) $(LCOV_FLAGS) --remove cfengine-lcov.info '/usr/include/*' --output-file cfengine-lcov.info LANG=C $(LCOV_GENHTML) $(LCOV_FLAGS) --prefix . --output-directory coverage-html --title "CFEngine Code Coverage" --legend --show-details cfengine-lcov.info @echo @echo " Code coverage information: file://"`pwd`"/coverage-html/index.html" @echo coverage: clean-coverage run-coverage collect-coverage ################################################################################ # Identical to what is in libpromises/Makefile.am. # This is because there is a circular dependency libcfnet <-> libpromises # so we need to generate it before everything else. ################################################################################ BUILT_SOURCES = \ $(srcdir)/libpromises/enterprise_extension.c \ $(srcdir)/libpromises/enterprise_extension.h ENTERPRISE_EXTENSION_GENERATE = $(SED) -f $(srcdir)/libpromises/enterprise_extension.sed $< > $@ ENTERPRISE_EXTENSION_MAKE = @if test -z "$(V)"; then echo " SED " $@; else echo "$(ENTERPRISE_EXTENSION_GENERATE)"; fi; $(ENTERPRISE_EXTENSION_GENERATE) $(srcdir)/libpromises/enterprise_extension.c: libpromises/extensions_template.c libpromises/enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) $(srcdir)/libpromises/enterprise_extension.h: libpromises/extensions_template.h libpromises/enterprise_extension.sed $(ENTERPRISE_EXTENSION_MAKE) # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = cfengine-lcov-base.info cfengine-lcov.info \ $(BUILT_SOURCES) cfengine-3.6.2/configure.ac0000664000175100017510000012347112411001073015301 0ustar00a10038a1003800000000000000dnl ########################################################################## dnl # dnl # Build CFEngine dnl # dnl # Run ./autogen.sh to build configure script dnl # dnl ########################################################################## AC_PREREQ(2.59) AC_INIT AC_CONFIG_SRCDIR([libpromises/generic_agent.c]) AC_CANONICAL_TARGET dnl dnl This program needs to be checked early, as MAKEINFO variable is expanded in dnl AM_INIT_AUTOMAKE. dnl AC_CHECK_PROG(MAKEINFO, makeinfo, makeinfo) define([revision], esyscmd([sh -c "(git rev-list -1 --abbrev-commit HEAD || echo unknown) | tr -d '\n'" 2>/dev/null]))dnl dnl dnl The version in the next line is the only one to set dnl _AM_SET_OPTION([tar-ustar]) AM_INIT_AUTOMAKE(cfengine, 3.6.2) AM_MAINTAINER_MODE([enable]) AC_DEFINE(BUILD_YEAR, esyscmd([date +%Y | tr -d '\n']), "Software build year") AC_DEFINE_UNQUOTED(ABS_TOP_SRCDIR, "`cd -- "$srcdir"; pwd`", [Absolute path of source tree]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_CONFIG_HEADERS([libutils/config.h]) dnl Libtool madness AC_CONFIG_MACRO_DIR([m4]) dnl dnl hide [s]include macros, so old aclocal (automake < 1.10) won't find them and dnl won't complain about something/something.m4 not found dnl m4_define(incstart,sinc) m4_define(incend,lude) dnl dnl Save environment CFLAGS before autoconf starts messing with it. dnl It is restored later. dnl ENV_CFLAGS="$CFLAGS" dnl ###################################################################### dnl Checks for programs. dnl ###################################################################### AC_PROG_CC AC_PROG_MKDIR_P AC_EXEEXT dnl GCC specific flags m4_include([m4/cf3_gcc_flags.m4]) # Use either new LT_INIT or old AC_DISABLE_STATIC/AC_PROG_LIBTOOL macros m4_ifdef([LT_INIT], [LT_INIT([disable-static])], [AC_DISABLE_STATIC AC_PROG_LIBTOOL]) AM_PROG_LEX AC_PROG_YACC AC_PROG_INSTALL AC_CONFIG_LIBOBJ_DIR(libcompat) AC_PATH_PROG(GETCONF, getconf, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) AM_CONDITIONAL(CROSS_COMPILING, test "x$cross_compiling" = "xyes") dnl ###################################################################### dnl Use pthreads if available dnl ###################################################################### AC_ARG_WITH([pthreads], [AS_HELP_STRING([--with-pthreads[[=PATH]]], [Specify path to pthreads, if not the part of operating system])]) if test "x$with_pthreads" != x && test "x$with_pthreads" != "xyes" && test "x$with_pthreads" != "xno"; then LIBS="$LIBS -L$with_pthreads/lib" CPPFLAGS="-I$with_pthreads/include $CPPFLAGS" fi ACX_PTHREAD([], [AC_MSG_ERROR(pthread-compatible library is required to build CFEngine)]) CC="$PTHREAD_CC" CFLAGS="$PTHREAD_CFLAGS $CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" dnl ###################################################################### dnl Whether to build extensions as builtin extensions or a separate dnl plugin. The default is plugin. dnl --enable-builtin-extensions is the default on Windows, and can be dnl used on other platforms for debugging purposes, but isn't otherwise dnl supported. dnl ###################################################################### AC_ARG_ENABLE([builtin-extensions], [AS_HELP_STRING([Build binaries with builtin extensions])], [], [ AS_CASE([${target_os}], [mingw*], [enable_builtin_extensions=yes], [enable_builtin_extensions=no]) ]) AM_CONDITIONAL([BUILTIN_EXTENSIONS], [test "x$enable_builtin_extensions" = "xyes"]) AS_IF([test "x$enable_builtin_extensions" = "xyes"], [AC_DEFINE([BUILTIN_EXTENSIONS], [1], [Define if you want builtin Enterprise extensions])]) AC_SUBST([enable_builtin_extensions]) dnl ###################################################################### dnl Configure files layout dnl ###################################################################### AC_ARG_ENABLE([fhs], [AS_HELP_STRING([--enable-fhs], [Enable FHS compliance. Defaults to custom CFEngine files layout])]) # # pkglibdir/pkgdatadir are not overridable, so use our own invention instead. # AS_IF([test x"$enable_fhs" = xyes], [ projlibdir='${libdir}/cfengine' datadir='${exec_prefix}/share/cfengine' WORKDIR='${localstatedir}/lib/cfengine' MASTERDIR='default' INPUTDIR='default' LOGDIR='${localstatedir}/lib/cfengine' PIDDIR='${localstatedir}/lib/cfengine' ], [ if test x"$prefix" = xNONE || test x"$prefix" = x/var/cfengine; then prefix=/var/cfengine case "$target_os" in mingw*) WORKDIR=$(cmd /c "echo %PROGRAMFILES%\\Cfengine" | sed 's/\\/\\\\/g') MASTERDIR=default INPUTDIR=default LOGDIR=$(cmd /c "echo %PROGRAMFILES%\\Cfengine" | sed 's/\\/\\\\/g') PIDDIR=$(cmd /c "echo %PROGRAMFILES%\\Cfengine" | sed 's/\\/\\\\/g') ;; *) WORKDIR=/var/cfengine MASTERDIR=default INPUTDIR=default LOGDIR=/var/cfengine PIDDIR=/var/cfengine ;; esac else WORKDIR="${localstatedir}/cfengine" MASTERDIR="default" INPUTDIR="default" LOGDIR="${localstatedir}/cfengine" PIDDIR="${localstatedir}/cfengine" fi sbindir='${exec_prefix}/bin' # /var/cfengine/bin despite being sbin_? projlibdir='${exec_prefix}/lib' mandir='${exec_prefix}/share/man' ]) AC_SUBST(projlibdir) dnl ###################################################################### dnl Platform specific compiler flags. dnl ###################################################################### AS_CASE([${target_os}], [mingw*], # Disable printf format warnings, because our wrapper supports more # flags than vanilla Windows version, so they are false positives. [CFLAGS="$CFLAGS -Wno-format"]) dnl ###################################################################### dnl Enable debugging dnl ###################################################################### AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [Enable debugging]), [debug=$enableval], [debug=no]) AM_CONDITIONAL([NDEBUG], [test x"$debug" = x"no"]) dnl Even though CFLAGS should contain the command-line CFLAGS dnl as last, some macro seem to messes the order up and insert dnl its own optimisation flags as well. So we append ENV_CFLAGS dnl at the end manually, causing a bit of flag duplication. if test x"$debug" = x"yes" then CFLAGS="$CFLAGS -g3 -O0 $ENV_CFLAGS" else CFLAGS="$CFLAGS -O2 -DNDEBUG $ENV_CFLAGS" fi dnl ###################################################################### dnl Checks for libraries. dnl ###################################################################### dnl Now check for database connectors # TODO remove AC_ARG_WITH([sql], [AS_HELP_STRING([--with-sql[[=PATH]]], [Enable SQL database connectors (deprecated, use \ --with[[out]]-postgresql and --with[[out]]-mysql instead)]) ], [with_postgresql=$with_sql; with_mysql=$with_sql], []) dnl PostgreSQL AC_ARG_WITH([postgresql], [AS_HELP_STRING([--with-postgresql[[=PATH]]], [Enable PostgreSQL connector]) ], [], [with_postgresql=check]) if test "x$with_postgresql" != "xno" then if test "x$with_postgresql" != xyes && test "x$with_postgresql" != xcheck then PG_CONFIG=$with_postgresql/bin/pg_config else PG_CONFIG=pg_config fi # pg_config is only for native builds if test "x$cross_compiling" = "xno" then if test x`which $PG_CONFIG` != x then pg_include_dir=`$PG_CONFIG --includedir` if test -n "$pg_include_dir" then POSTGRESQL_CPPFLAGS="-I$pg_include_dir" fi fi fi CF3_WITH_LIBRARY(postgresql, [AC_CHECK_LIB(pq, PQconnectdb, [], [if test "x$with_postgresql" != xcheck; then AC_MSG_ERROR(Cannot find PostgreSQL client library); fi] ) AC_CHECK_HEADERS(libpq-fe.h, [], [if test "x$with_postgresql" != xcheck; then AC_MSG_ERROR(Cannot find PostgreSQL client library); fi] )] ) fi dnl MySQL AC_ARG_WITH([mysql], [AS_HELP_STRING([--with-mysql[[=PATH]]], [Enable MySQL connector]) ], [], [with_mysql=check]) if test "x$with_mysql" != "xno" then if test "x$with_mysql" != xyes && test "x$with_mysql" != xcheck then MYSQL_CONFIG=$with_mysql/bin/mysql_config else MYSQL_CONFIG=mysql_config fi # mysql_config is only for native builds if test "x$cross_compiling" = "xno" then if test x`which $MYSQL_CONFIG` != x then mysql_include_dir=`$MYSQL_CONFIG --include` if test -n "$mysql_include_dir" then MYSQL_CPPFLAGS="$mysql_include_dir" fi fi fi CF3_WITH_LIBRARY(mysql, [AC_CHECK_LIB(mysqlclient, mysql_real_connect, [], [if test "x$with_mysql" != xcheck; then AC_MSG_ERROR(Cannot find MySQL client library); fi] ) AC_CHECK_HEADERS(mysql.h, [], [if test "x$with_mysql" != xcheck; then AC_MSG_ERROR(Cannot find MySQL clientlibrary); fi] ) AC_CHECK_LIB(mysqlclient, EVP_CIPHER_CTX_init, [AC_MSG_ERROR([MySQL client library exports symbols clashing \ with OpenSSL. Get the update from distribution provider, \ recompile MySQL library or disable MySQL connector. See \ http://bugs.mysql.com/bug.php?id=65055 for details.]) ] )] ) fi dnl dnl In-process databases dnl dnl QDBM AC_ARG_WITH([qdbm], [AS_HELP_STRING([--with-qdbm[[=PATH]]], [use QDBM to store runtime data])]) AS_IF([test -n "$with_qdbm" && test "x$with_qdbm" != "xno"], [WITH_QDBM=1], [WITH_QDBM=0]) if test $WITH_QDBM = 1; then CF3_WITH_LIBRARY(qdbm, [ AC_CHECK_LIB(qdbm, dpopen, [], [AC_MSG_ERROR(Cannot find QDBM)]) AC_CHECK_HEADERS(depot.h, [], [AC_MSG_ERROR(Cannot find QDBM)]) AC_DEFINE(QDB, 1, [Define if QDBM is available]) ]) fi dnl Tokyo Cabinet AC_ARG_WITH([tokyocabinet], [AS_HELP_STRING([--with-tokyocabinet[[=PATH]]], [use Tokyo Cabinet to store runtime data])]) AS_IF([test $WITH_QDBM -eq 0 && test -n "$with_tokyocabinet" && test "x$with_tokyocabinet" != "xno"], [WITH_TOKYO=1], [WITH_TOKYO=0]) if test $WITH_TOKYO = 1; then CF3_WITH_LIBRARY(tokyocabinet, [ AC_CHECK_LIB(tokyocabinet, tchdbnew, [], [AC_MSG_ERROR(Cannot find Tokyo Cabinet)]) AC_CHECK_HEADERS(tcutil.h, [], [AC_MSG_ERROR(Cannot find Tokyo Cabinet)]) AC_CHECK_HEADERS(tchdb.h, [], [AC_MSG_ERROR(Cannot find Tokyo Cabinet)]) AC_DEFINE(TCDB, 1, [Define if Tokyo Cabinet is available.]) ]) fi dnl OpenLDAP Lightning MDB AC_ARG_WITH([lmdb], [AS_HELP_STRING([--with-lmdb[[=PATH]]], [use Lightning MDB to store runtime data])]) AS_IF([test $WITH_TOKYO -eq 0 && test $WITH_QDBM -eq 0 && (! test -n "$with_lmdb" || test "x$with_lmdb" != "xno")], [WITH_LMDB=1], [WITH_LMDB=0]) if test $WITH_LMDB = 1; then CF3_WITH_LIBRARY(lmdb, [ AC_CHECK_LIB(lmdb, mdb_dbi_open, [], [AC_MSG_ERROR(Cannot find Lightning MDB)]) AC_CHECK_HEADERS(lmdb.h, [], [AC_MSG_ERROR(Cannot find Lightning MDB)]) AC_DEFINE(LMDB, 1, [Define if Lightning MDB is available]) ]) fi if test $WITH_QDBM -eq 0 && test $WITH_TOKYO -eq 0 && test $WITH_LMDB -eq 0; then AC_MSG_ERROR(Either Tokyo Cabinet, LMDB, or QDBM must be selected to compile CFEngine) fi dnl dnl OpenSSL dnl AC_ARG_WITH(openssl, [AS_HELP_STRING([--with-openssl[[=PATH]]], [Specify OpenSSL path])], [], [with_openssl=yes]) if test x"$with_openssl" = xno ; then AC_MSG_ERROR([This release of CFEngine requires OpenSSL >= 0.9.7]) fi CF3_WITH_LIBRARY(openssl, [ AC_CHECK_LIB(crypto, RSA_generate_key_ex, [], []) AC_CHECK_LIB(ssl, SSL_library_init, [], []) AC_CHECK_DECLS([SSL_CTX_clear_options], [], [], [[#include ]]) AC_CHECK_HEADERS([openssl/opensslv.h], [], [AC_MSG_ERROR(Cannot find OpenSSL)]) AC_MSG_CHECKING(for OpenSSL version) AC_PREPROC_IFELSE([AC_LANG_SOURCE([[ #include #if OPENSSL_VERSION_NUMBER < 0x0090602fL #This OpenSSL is too old #endif ]])],[AC_MSG_RESULT(OK)],[AC_MSG_ERROR(This release of CFEngine requires OpenSSL >= 0.9.7)]) if test "x$ac_cv_lib_crypto_RSA_generate_key_ex" = "xyes" ; then AC_DEFINE(OPENSSL_NO_DEPRECATED, 1, [Define if non deprecated API is available.]) fi if test "x$ac_cv_lib_crypto_RSA_generate_key_ex" = "xno" && \ test "x$ac_cv_lib_crypto_RSA_generate_key" = "xno" ; then AC_MSG_ERROR(Cannot find OpenSSL) fi ]) dnl PCRE AC_ARG_WITH([pcre], [AS_HELP_STRING([--with-pcre[[=PATH]]], [Specify PCRE path])], [], [with_pcre=yes]) if test "x$with_pcre" = "xno"; then AC_MSG_ERROR([PCRE is required]) fi CF3_WITH_LIBRARY(pcre, [ AC_CHECK_LIB(pcre, pcre_exec, [], [AC_MSG_ERROR(Cannot find PCRE)]) AC_CHECK_HEADERS([pcre.h], [], [AC_CHECK_HEADERS([pcre/pcre.h], [], AC_MSG_ERROR(Cannot find PCRE))]) ]) dnl libvirt AC_ARG_WITH([libvirt], [AS_HELP_STRING([--with-libvirt[[=PATH]]], [support virtual machine management])], [], [with_libvirt=check]) if test "x$with_libvirt" != xno; then CF3_WITH_LIBRARY(libvirt, [ AC_CHECK_LIB(virt, virConnectOpen, [], [if test "x$with_libvirt" != xcheck; then AC_MSG_ERROR(Cannot find libvirt library); fi]) AC_CHECK_HEADERS(libvirt/libvirt.h, [], [if test "x$with_libvirt" != xcheck; then AC_MSG_ERROR(Cannot find libvirt library headers); fi]) ]) fi dnl libacl AC_ARG_WITH([libacl], [AS_HELP_STRING([--with-libacl[[=PATH]]], [Specify libacl path])], [], [with_libacl=check]) if test "x$with_libacl" != xno; then CF3_WITH_LIBRARY(libacl, [ AC_CHECK_LIB(acl, acl_init, [], [if test "x$with_libacl" != xcheck; then AC_MSG_ERROR(Cannot find libacl library); fi]) AC_CHECK_HEADERS([acl.h sys/acl.h acl/libacl.h], [libacl_header_found=yes]) if test "x$libacl_header_found" != "xyes" && test "x$with_libacl" != xcheck; then AC_MSG_ERROR(Cannot find libacl library headers); fi ]) fi dnl libxml2 AC_ARG_WITH([libxml2], [AS_HELP_STRING([--with-libxml2[[=PATH]]], [Specify libxml2 path]) ], [], [with_libxml2=check]) if test "x$with_libxml2" != xno then if test "x$with_libxml2" != xyes && test "x$with_libxml2" != xcheck then XML2_CONFIG=$with_libxml2/bin/xml2-config else XML2_CONFIG=xml2-config fi # xml2-config is only for native builds if test "x$cross_compiling" = "xno" && test x`which $XML2_CONFIG` != x then xml2_include_dir=`$XML2_CONFIG --cflags` if test -n "$xml2_include_dir" then LIBXML2_CPPFLAGS="$xml2_include_dir" fi else # xml2-config not found # if a path, e.g. /var/cfengine was given, then we # must take into account that libxml2 includes are in # /var/cfengine/include/libxml2 LIBXML2_CPPFLAGS=-I$with_libxml2/include/libxml2 fi CF3_WITH_LIBRARY(libxml2, [AC_CHECK_LIB(xml2, xmlFirstElementChild, [], [if test "x$with_libxml2" != xcheck; then AC_MSG_ERROR(Cannotfind libxml2); fi] ) AC_CHECK_HEADERS([libxml/xmlwriter.h], [break], [if test "x$with_libxml2" != xcheck; then AC_MSG_ERROR(Cannot find libxml2); fi] )] ) fi AM_CONDITIONAL([HAVE_LIBXML2], [test "x$with_libxml2" != xno && test "x$ac_cv_lib_xml2_xmlFirstElementChild" = xyes]) dnl avahi AC_CHECK_HEADERS(avahi-client/client.h, AM_CONDITIONAL(HAVE_AVAHI_CLIENT, true), AM_CONDITIONAL(HAVE_AVAHI_CLIENT, false), []) AC_CHECK_HEADERS(avahi-common/address.h, AM_CONDITIONAL(HAVE_AVAHI_COMMON, true), AM_CONDITIONAL(HAVE_AVAHI_COMMON, false), []) dnl dnl ###################################################################### dnl Checks for header files. dnl ###################################################################### AC_CHECK_HEADERS(unistd.h stdlib.h sys/loadavg.h) AC_CHECK_HEADERS(sys/param.h) # sys/param.h is required for sys/mount.h on OpenBSD AC_CHECK_HEADERS(sys/mount.h, [], [], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_PARAM_H # include #endif ]) # Required on BSD to get struct sockaddr_dl (for retrieving MAC addresses from getifaddrs()) AC_CHECK_HEADERS(net/if_dl.h) AC_CHECK_HEADERS(utime.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(sys/time.h) AC_CHECK_HEADERS(malloc.h sys/malloc.h) AC_CHECK_HEADERS(vfs.h) AC_CHECK_HEADERS(sys/vfs.h) AC_CHECK_HEADERS(sys/sockio.h) AC_CHECK_HEADERS(sys/statvfs.h) AC_CHECK_HEADERS(sys/statfs.h) AC_CHECK_HEADERS(fcntl.h) AC_CHECK_HEADERS(sys/filesys.h) AC_CHECK_HEADERS(dustat.h) AC_CHECK_HEADERS(sys/systeminfo.h) AC_CHECK_HEADERS(ieeefp.h) AC_CHECK_HEADERS(winsock2.h) AC_CHECK_HEADERS(ws2tcpip.h) AC_CHECK_HEADERS(zone.h) AC_CHECK_HEADERS(sys/uio.h) AC_CHECK_HEADERS(sys/types.h) AC_CHECK_HEADERS(sys/mpctl.h) dnl For HP-UX $(sys.cpus) - Mantis #1069 AC_CHECK_HEADERS(shadow.h) AC_CHECK_HEADERS(sys/jail.h, [], [], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_PARAM_H # include #endif ]) AC_HEADER_STDC AC_HEADER_TIME AC_HEADER_SYS_WAIT AC_HEADER_DIRENT AC_HEADER_STDBOOL dnl ###################################################################### dnl Checks for data types dnl ###################################################################### AC_TYPE_MODE_T AC_TYPE_SIZE_T AC_TYPE_UID_T AC_TYPE_PID_T AC_CHECK_TYPES(clockid_t) AC_CHECK_TYPES(socklen_t, [], [], [[ #ifdef HAVE_SYS_TYPES_H # include #endif #include ]]) dnl ###################################################################### dnl Checks for typedefs, structures, and compiler characteristics. dnl ###################################################################### AC_C_CONST AC_FUNC_FSEEKO AC_SYS_LARGEFILE AC_TYPE_OFF_T # # AC_SYS_LARGEFILE correctly figures out necessary macros for large files, but # on AIX there is a gotcha: # # Code generated by flex #includes at the beginning of the file, which # picks up 32-bit wide off_t. Then it #includes which provides LFS # macros, and finally it includes another system header, now with 64-bit wide # off_t, which causes a conflict. # if test "x$ac_cv_sys_large_files" = x1; then CPPFLAGS="-D_LARGE_FILES=1 $CPPFLAGS" fi dnl ###################################################################### dnl Check for libraries dnl ###################################################################### AC_CHECK_LIB(m, sqrt) AC_CHECK_LIB(rt, clock_gettime) AC_CHECK_LIB(dl, dlopen) dnl ###################################################################### dnl Check for special functions dnl ###################################################################### AC_CHECK_DECLS(clock_gettime, [], [], [[#include ]]) AC_REPLACE_FUNCS(clock_gettime) AC_CHECK_DECLS(unsetenv) AC_REPLACE_FUNCS(unsetenv) AC_CHECK_DECLS(strnlen) AC_REPLACE_FUNCS(strnlen) cf3_FUNC_STRNDUP AC_CHECK_DECLS(setlinebuf) AC_REPLACE_FUNCS(setlinebuf) AC_CHECK_DECLS(strlcat) AC_REPLACE_FUNCS(strlcat) AC_CHECK_DECLS(strlcpy) AC_REPLACE_FUNCS(strlcpy) AC_CHECK_DECLS(realpath) AC_CHECK_DECLS(strdup) AC_REPLACE_FUNCS(strdup) AC_CHECK_DECLS(memrchr) AC_REPLACE_FUNCS(memrchr) AC_CHECK_DECLS(round, [], [], [[#include ]]) AC_REPLACE_FUNCS(round) AC_CHECK_DECLS(nanosleep) AC_REPLACE_FUNCS(nanosleep) AC_CHECK_DECLS(memdup) AC_REPLACE_FUNCS(memdup) AC_CHECK_DECLS(memmem) AC_REPLACE_FUNCS(memmem) AC_CHECK_DECLS(srand48) AC_REPLACE_FUNCS(srand48) AC_CHECK_DECLS(drand48) AC_REPLACE_FUNCS(drand48) AC_CHECK_DECLS(strerror) AC_REPLACE_FUNCS(strerror) AC_CHECK_DECLS(strstr) AC_REPLACE_FUNCS(strstr) AC_CHECK_DECLS(strcasestr) AC_REPLACE_FUNCS(strcasestr) AC_CHECK_DECLS(strcasecmp) AC_REPLACE_FUNCS(strcasecmp) AC_CHECK_DECLS(strncasecmp) AC_REPLACE_FUNCS(strncasecmp) AC_CHECK_DECLS(strsep) AC_REPLACE_FUNCS(strsep) AC_CHECK_DECLS(strsignal) AC_REPLACE_FUNCS(strsignal) AC_CHECK_DECLS(gmtime_r, [], [], [[#include ]]) AC_REPLACE_FUNCS(gmtime_r) AC_CHECK_DECLS(getline, [], [], [#define _GNU_SOURCE 1 AC_INCLUDES_DEFAULT]) AC_REPLACE_FUNCS(getline) AC_CHECK_DECLS(localtime_r, [], [], [[#include ]]) AC_REPLACE_FUNCS(localtime_r) AC_CHECK_DECLS(fgetgrent, [], [], [[#include ]]) AC_CHECK_DECLS(isfinite, [], [], [[#include ]]) AC_CHECK_FUNCS(getpwent setpwent endpwent) AC_CHECK_FUNCS(fgetspent lckpwdf ulckpwdf) AC_CHECK_DECLS(getloadavg) AC_FUNC_GETLOADAVG AC_C_BIGENDIAN AC_CHECK_HEADERS([endian.h]) AC_CHECK_DECLS(le32toh, [], [], [[#include ]]) CF3_PATH_ROOT_PROG([CHPASSWD], [chpasswd], [], [/sbin:/usr/sbin:/bin:/usr/bin:$PATH]) AS_IF([test "x$CHPASSWD" != "x"], [AC_DEFINE(HAVE_CHPASSWD, 1, [Define if chpasswd tool is present])] [AC_DEFINE_UNQUOTED(CHPASSWD, ["$CHPASSWD"], [Path to chpasswd tool])] ) dnl AIX has this. CF3_PATH_ROOT_PROG([PWDADM], [pwdadm], [], [/sbin:/usr/sbin:/bin:/usr/bin:$PATH]) AS_IF([test "x$PWDADM" != "x"], [AC_DEFINE(HAVE_PWDADM, 1, [Define if pwdadm tool is present])] [AC_DEFINE_UNQUOTED(PWDADM, ["$PWDADM"], [Path to pwdadm tool])] ) CF3_PATH_ROOT_PROG([USERADD], [useradd], [], [/sbin:/usr/sbin:/bin:/usr/bin:$PATH]) AS_IF([test "x$USERADD" != "x"], [AC_DEFINE(HAVE_USERADD, 1, [Define if useradd tool is present])] [AC_DEFINE_UNQUOTED(USERADD, ["$USERADD"], [Path to useradd tool])] ) CF3_PATH_ROOT_PROG([USERMOD], [usermod], [], [/sbin:/usr/sbin:/bin:/usr/bin:$PATH]) AS_IF([test "x$USERMOD" != "x"], [AC_DEFINE(HAVE_USERMOD, 1, [Define if usermod tool is present])] [AC_DEFINE_UNQUOTED(USERMOD, ["$USERMOD"], [Path to usermod tool])] ) CF3_PATH_ROOT_PROG([USERDEL], [userdel], [], [/sbin:/usr/sbin:/bin:/usr/bin:$PATH]) AS_IF([test "x$USERDEL" != "x"], [AC_DEFINE(HAVE_USERDEL, 1, [Define if userdel tool is present])] [AC_DEFINE_UNQUOTED(USERDEL, ["$USERDEL"], [Path to userdel tool])] ) AS_IF([test "x$USERADD" != x && \ test "x$USERMOD" != x && test "x$USERDEL" != x], [have_userprogs=yes], [have_userprogs=no] ) AC_ARG_WITH([pam], AS_HELP_STRING([--with-pam], [Compile with PAM support])) AS_IF([test x$with_pam != xno], [ CF3_WITH_LIBRARY(pam, [ AC_CHECK_LIB(pam, pam_start) AC_CHECK_HEADERS([security/pam_appl.h]) ]) dnl These platforms must have pam, others can have it, but not required. AS_CASE([$target_os], [*gnu*|*solaris*|*aix*|*hpux*|*hp-ux*], [ AS_IF([test "x$ac_cv_lib_pam_pam_start" != "xyes"], [AC_MSG_ERROR(Cannot find PAM library)] ) AS_IF([test "x$ac_cv_header_security_pam_appl_h" != "xyes"], [AC_MSG_ERROR(Cannot find PAM headers)] )] ) AS_IF([test "x$ac_cv_lib_pam_pam_start" = "xyes" && \ test "x$ac_cv_header_security_pam_appl_h" = "xyes"], [have_pam=yes], [have_pam=no] ) AC_CHECK_FUNCS(fgetpwent fgetgrent) AS_IF([test "x$have_pam" = "xyes" && \ test "x$have_userprogs" = "xyes" && \ test "x$ac_cv_func_fgetpwent" = "xyes" && \ test "x$ac_cv_func_fgetgrent" = "xyes"], [ users_promises_ok=yes ],[ users_promises_ok=no ]) ], [ users_promises_ok=no ]) AM_CONDITIONAL(HAVE_USERS_PROMISE_DEPS, [test "x$users_promises_ok" = "xyes"]) AC_CHECK_DECLS(getnetgrent, [], [], [[#include ]]) AC_CHECK_FUNCS(getnetgrent) AC_CHECK_DECLS(setnetgrent, [], [], [[#include ]]) AC_CHECK_FUNCS(setnetgrent) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[extern int setnetgrent(const char *)]])], [AC_DEFINE([SETNETGRENT_RETURNS_INT], 1, [Whether setnetgrent returns int])], [AC_DEFINE([SETNETGRENT_RETURNS_INT], 0, [Whether setnetgrent returns int])]) AC_CHECK_DECLS(endnetgrent, [], [], [[#include ]]) AC_CHECK_FUNCS(endnetgrent) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[extern int endnetgrent(const char *)]])], [AC_DEFINE([ENDNETGRENT_RETURNS_INT], 1, [Whether endnetgrent returns int])], [AC_DEFINE([ENDNETGRENT_RETURNS_INT], 0, [Whether endnetgrent returns int])]) AC_CHECK_FUNCS(sendto) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)]])], [AC_DEFINE([SENDTO_RETURNS_SSIZE_T], 1, [Whether sendto returns ssize_t])], [AC_DEFINE([SENDTO_RETURNS_SSIZE_T], 0, [Whether sendto does not returns ssize_t])]) CF3_CHECK_PROPER_FUNC([ctime], [], [[#error ctime(3) may produce different results on different OSes. Let's have our POSIX-compliant implementation all the time]], [#define ctime rpl_ctime]) CF3_REPLACE_PROPER_FUNC([ctime]) dnl Check whether mkdir accepts two parameters CF3_CHECK_PROPER_FUNC([mkdir], [[#include #include ]], [[int mkdir(const char *pathname, mode_t mode);]], [#define mkdir rpl_mkdir]) dnl Check for Win32 stat. We don't know to detect improper stat during dnl compilation, so we resort to OS type detection. CF3_CHECK_PROPER_FUNC([stat], [[#include #include ]], [[#if defined(__MINGW32__) #error stat in Windows CRT ill-behaves #endif]], []) dnl Check for Win32 rename. We don't know how to detect improper rename (not dnl removing target file if it exists) during cross-compilation, so we resort to dnl OS type detection. CF3_CHECK_PROPER_FUNC([rename], [], [[#if defined(__MINGW32__) #error rename in Windows CRT ill-behaves #endif]], [#define rename rpl_rename]) AC_CHECK_DECLS(mkdtemp) AC_REPLACE_FUNCS(mkdtemp) AC_CHECK_DECLS(strrstr) AC_REPLACE_FUNCS(strrstr) AC_CHECK_FUNCS(seteuid setegid setreuid setregid) AC_CHECK_FUNCS(uname gethostname chflags) AC_CHECK_FUNCS(mkfifo statfs statvfs door) AC_CHECK_FUNCS(sysinfo setsid sysconf) AC_CHECK_FUNCS(getzoneid getzonenamebyid) AC_CHECK_FUNCS(fpathconf) AC_CHECK_MEMBERS([struct stat.st_mtim, struct stat.st_mtimespec]) AC_MSG_CHECKING([for PRIuMAX/PRIdMAX macros]) AC_EGREP_CPP([primacros_found], AC_INCLUDES_DEFAULT [#include #if defined(PRIuMAX) && defined(PRIdMAX) primacros_found #endif ], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_MSG_RESULT(Unable to find out how to scan intmax_t/uintmax_t types)]) HW_FUNC_VSNPRINTF HW_FUNC_SNPRINTF HW_FUNC_VASPRINTF HW_FUNC_ASPRINTF dnl dirfd might be a function or a macro AC_CHECK_DECLS(dirfd, [], [], [AC_INCLUDES_DEFAULT #ifdef HAVE_DIRENT_H # include #endif ]) AC_CHECK_FUNCS(dirfd, [], [ AC_MSG_CHECKING([for dirfd macro]) AC_EGREP_CPP([dirfd_found], AC_INCLUDES_DEFAULT [#ifdef HAVE_DIRENT_H # include #endif #ifdef dirfd dirfd_found #endif ], [AC_MSG_RESULT(yes) DIRFD_MACRO_FOUND=1], [AC_MSG_RESULT(no)]) if test x$DIRFD_MACRO_FOUND = x; then AC_LIBOBJ([dirfd]) fi]) AC_CHECK_FUNCS(jail_get) dnl dnl Various functions dnl AC_SEARCH_LIBS(setsockopt, socket) AC_SEARCH_LIBS(gethostent, nsl) AC_CHECK_FUNCS(socket) AC_CHECK_FUNCS(setsockopt) AC_CHECK_FUNCS(gethostent) AC_CHECK_TYPES(struct sockaddr_storage, [], [], [[ #if HAVE_WINSOCK2_H #include #endif #if HAVE_WS2TCPIP_H #include #else #include #include #endif]]) AC_CHECK_DECLS(getaddrinfo, [], [AC_LIBOBJ(getaddrinfo)], [[ #if HAVE_WINSOCK2_H #include #endif #if HAVE_WS2TCPIP_H #include #else #include #include #endif ]]) AC_CHECK_DECLS([[inet_ntop], [inet_pton]], [], [], [[#include ]]) AC_REPLACE_FUNCS(inet_ntop inet_pton) AC_CHECK_FUNCS(getifaddrs) AC_CHECK_FUNCS(getprocs64) AC_CHECK_FUNC(lchown, AC_DEFINE(HAVE_LCHOWN, 1, [Whether to use lchown(3) to change ownerships])) AC_CHECK_DECLS(pthread_attr_setstacksize, [], [], [[#include ]]) AC_REPLACE_FUNCS(pthread_attr_setstacksize) AC_CHECK_DECLS(pthread_sigmask, [], [], [[#include ]]) AC_REPLACE_FUNCS(pthread_sigmask) AC_CHECK_DECLS([openat], [], [], [[#include ]]) AC_CHECK_DECLS([fstatat], [], [], [[#include ]]) AC_CHECK_DECLS([fchownat], [], [], [[#include ]]) AC_REPLACE_FUNCS(openat fstatat fchownat) AC_CHECK_DECLS([log2], [], [], [[#include ]]) AC_REPLACE_FUNCS(log2) dnl ###################################################################### dnl Required by cf-upgrade. It cannot be implemented in libcompat because dnl cf-upgrade does not link to any libraries except libutils and only dnl statically. dnl ###################################################################### AC_CHECK_FUNC(fexecve, AC_DEFINE(HAVE_FEXECVE, 1, [Whether to use fexecve(3) to execute a new process])) dnl ###################################################################### dnl These need declarations here, but will be defined in the dnl Enterprise Windows code. dnl ###################################################################### AC_CHECK_DECLS(alarm) AC_CHECK_DECLS(chmod) AC_CHECK_DECLS(chown) AC_CHECK_FUNCS(fchmod) AC_CHECK_DECLS(uname) AC_CHECK_DECLS(getuid) AC_CHECK_DECLS(getgid) AC_CHECK_DECLS(lstat) AC_CHECK_FUNCS(sleep) AC_CHECK_DECLS(socketpair, [], [], [[#include ]]) AC_CHECK_DECLS(fsync) AC_CHECK_DECLS(glob, [], [], [[#include ]]) dnl ###################################################################### dnl Check for sa_len in struct sockaddr dnl ###################################################################### AC_CHECK_MEMBERS([struct sockaddr.sa_len], , , [ #include #include ]) AC_CHECK_MEMBERS([struct ifreq.ifr_hwaddr],,, [ #include #include ]) dnl BSD uses sys/sysctl.h for CPU counting AC_CHECK_HEADERS(sys/sysctl.h, [], [], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_PARAM_H # include #endif ]) dnl ###################################################################### dnl Requirements for GetUptimeMinutes() to set $(sys.uptime) dnl ###################################################################### dnl Linux sysinfo() call AC_CHECK_MEMBERS([struct sysinfo.uptime], , , [#include ]) dnl BSD uses sys/sysctl.h to get time-of-boot AC_CHECK_HEADERS(sys/sysctl.h, [], [], [AC_INCLUDES_DEFAULT #ifdef HAVE_SYS_PARAM_H # include #endif ]) dnl Solaris uses kstat.h to get time-of-boot AC_CHECK_HEADERS(kstat.h) dnl SystemV way to get uptime, highly portable AC_CHECK_HEADERS(utmp.h) dnl POSIX way to get uptime AC_CHECK_HEADERS(utmpx.h) dnl ####################################################################### dnl Newer BSD systems don't have a compatible rtentry - use ortentry dnl ####################################################################### rtry=none AC_MSG_CHECKING(for either struct rtentry or struct ortentry) AC_EGREP_HEADER(rtentry, net/route.h, rtry=rtentry) if test "$rtry" = rtentry; then AC_DEFINE(HAVE_RTENTRY, 1, [Do we have any route entry structure?]) fi AC_EGREP_HEADER(ortentry, net/route.h, rtry=ortentry) if test "$rtry" = ortentry; then AC_DEFINE(HAVE_ORTENTRY, 1, [The old route entry structure in newer BSDs]) fi AC_MSG_RESULT([$rtry]) dnl ####################################################################### dnl Enable extended attributes. Used for SELinux and ACLs dnl ####################################################################### AC_CHECK_FUNCS(listxattr, [AC_DEFINE(WITH_XATTR, 1, [Define if you have a libc that supports extended attributes])]) AC_CHECK_HEADERS([attr/xattr.h sys/xattr.h]) AC_MSG_CHECKING([whether xattr functions have extra arguments]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include #include ], [(void)listxattr("", 0, 0, 0); (void)getxattr("", "", 0, 0, 0, 0); (void)setxattr("", "", "", 0, 0, 0); (void)removexattr("", "", 0);])], [AC_DEFINE(WITH_XATTR_EXTRA_ARGS, 1, [Define if your xattr implementation has extra arguments])] [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) dnl ###################################################################### dnl Give the chance to enable SELINUX dnl ###################################################################### AC_ARG_ENABLE([selinux], [AS_HELP_STRING([--enable-selinux], [Deprecated. SELinux support is always enabled])]) dnl ###################################################################### dnl Collect all the options dnl ###################################################################### CORE_CPPFLAGS="$LMDB_CPPFLAGS $TOKYOCABINET_CPPFLAGS $QDBM_CPPFLAGS $PCRE_CPPFLAGS $OPENSSL_CPPFLAGS $SQLITE3_CPPFLAGS $LIBACL_CPPFLAGS $POSTGRESQL_CPPFLAGS $MYSQL_CPPFLAGS $LIBXML2_CPPFLAGS $CPPFLAGS" CORE_CFLAGS="$LMDB_CFLAGS $TOKYOCABINET_CFLAGS $QDBM_CFLAGS $PCRE_CFLAGS $OPENSSL_CFLAGS $SQLITE3_CFLAGS $LIBACL_CFLAGS $POSTGRESQL_CFLAGS $MYSQL_CFLAGS $LIBXML2_CFLAGS $CFLAGS" CORE_LDFLAGS="$LMDB_LDFLAGS $TOKYOCABINET_LDFLAGS $QDBM_LDFLAGS $PCRE_LDFLAGS $OPENSSL_LDFLAGS $SQLITE3_LDFLAGS $LIBACL_LDFLAGS $POSTGRESQL_LDFLAGS $MYSQL_LDFLAGS $LIBXML2_LDFLAGS $LDFLAGS" CORE_LIBS="$LMDB_LIBS $TOKYOCABINET_LIBS $QDBM_LIBS $PCRE_LIBS $OPENSSL_LIBS $SQLITE3_LIBS $LIBACL_LIBS $POSTGRESQL_LIBS $MYSQL_LIBS $LIBXML2_LIBS $LIBS" dnl ###################################################################### dnl Make them available to subprojects. dnl ###################################################################### AC_SUBST([CORE_CPPFLAGS]) AC_SUBST([CORE_CFLAGS]) AC_SUBST([CORE_LDFLAGS]) AC_SUBST([CORE_LIBS]) AC_CONFIG_FILES([configure_flags.env]) dnl ###################################################################### dnl OS specific stuff dnl ###################################################################### case "$target_os" in solaris2.8|solaris2.9) AC_DEFINE(_XOPEN_SOURCE, 500, [UNIX 98]) AC_DEFINE(__EXTENSIONS__, 1, [Extended UNIX 98 interfaces]) ;; solaris2.10|solaris2.11) AC_DEFINE(_XOPEN_SOURCE, 600, [SUSv3]) AC_DEFINE(__EXTENSIONS__, 1, [Extended UNIX 98 interfaces]) ;; hpux*|hp-ux*) ;; aix*) CPPFLAGS="$CPPFLAGS -w" ;; linux*|*bsd*gnu) AC_CHECK_LIB(nss_nis, yp_get_default_domain) ;; freebsd*|dragonfly*) ;; netbsd*) ;; unicos*) ;; cray*) ;; qnx*) ;; openbsd*|obsd*) ;; gnu*) ;; sysv4.2MP|unix_sv*) ;; cygwin*) ;; mingw*) ;; sco*) ;; darwin*) ;; *) AC_MSG_ERROR(Unknown system type $target_os) ;; esac m4_include([m4/cf3_platforms.m4]) dnl ##################################################################### dnl Configure LOCKDIR and LOGDIR dnl ##################################################################### AC_ARG_WITH(workdir, [ --with-workdir=WORKDIR default internal for trusted cache ], [ if test x$withval != x ; then WORKDIR=$withval LOGDIR=$withval PIDDIR=$withval fi ], ) dnl Expand ${prefix} and whatnot in WORKDIR adl_RECURSIVE_EVAL("${WORKDIR}", WORKDIR) AC_DEFINE_UNQUOTED(WORKDIR, "${WORKDIR}", [Workdir location]) AC_SUBST(workdir, "${WORKDIR}") AC_ARG_WITH(masterdir, [ --with-masterdir=MASTERDIR default internal for masterfiles directory ], [ if test x$withval != x ; then MASTERDIR=$withval fi ], ) dnl Expand ${prefix} and whatnot in MASTERDIR adl_RECURSIVE_EVAL("${MASTERDIR}", MASTERDIR) AC_DEFINE_UNQUOTED(MASTERDIR, "${MASTERDIR}", [Masterfiles directory location]) AC_SUBST(masterdir, "${MASTERDIR}") AC_ARG_WITH(inputdir, [ --with-inputdir=INPUTDIR default internal for inputs directory ], [ if test x$withval != x ; then INPUTDIR=$withval fi ], ) dnl Expand ${prefix} and whatnot in INPUTDIR adl_RECURSIVE_EVAL("${INPUTDIR}", INPUTDIR) AC_DEFINE_UNQUOTED(INPUTDIR, "${INPUTDIR}", [Inputs directory location]) AC_SUBST(inputdir, "${INPUTDIR}") AC_ARG_WITH(logdir, [ --with-logdir=LOGDIR default internal for log directory ], [ if test x$withval != x ; then LOGDIR=$withval fi ], ) dnl Expand ${prefix} and whatnot in LOGDIR adl_RECURSIVE_EVAL("${LOGDIR}", LOGDIR) AC_DEFINE_UNQUOTED(LOGDIR, "${LOGDIR}", [Logdir location]) AC_SUBST(logdir, "${LOGDIR}") AC_ARG_WITH(piddir, [ --with-piddir=LOGDIR default internal for pid directory ], [ if test x$withval != x ; then PIDDIR=$withval fi ], ) dnl Expand ${prefix} and whatnot in PIDDIR adl_RECURSIVE_EVAL("${PIDDIR}", PIDDIR) AC_DEFINE_UNQUOTED(PIDDIR, "${PIDDIR}", [piddir location]) AC_SUBST(piddir, "${PIDDIR}") AC_ARG_WITH(shell, [AS_HELP_STRING([--with-shell=PATH], [Specify path to POSIX-compatible shell (if not /bin/sh)])], [], [with_shell=/bin/sh]) if test "x$with_shell" = "xno"; then AC_MSG_ERROR([Please specify full path to POSIX-compatible shell]) fi AC_DEFINE_UNQUOTED(SHELL_PATH, "$with_shell", [Path to the POSIX-compatible shell]) dnl ##################################################################### dnl Hostname and Version stuff dnl ##################################################################### AC_PATH_PROG(HOSTNAME, hostname, "", $PATH) AC_DEFINE_UNQUOTED(AUTOCONF_HOSTNAME, "`$HOSTNAME`", [Special CFEngine symbol]) AC_DEFINE_UNQUOTED(AUTOCONF_SYSNAME, "$target_os", [Speial CFEngine symbol]) dnl ##################################################################### dnl xen cpuid-based hvm detection dnl ##################################################################### AC_MSG_CHECKING(for Xen cpuid-based HVM detection) if test x"$GCC" = "xyes"; then case $host_cpu in i[[3456]]86*|x86_64*) AC_DEFINE(XEN_CPUID_SUPPORT, 1, [Define if XEN cpuid-based HVM detection is available.]) AC_MSG_RESULT(yes) ;; *) AC_MSG_RESULT(no) ;; esac else AC_MSG_RESULT(no) fi dnl dnl Code coverage dnl AC_ARG_ENABLE(coverage, AS_HELP_STRING([--enable-coverage], [Enable code coverage]), [use_coverage=$enableval], [use_coverage=no]) if test "x$use_coverage" = "xyes"; then if test "$GCC" != "yes"; then AC_MSG_ERROR([GCC is required for --enable-coverage]) fi if test "$debug" != "yes"; then AC_MSG_ERROR([--enable-debug is required for --enable-coverage]) fi AC_CHECK_PROG(LCOV, lcov, lcov) AC_CHECK_PROG(LCOV_GENHTML, genhtml, genhtml) if test -z "$LCOV"; then AC_MSG_ERROR([Cannot find lcov from the LTP package]) fi if test -z "$LCOV_GENHTML"; then AC_MSG_ERROR([Could not find genhtml from the LTP package]) fi dnl Remove all optimization flags from CFLAGS changequote({,}) CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` changequote([,]) dnl Add the special gcc flags CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage" LDFLAGS="$LDFLAGS -lgcov" fi # # Populate contents of config.post.h # AC_SUBST(post_macros) AM_SUBST_NOTMAKE(post_macros) dnl ###################################################################### dnl Summarize dnl ###################################################################### AC_MSG_RESULT( ) AC_MSG_RESULT( Summary of options...) AC_MSG_RESULT([> Required libraries]) AC_MSG_RESULT([-> OpenSSL: $OPENSSL_PATH]) AC_MSG_RESULT([-> PCRE: $PCRE_PATH]) if test $WITH_TOKYO = 1; then AC_MSG_RESULT([-> DB: Tokyo Cabinet: $TOKYOCABINET_PATH]) elif test $WITH_QDBM = 1; then AC_MSG_RESULT([-> DB: QDBM: $QDBM_PATH]) fi AC_MSG_RESULT([> Optional libraries]) if test "x$ac_cv_lib_mysqlclient_mysql_real_connect" = "xyes"; then AC_MSG_RESULT([-> MySQL connector: $MYSQL_PATH]) else AC_MSG_RESULT([-> MySQL connector: disabled]) fi if test "x$ac_cv_lib_pq_PQconnectdb" = "xyes"; then AC_MSG_RESULT([-> PostgreSQL connector: $POSTGRESQL_PATH]) else AC_MSG_RESULT([-> PostgreSQL connector: disabled]) fi if test $WITH_LMDB = 1; then AC_MSG_RESULT([-> DB: Lightning MDB: $LMDB_PATH]) elif test $WITH_TOKYO = 1; then AC_MSG_RESULT([-> DB: Tokyo Cabinet: $TOKYOCABINET_PATH]) elif test $WITH_QDBM = 1; then AC_MSG_RESULT([-> DB: QDBM: $QDBM_PATH]) fi if test "x$ac_cv_lib_virt_virConnectOpen" = xyes; then AC_MSG_RESULT([-> libvirt: $LIBVIRT_PATH]) else AC_MSG_RESULT([-> libvirt: disabled]) fi if test "x$ac_cv_lib_acl_acl_init" = xyes; then AC_MSG_RESULT([-> libacl: $LIBACL_PATH]) else AC_MSG_RESULT([-> libacl: disabled]) fi if test "x$ac_cv_lib_xml2_xmlFirstElementChild" = xyes; then AC_MSG_RESULT([-> libxml2: $LIBXML2_PATH]) else AC_MSG_RESULT([-> libxml2: disabled]) fi if test "x$users_promises_ok" = "xyes"; then AC_MSG_RESULT([-> User promises: PAM/user* tools]) else AC_MSG_RESULT([-> User promises: disabled]) fi if test "x$enable_builtin_extensions" = "xyes"; then AC_MSG_RESULT([-> Enterprise extensions: Built in]) else AC_MSG_RESULT([-> Enterprise extensions: Plugin or not included]) fi m4_indir(incstart[]incend, [nova/config.m4]) AC_MSG_RESULT([-> Workdir: $WORKDIR]) AC_MSG_RESULT([-> Masterdir: $MASTERDIR]) AC_MSG_RESULT([-> Inputdir: $INPUTDIR]) AC_MSG_RESULT([-> Logdir: $LOGDIR]) AC_MSG_RESULT([-> Piddir: $PIDDIR]) AC_MSG_RESULT( ) dnl ###################################################################### dnl Now make the Makefiles dnl ###################################################################### AC_CONFIG_FILES([Makefile libcompat/Makefile libutils/Makefile libutils/config.post.h libcfnet/Makefile libenv/Makefile libpromises/Makefile cf-agent/Makefile cf-promises/Makefile cf-execd/Makefile cf-key/Makefile cf-monitord/Makefile cf-upgrade/Makefile cf-runagent/Makefile cf-serverd/Makefile ext/Makefile examples/Makefile tests/Makefile tests/acceptance/Makefile tests/unit/Makefile tests/load/Makefile]) AC_OUTPUT AC_MSG_RESULT(DONE: Configuration done. Run make/gmake to build CFEngine Community.) cfengine-3.6.2/depcomp0000755000175100017510000005601612403654567014415 0ustar00a10038a1003800000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: cfengine-3.6.2/autogen.sh0000775000175100017510000000120412411001073015001 0ustar00a10038a1003800000000000000#!/bin/sh try_exec() { type "$1" > /dev/null 2>&1 && exec "$@" } unset foo (: ${foo%%bar}) 2> /dev/null T1="$?" if test "$T1" != 0; then try_exec /usr/xpg4/bin/sh "$0" "$@" echo "No compatible shell script interpreter found." echo "Please find a POSIX shell for your system." exit 42 fi # # Do not set -e before switching to POSIX shell, as it will break the test # above. # set -e srcdir=`dirname $0` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` cd $srcdir autoreconf -Wno-portability --force --install -I m4 || exit 1 cd $ORIGDIR || exit $? if [ -z "$NO_CONFIGURE" ]; then $srcdir/configure --enable-maintainer-mode "$@" fi cfengine-3.6.2/INSTALL0000644000175100017510000000507412316547775014074 0ustar00a10038a1003800000000000000PREREQUISITES ------------- In order to build CFEngine you need the following tools and libraries installed: * C compiler supporting C90 + selected C99 constructs: - _Bool type - anonymous aggregates "(MyType) { .foo = 1, .bar = 2 }" - declarations in "for" loop - named initializers - uintmax_t and corresponding printf/scanf formats The following compilers are known to work: - gcc >= 3.0 - clang >= 2.6 * GNU make * PAM library * OpenSSL library * PCRE library * POSIX threads (pthreads) library, if not provided by the operating system * Latest available LMDB (Lightning Memory-mapped DataBase), Tokyo Cabinet or QDBM * MySQL client library (optional) * PostgreSQL client library (optional) * libacl library (optional) In order to build CFEngine cloned from git, you will need the following additional tools: * GNU Automake >= 1.10.1 * GNU Autoconf >= 2.60 * GNU Libtool >= 1.5.24 * Yacc (note: GNU Bison 2.4.2 has troubles invoking m4) * Lex Latest stable versions of the tools and libraries are generally advised. OPERATING SYSTEMS ----------------- CFEngine is regularly built and tested on the following operating systems: * GNU/Linux (many distributions) * Solaris * Windows with MinGW HARDWARE PLATFORMS ------------------ CFEngine is regularly built and tested on the following CPU architectures: * x86 * x86-64 * SPARC OTHER CONFIGURATIONS -------------------- In case you have successfully compiled CFEngine on a different OS and/or using different tools or versions of tools, please report it to help-cfengine@ mailing list[1]. Please consider running a testsuite (see below), and posting results to mailing list too. [1] https://cfengine.org/mailman/listinfo/help-cfengine BUILD INSTRUCTIONS ------------------ From tarball: $ ./configure [configure options] $ make [-jN] From git checkout: $ ./autogen.sh [configure options] $ make [-jN] See the available configure options: $ ./configure --help or $ ./autogen.sh --help INSTALLATION INSTRUCTIONS ------------------------- CFEngine might be installed in two configurations: * (default) Native CFEngine file layout. Everything is installed in /var/cfengine, layed out as a "secondary FHS root". This layout is designed to keep CFEngine running even if most of the system is broken (e.g. /usr is not mounted due to NFS breakage). * FHS file layout, enabled by --enable-fhs. This layout follows FHS 2.3. After the build process has completed (see BUILD INSTRUCTIONS above), type: $ make install RUNNING TESTSUITE ----------------- Please refer to the instructions in tests/README file. cfengine-3.6.2/ChangeLog0000664000175100017510000017736712411001113014575 0ustar00a10038a10038000000000000003.6.2 Bug fixes: - don't regenerate software_packages.csv every time (Redmine #6441) - improve verbose message for package_list_command - fix missing log output on AIX (Redmine #6434) - assorted fixes to dirname() esp on Windows (Redmine #4716) - fix package manager detection - fix build issues on FreeBSD - allow copying of dead symbolic links (Redmine #6175) - preserve order in readstringarrayidx (Redmine #6466) - fix passing of unexpanded variable references to arrays (Redmine #5893) - use entries for new {admin,deny}_{ips,hostnames} constraints in the relevant legacy lists (Redmine #6542) - cope with ps's numeric fields overflowing to the right - interpret failing function calls in ifvarclass as class not set (Redmine #6327) - remove unexpanded lists when extending lists (Redmine #6541) - infer start-time of a process from elapsed when needed (Redmine #4094) - fix input range definition for laterthan() function (Redmine #6530) - don't add trailing delimiter when join()'ing lists ending with a null-value (Redmine #6552) - 9999999999 (ten 9s) or higher has been historically used as an upper bound in CFEngine code and policy but because of overflow on 32-bit platforms it caused problems with big numbers. Fixed in two ways: first change all existing policy uses to 999999999 (nine 9s instead of eleven 9s), second fix the C code to not wrap-around in case of overflow, but use the LONG_MAX value (Redmine #6531). - cf-serverd and other daemons no longer reload their configuration every minute if CFEngine is built with an inputs directory outside of the work directory (not the default). (Redmine #6551) 3.6.1 New features: - Introduced Solaris and AIX support into the 3.6 series, with many associated build and bug fixes. Changes: - Short-circuit evaluation of classes promises if class is already set (Redmine #5241) - fix to assume all non-specified return codes are failed in commands promises (Redmine #5986) - cf-serverd logs reconfiguration message to NOTICE (was INFO) so that it's always logged in syslog Bug fixes: - File monitoring has been completely rewritten (changes attribute in files promise), which eliminates many bugs, particularly regarding files that are deleted. Upgrading will keep all monitoring data, but downgrading again will reinitialize the DB, so all files will be reported as if they were new. (Redmine #2917) - $(this.promiser) expands in files promises for 'transformer', 'edit_template', 'copy_from.source', 'file_select.exec_program', 'classes' and 'action' bodies (Redmine #1554, #1496, #3530, #1563) - 'body changes' notifies about disappeared files in file monitoring (Redmine #2917) - Set not-kept classes when files or commands promise should be repaired, but is warn-only (Redmine #2359) - Fixed CFEngine template producing a zero-sized file (Redmine #6088) - Add 0-9 A-Z _ to allowed context of module protocol (Redmine #6063) - Extend ps command column width on Solaris and filter on zone rather than adding it to the ps output. - Fixed strftime() function on Solaris when called with certain specifiers. - Fixed users promise bug regarding password hashes in a NIS/NSS setup. - Fixed $(sys.uptime), $(sys.systime) and $(sys.sysday) in AIX. (Redmine #5148, #5206) - Fixed processes_select complaining about "Unacceptable model uncertainty examining processes" (Redmine #6337) - ps command for linux has been changed to cope with big rss values (Redmine #6337) - Address ps -axo shift on FreeBSD 10 and later (Redmine #5667) - methods and services promises respect action_policy => "warn" (Redmine #5924) - LMDB should no longer deadlock if an agent is killed on the hub while holding the DB lock. Note that the change only affects binary packages shipped by CFEngine, since the upstream LMDB project has not yet integrated the change. (Redmine #6013) 3.6.0 Changes: - Changes to logging output - add process name and pid in syslog message (GitHub #789) - cf-serverd logging levels are now more standardised: - INFO logs only failures - VERBOSE logs successful requests as well - DEBUG logs actual protocol traffic. - cf-serverd now logs the relevant client IP address on each message. - Logging contexts to local database (cf_classes.tcdb) has been deprecated. - 'usebundle' promisees are logged for all the bundle promises - output from 'reports' promises has nothing prefixed except 'R: ' - a log line with stack path is generated when the promise type evaluated changes - LMDB (symas.com/mdb) is the default database for local data storage : use version 0.9.9 or later cf-agent --self-diagnostics (-x) is only implemented for TCDB, not for LMDB - port argument in readtcp() and selectservers() may be a service name (e.g. "http", "pop3"). - Enable source file in agent copy_from promises to be a relative path. - file "changes" reporting now reports with log level "notice", instead of "error". - process_results default to AND'ing of set attributes if not specified (Redmine #3224) - interface is now canonified in sys.hardware_mac[interface] to align with sys.ipv4[interface] (Redmine #3418) - cf-promises no longer errors on missing bodies when run without --full-check (-c) - Linux flavor "SUSE" now correctly spelled with all uppercase in variables and class names (Redmine #3734). The "suse" lowercase version is also provided for convenience (Redmine #5417). - $(this.promise_filename) and $(..._dirname) variables are now absolute paths. (Redmine #3839) - including the same file multiple times in 'body control inputs' is not an error - portnumber in body copy_from now supports service names like "cfengine", "pop3" etc, check /etc/services for more. - The failsafe.cf policy, run on bootstrap and in some other unusual cases, has been extracted from C code into libpromises/failsafe.cf - masterfiles - cf_promises_validated is now in JSON format - timestamp key is timestamp (sec since unix epoch) of last time validated - the masterfiles now come from https://github.com/cfengine/masterfiles and are not in the core repository - cf-serverd calls cf-agent with -Dcfruncommand when executing cf-runagent requests - Mark as removed: promise_notkept_log_include, promise_notkept_log_exclude, promise_repaired_log_include, promise_repaired_log_exclude, classes_include, classes_exclude, variables_include, variables_exclude attributes from report_data_select body (syntax is valid but not functional). They have been replaced by the following attributes: promise_handle_include, promise_handle_exclude, metatags_include, metatags_exclude. New features: - New promise type "users" for managing local user accounts. - TLS authentication and fully encrypted network protocol. Additions specific to the new type of connections: - New attribute "allowlegacyconnects" in body server control, which enables serving policy via non-latest cfengine protocol, to the given list of hosts. If the option is absent, it defaults to allow all hosts. To refuse non-TLS connections, specify an empty list. - New attribute "protocol_version" in body copy_from, and body common control, which defines the preferred protocol for outgoing connections.. Allowed values at the moment: "0" or "undefined", "classic" or "1", "latest" or "2". By leaving the copy_from option as undefined the common control option is used, and if both are undefined then classic protocol is used by default. - The new networking protocol uses TLS for authentication, after which all dialog is encrypted within the established TLS session. cf-serverd is still able to speak the legacy protocol with old agents. - The 'skipverify' option in 'body server control' is deprecated and only left for compatibility; it does nothing - cf-serverd does not hang up the connection if some request fails, so that the client can add more requests. - For the connections using the new protocol, all of the paths in bundle server access_rules now differentiate between a directory and a file using the trailing slash. If the path exists then this is auto-detected and trailing slash appended automatically. You have to append a trailing slash manually to an inexistent or symbolic path (e.g. "/path/to/$(connection.ip)/") to force recursive access. - New in 'access' promises for 'bundle server access_rules' - Attributes "admit_ips", "admit_hostnames", "admit_keys", "deny_ips", "deny_hostnames", "deny_keys" - "admit_keys" and "deny_keys" add the new functionality of controlling access according to host identity, regardless of the connecting IP. - For these new attributes, regular expressions are not allowed, only CIDR notation for "admit/deny_ips", exact "SHA=..." strings for "admit/deny_keys", and exact hostnames (e.g. "cfengine.com") or subdomains (starting with dot, e.g. ".cfengine.com") for "admit/deny"_hostnames. Same rules apply to 'deny_*' attributes. - These new constaints and the paths in access_rules, can contain special variables "$(connection.ip)", "$(connection.hostname)", "$(connection.key)", which are expanded dynamically for every received connection. - For connections using the new protocol, "admit" and "deny" constraints in bundle server access_rules are being phased out, preferred attributes are now "admit_ips", "deny_ips", "admit_hostnames", "deny_hostnames", "admit_keys", "deny_keys". - New "shortcut" attribute in bundle server access_rules used to dynamically expand non-absolute request paths. - masterfiles - standard library split: lib/3.5 (compatibility) and lib/3.6 (mainline) - many standard library bundles and bodies, especially packages- and file-related, were revised and fixed - supports both Community and Enterprise - new 'inventory/' structure to provide OS, dmidecode, LSB, etc. system inventory (configured mainly in def.cf) - cf_promises_release_id contains the policy release ID which is the GIT HEAD SHA if available or hash of tree - a bunch'o'bundles to make starting with CFEngine easier: - file-related: file_mustache, file_mustache_jsonstring, file_tidy, dir_sync, file_copy, file_link, file_hardlink, file_empty, file_make - packages-related: package_absent, package_present, package_latest, package_specific_present, package_specific_absent, package_specific_latest, package_specific - XML-related: xml_insert_tree_nopath, xml_insert_tree, xml_set_value, xml_set_attribute - VCS-related: git_init, git_add, git_checkout, git_checkout_new_branch, git_clean, git_stash, git_stash_and_clean, git_commit, git - process-related: process_kill - other: cmerge, url_ping, logrotate, prunedir - New command line options for agent binaries - New options to cf-promises - '--show-classes' and '--show-vars' - '--eval-functions' controls whether cf-promises should evaluate functions - Colorized output for agent binaries with command line option '--color' (auto-enabled if you set CFENGINE_COLOR=1) - New language features - New variable type 'data' for handling of structured data (ie JSON), including supporting functions: - 'data_readstringarray' - read a delimited file into a data map - 'data_readstringarrayidx' - read a delimited file into a data array - 'datastate' - create a data variable with currently set classes and variables - 'datatype' - determine the type of the top element of a container - 'format' - %S can be used to serialize 'data' containers into a string - 'mergedata' - merge two data containers, slists/ilists/rlists, or "classic" arrays into a data container - 'parsejson' - create a data container from a JSON string - 'readjson' - create a data container from a file that contains JSON - 'storejson' - serialize a data container into a string - Most functions operating on lists can also operate on data containers - pass a data container to a bundle with the @(container) notation - the module protocol accepts JSON for data containers with the '%' sigil - Tagging of classes and variables allows annotating of language construct with meta data; supporting functionality: - The module protocol in 'commands' promises has been extended to allow setting of tags of created variables and classes, and the context of created variables - 'getclassmetatags' - returns list of meta tags for a class - 'getvariablemetatags' - returns list of meta tags for a variable - 'body file control' has an 'inputs' attribute to include library files and other dependencies - bundlesequences can be built with bundlesmatching() based on bundle name and tags - New attributes in existing promise types and bodies - New option 'preserve_all_lines' for insert_type in insert_lines promises - Caching of expensive system functions to avoid multiple executions of execresult() etc, can be controlled via cache_system_functions attribute in body common control - New option 'mailsubject' in body executor control allows defining the subject in emails sent by CFEngine - Support for Mustache templates in 'files' promises; use 'template_method' and 'template_data' attributes. Without 'template_data' specified, uses datastate(). - New and improved functions - 'bundlesmatching' - returns list of defined bundles matching a regex and tags - 'canonifyuniquely' - converts a string into a unique, legal class name - 'classesmatching' - returns list of set classes matching a regex and tags - 'eval' - evaluates mathematical expressions; knows SI k, m, g quantifiers, e.g. "100k" - 'findfiles' - list files matching a search pattern; use "**" for recursive searches - 'makerule' - evaluates whether a target file needs to be rebuilt from sources - 'max', 'min' - returns maximum and minimum of the numbers in a container or list (sorted by a 'sort' method) - 'mean' - returns the mean of the numbers in a container or list - 'nth' - learned to look up by key in a data container holding a map - 'packagesmatching' - returns a filtered list of installed packages. - 'readfile' - learned to read system files of unknown size like those in /proc - 'sort' - can sort lexicographically, numerically (int or real), by IP, or by MAC - 'string_downcase', 'string_upcase' - returns the lower-/upper-case version of a string - 'string_head', 'string_tail' - returns the beginning/end of a string - 'string_length' - returns the length of a string - 'string_reverse' - reverses a string - 'string_split' - improved implementation, deprecates 'splitstring' - 'variablesmatching' - returns a list of variables matching a regex and tags - 'variance' - returns the variance of numbers in a list or container - New hard classes - Introduced alias 'policy_server' for context 'am_policy_hub' (the latter will be deprecated) - all the time-based classes have GMT equivalents - New variables - 'sys.bindir' - the location of the CFEngine binaries - 'sys.failsafe_policy_path' - the location of the failsafe policy file - 'sys.inputdir' - the directory where CFEngine searches for policy files - 'sys.key_digest' - the digest of the host's cryptographic key - 'sys.libdir', 'sys.local_libdir' - the location of the CFEngine libraries - 'sys.logdir' - the directory where the CFEngine log files are saved - 'sys.masterdir' - the location of masterfiles on the policy server - 'sys.piddir' - the directory where the daemon pid files are saved - 'sys.sysday' - the number of days since the beginning of the UNIX epoch - 'sys.systime' - the number of seconds since the beginning of the UNIX epoch - 'sys.update_policy_path' - the name of the update policy file - 'sys.uptime' - the number of minutes the host has been online - 'this.promise_dirname' - the name of the file in which the current promise is defined - 'this.promiser_uid' - the ID of the user running cf-agent - 'this.promiser_gid' - the group ID of the user running cf-agent - 'this.promiser_ppid' - the ID of the parent process running cf-agent Deprecations: - 'splitstring' - deprecated by 'string_split' - 'track_value' - 'skipverify' Bug fixes: for a complete list of fixed bugs, see Redmine at https://cfengine.com/dev - various fixes in evaluation and variable resolution - Improve performance of list iteration (Redmine #1875) - Removed limitation of input length to internal buffer sizes - directories ending with "/" are not ignored - lsdir() always return a list now, never a scalar - 'abortclasses' fixed to work in common bundles and other cases - namespaced 'edit_line' bundles now work (Redmine#3781) - lists are interpolated in correct order (Redmine#3122) - cf-serverd reloads policies properly when they change - lots of leaks (memory and file descriptor) fixed 3.5.3 Changes: - Improved security checks of symlink ownership. A symlink created by a user pointing to resources owned by a different user will no longer be followed. - Changed the way package versions are compared in package promises. (Redmine #3314) In previous versions the comparison was inconsistent. This has been fixed, but may also lead to behavior changes in certain cases. In CFEngine 3.5.3, the comparison works as follows: For instance: apache-2.2.31 ">=" "2.2.0" will result in the package being installed. Bug fixes: - fix cf-monitord crash due to incorrect array initialization (Redmine #3180) - fix cf-serverd stat()'ing the file tree every second (Redmine #3479) - correctly populate sys.hardware_addresses variable (Redmine #2936) - add support for Debian's GNU/kfreebsd to build system (Redmine #3500) - fix possible stack corruption in guest_environments promises (Redmine #3552) - work-around hostname trunctation in HP-UX's uname (Redmine #3517) - fix body copy purging of empty directories (Redmine #3429) - make discovery and loading of avahi libraries more robust - compile and packaging fixes for HP-UX, AIX and Solaris - fix fatal error in lsdir() when directory doesn't exist (Redmine #3273) - fix epoch calculation for stime inrange calculation (Redmine #2921) 3.5.2 Bug fixes: - fix delayed abortclasses checking (Redmine #2316, #3114, #3003) - fix maplist arguments bug (Redmine #3256) - fix segfaults in cf-pomises (Redmine #3173, 3194) - fix build on Solaris 10/SmartOS (Redmine #3097) - sanitize characters from /etc/issue in sys.flavor for Debian (Redmine #2988) - Fix segfault when dealing with files or data > 4K (Redmine #2912, 2698) - Don't truncate keys to 126 characters in getindices (Redmine #2626) - files created via log_* actions now have mode 600 (Redmine #1578) - fix wrong log message when a promise is ignored due to 'ifvarclass' not matching - fix lifetime of persistent classes (Redmine #3259) - fix segfault when process_select body had no process_result attribute Default to AND'ed expression of all specified attributes (Redmine #3224) - include system message in output when acl promises fail - fix invocation of standard_services bundle and corresponding promise compliance (Redmine #2869) 3.5.1 Changes: - file changes are logged with log level Notice, not Error - the CFEngine Standard Library in masterfiles/libraries is now split into promise-type specific policy files, and lives in a version-specific directory. This should have no impact on current code, but allows more granular include of needed stdlib elements (Redmine #3044) Bug fixes: - fix recursive copying of files (Redmine #2965) - respect classes in templates (Redmine ##2928) - fix timestamps on Windows (Redmine #2933) - fix non-root cf-agent flooding syslog (Redmine #2980) - fix email flood from cf-execd due to timestamps in agent output (Redmine #3011) - Preserve security context when editing or copying local files (Redmine #2728) - fix path for sys.crontab on redhat systems (Redmine #2553) - prevent incorrect "insert_lines promise uses the same select_line_matching anchor" warning (Redmine #2778) - Fix regression of setting VIPADDRESS to 127.0.0.1 (Redmine #3010) - Fix "changes" promise not receiving status when file is missing (Redmine #2820) - Fix symlinks being destroyed when editing them (Redmine #2363) - Fix missing "promise kept" status for the last line in a file (Redmine #2943) 3.5.0 New features: - classes promises now take an optional scope constraint. - new built-in functions: every, none, some, nth, sublist, uniq, filter - every - none - some - nth - sublist - uniq - filter - classesmatching - strftime - filestat - ifelse - maparray - format - cf-promises flag --parse-tree is replaced by --policy-output-format=, requiring the user to specify the output format (none, cf, json) - cf-promises allows partial check of policy (without body common control) without integrity check; --full-check enforces integrity check - agent binaries support JSON input format (.json file as generated by cf-promises) - cf-key: new options --trust-key/-t and --print-digest/-p - Class "failsafe_fallback" is defined in failsafe.cf when main policy contains errors and failsafe is run because of this - add scope attribute for body classes (Redmine #2013) - Better diagnostics of parsing errors - Error messages from parser now show the context of error - new cf-agent option: --self-diagnostics - new output format, and --legacy-output - warnings for cf-promises. - Enable zeroconf-discovery of policy hubs for automatic bootstrapping if Avahi is present - Support for sys.cpus on more platforms than Linux & HPUX Changes: - parser no longer allows ',' after promiser or promisee. must be either ';' or lval - Make parser output in GCC compatible format the only supported format (remove --gcc-brief-format flag) - Silence license warnings in Enterprise Free25 installations - action_policy => "warn" causes not_kept classes to be set on promise needing repair. - command line option version (-V) now prints a shorter parsable version without graphic - implicit execution of server and common bundles taking arguments is skipped in cf-serverd. - WARNING: option --policy-server removed, require option to --bootstrap instead - process promises don't log if processes are out of range unless you run in verbose mode - reports promises are now allowed in any context (Redmine #2005) - cf-report has been removed - cf-execd: --once implies --no-fork - Version info removed from mail subject in the emails sent by cf-execd. The subject will only contain "[fqname/ipaddress]" instead of "communnity/nova [fqname/ipaddress]" Please change your email filters accordingly if necessary. - "outputs" promise type is retired. Their semantics was not clear, and the functionality is better suited for control body setting, not a promise. - Tokyo Cabinet databases are now automatically checked for correctness during opening. It should prevent a number of issues with corrupted TC databases causing binaries to hang. - Improved ACL handling on Windows, which led to some syntax changes. We now consistently use the term "default" to describe ACLs that can be inherited by child objects. These keywords have received new names: acl_directory_inherit -> acl_default specify_inherit_aces -> specify_default_aces The old keywords are deprecated, but still valid. In addition, a new keyword "acl_inherit" controls inheritance behavior on Windows. This feature does not exist on Unix platforms. (Redmine #1832) - Networking code is moved from libpromises to its own library, libcfnet. Work has begun on making the API more sane and thread-safe. Lots of legacy code was removed. - Add getaddrinfo() replacement in libcompat (borrowed from PostgreSQL). - Replace old deprecated and non thread-safe resolver calls with getaddrinfo() and getnameinfo(). - Hostname2IPString(), IPString2Hostname() are now thread-safe, and are returning error when resolution fails. - Running cf-execd --once now implies --no-fork, and also does not wait for splaytime to pass. - execresult(), returnszero() and commands promises no longer requires the first word word to be an absolute path when using the shell. (Part of Redmine #2143) - commands promises useshell attribute now accepts "noshell" and "useshell" values. Boolean values are accepted but deprecated. (Part of Redmine #2143) - returnszero() now correctly sets the class name in this scenario (Part of Redmine #2143): classes: "commandfailed" not => returnszero("/bin/nosuchcommand", "noshell"); Bugfixes: - bundles are allowed to be empty (Redmine #2411) - Fixed '.' and '-' not being accepted by a commands module. (Redmine #2384) - Correct parsing of list variables by a command module. (Redmine #2239) - Fixed issue with package management and warn. (Redmine #1831) - Fixed JSON crash. (Redmine #2151) - Improved error checking when using fgets(). (Redmine #2451) - Fixed error message when deleting nonexistent files. (Redmine #2448) - Honor warn-only when purging from local directory. (Redmine #2162) - Make sure "restart" and "reload" are recognized keywords in packages. (Redmine #2468) - Allocate memory dynamically to avoid out-of-buffer or out-of-hash situations - fix edit_xml update of existing attributes (Redmine #2034) - use failsafe policy from compile-time specified workdir (Redmine #1991) - ifvarclass checked from classes promises in common bundles - do not wait for splaytime when executing only once - disable xml editing functionality when libxml2 doesn't provide necessary APIs (Redmine #1937) - Out-of-tree builds should work again, fixed a bunch of related bugs. - Fixed race condition in file editing. (Redmine #2545) - Fixed memory leak in cf-serverd and others (Redmine #1758) 3.4.5 (Bugfix and Stability release) Bugfixes: - make qualified arrays expand correcty (Redmine #1998, Mantis #1128) - correct possible errors in tcdb files when opening - avoid possible db corruption when mixing read/write and cursor operations - Allow umask value of 002 (Redmine #2496) 3.4.4 (Bugfix and Stability release) Bugfixes: - prevent possible crash when archiving files (GitHub #316) - don't create symlinks to cf-know in update policy - don't enable xml support if libxml2 is too old (Redmine #1937) 3.4.3 (Bugfix and Stability release) Bugfixes: - Don't flood error messages when processes are out of defined range - prevent segmentation fault in cf-monitord -x (Redmine #2021) - when copying files, use same file mode as source file, rather than 0600 (Redmine #1804) - include xpath in messages generated by edit_xml operations (Redmine #2057) 3.4.2 (Bugfix and Stability release) Bugfixes: - Fixes to policies in masterfiles (see masterfiles/Changelog for details) - Fixes for OpenBSD (GitHub #278) - Do not canonify values specified in abortbundleclasses/abortclasses (Redmine #1786) - Fix build issues on NetBSD, SLES 12.2 - Improve error message when libxml2 support is not compiled (Redmine #1799) - fix potential segmentation fault when trimming network socket data (GitHub #233) - fix potential segmentation fault when address-lookups in lastseen db failed (GitHub #233) - execute background promise serially when max_children was reached, rather than skipping them (GitHub #233) - fix segmentation fault in cf-promises when invoked with --reports (Redmine #1931) - fix compilation with Sun Studio 12 (Redmine #1901) - silence type-pun warning when building on HP-UX (GitHub #287) 3.4.1 (Bugfix and Stability release) New feature/behavior: - cf-execd terminates agent processes that are not responsive for a configurable amount of time (see agent_expireafter in body executor control), defaulting to 1 week Bugfixes: - fix regression of classmatch() failing with hard classes (Redmine #1834) - create promise-defined and persistent classes in correct namespace (Redmine #1836) - several fixes to namespace support - fix several crash bugs caused by buffer overflow and race conditions in cf-serverd - regenerate time classes in cf-execd for each run (Redmine #1838) - edit_xml: fix select_xpath implementation and update documentation NOTE: code that uses select_xpath_region needs to be changed to select_xpath - edit_xml: make sure that text-modification functions don't overwrite child nodes - edit_xml: improve error logging 3.4.0 New features: - Added rpmvercmp utility to compare versions of RPM packages for accurate sorting of RPM packages for packages promises. - Implement network timeout on server side to avoid keeping stale connections for hours. - XML editing capabilities. See the documentation for edit_xml body. Note the new dependency: libxml2. - Implement inheritance of local classes by bundles called using "usebundle". By default classes are not inherited. See the examples/unit_inherit.cf for an example. - Moved from Nova/Enterprise: - POSIX ACL support, - "outputs" promise type, - remote syslog support. - packages_default_arch_command hook in packages promises, to specify default architecture of the packages on the system. - packages_version_less_command / packages_version_equal_command hooks in packages promises, to specify external command for native package manager versions comparison - agent_expireafter in body executor control allows you to set a timeout on all cf-agent runs, to enforce a threshold on the number of concurrent agents - Running in Solaris zone is now detected and classes "zone" and "zone_" are created in this case. - VirtualBox support added to guest_environment promises. - guest_environment promises are supported under OS X. - The "depends_on" attribute is now active, for the partal ordering of promises. If a promise depends on another (referred by handle) it will only be considered if the depends_on list is either kept or repaired already. ** WARNING: When upgrading, make sure that any existing use of depends_on does not make some promises being unintentionally ignored. This can happen if you are currently refering to non-existant or never-run handles in depends_on attributes. - methods return values, initial implementation - New format for cf-key -s, includes timestamp of last connection - cf-promises --parse-tree option to parse policy file and dump it in JSON format - Namespaces support for bundles and bodies. See the examples/unit_namespace*.cf for the usage. - Default arguments for bundles. See the examples/unit_defaults.cf - Metadata promise type. See the examples/unit_meta.cf New semantics: - Methods promises now return the status of promises kept within them. If any promise was not kept, the method is not kept, else if any promise is repaired, the method was repaired else it was kept. - Remote variable access in namespaces by $(namespace:bundle.variable) Changed functionality: - cf-execd -F switch no longer implies 'run once'. New -O/--once option is added to achieve this behaviour. This makes cf-execd easier to run from systemd, launchd and other supervision systems. Misc: - Support for the following outdated platforms and corresponding classes has been removed. De facto those platforms were unsupported for a long time, as CFEngine codebase uses C99 language features unavailable on old platforms: - SunOS 3.x (sun3) - SunOS 4.x (sun4) - Ultrix (ultrix) - DEC OSF/1 AXP (osf) - Digital UNIX (digital) - Sony NEWS (newsos) - 4.3BSD (bsd4_3) - IRIX (irix, irix4, irix64) - IBM Academic Operating System (aos) - BSD/OS / BSDi / BSD/386 (bsdos) - NeXTSTEP (nextstep) - GNU Hurd (gnu) - NEC UX/4800 (ux4800) - (Old news) Since 3.3.0 the layout of CFEngine Community packages has changed slightly. cf-* binaries have been moved to /var/cfengine/bin, due to the following reasons: - cf-* binaries are linked to libraries installed to /var/cfengine/lib, so placing binaries in /usr/local/sbin does not increase reliability of the CFEngine, - keeping whole CFEngine under single prefix (/var/cfengine) makes packaging simpler, - it matches the layout of CFEngine Enterprise packages. Please adjust your policies (the recommended ways to deal with the move are either to adjust $PATH to include /var/cfengine or to create symlinks in /usr/local/sbin in case you are relying on binaries to be available in $PATH). - Workdir location is properly changed if --prefix or --enable-fhs options are supplied to configure (Mantis #1195). - Added check for broken libmysqlclient implementations (Mantis #1217). - Standard library is updated from COPBL repository. - cf-know is no longer built in Community releases. The only functionality useful in Community, namely the reference manual generation, is provided by new compile-time cf-gendoc tool. - Filename (for storing filechanges) changed from file_change.log -> file_changes.log (in /var/cfengine/state) New format for storing file changes introduced: [timestamp,filename,,Message] N = New file found C = Content Changed S = Stats changed R = File removed - Acceptance test suite passes on Mac OS X. - Changed some port numbers to replace old services with imap(s) - archlinux hard class on Arch Linux. - Detect BSD Make and automatically switch to GNU Make during build. Bugfixes: - cfruncommand for cf-execd is an arbitrary shell command now (Mantis #1268). - Fixed broken "daily" splayclasses (Mantis #1307). - Allow filenames up to 4096 bytes in network transfers (Redmine #1199). - Fix stale state preserved during cf-serverd reload (Redmine #1487). - Free disk space calculation is fixed (Mantis #1120). - Numerous portability bugfixes (especially OpenBSD, Solaris, AIX-related). - Compatibility fixes for AIX, HP-UX, Solaris (Mantis #1185, Mantis #1177, Mantis #1109). - Fixed broken socklen_t configure check under OpenBSD (Mantis #1168). - Fixed hang in cf-promises under OpenBSD (Mantis #1113). - Fixed endless loop in evaluating "$()" construct (Mantis #1023). - Fixed check for old PCRE versions (Mantis #1262). - Fixed insertion of multi-line blocks at the start of file (Mantis #809). - Fixed numerous memory leaks. - Fixes for metadata that were not resolvable - Fixes for namespaces that would not support metadata and variable expansion - Point-to-point network interfaces are detected and reported by CFEngine (Mantis #1246) - Partial non-GNU userspace support in acceptance testsuite (Mantis #1255) Full list of issues fixed is available on https://cfengine.com/bugtracker/changelog_page.php (old bug tracker) and https://cfengine.com/dev/projects/core/versions/34 (new bug tracker) 3.3.9 (Bugfix and Stability release) Bugfixes: - Do not lose hard classes in cf-serverd during policy reload (Mantis #1218). - Implement recieve network timeout in cf-serverd. Prevents overloading cf-serverd with stale connections. 3.3.8 (Bugfix and Stability release) Versions 3.3.6, 3.3.7 were internal and weren't released. Bugfixes: - Propery set sys.domain variable if hostname is fully-qualified. - Fixed several small memory leaks. - Make network timeout for network reads configurable. Previously it was hardcoded to be 30 seconds, which was not enough for cf-runagent invoking cf-agent on big policies (Mantis #1028). 3.3.5 (Bugfix and Stability release) Bugfixes: - Fixed cf-execd memory leak on hosts with cf-monitord running. - Robustify against wrongly-sized entires in embedded databases. Standard library: - Bugfixes from upstream COPBL repository. - standard_services bundle from upstream COPBL repository. 3.3.4 (Bugfix and Stability release) Evaluation of policies: - Fix wrong classes set after installation of several packages using packages promises (Mantis #829). - Fix segfault using edit_template on existing file (Mantis #1155). Misc: - Fix memory leak during re-read of network interfaces' information in cf-execd/cf-serverd. 3.3.3 (Bugfix and Stability release) Evaluation of policies: - Zero-length files are valid for readfile() and similar functions (Mantis #1136). - Unchoke agent in case it encounters symlinks in form ./foo (Similar to Mantis #1117). Misc: - Fix generation of reference manual on machines with umask more relaxed than 022. - Use statvfs(3) on OpenBSD to obtain filesystem information (Mantis #1135). 3.3.2 (Bugfix and Stability release) Evaluation of policies: - Do not segfault if file copy was interrupted due to network connectivity or server going away (Mantis #1089). - Do not segfault if log_failed attribute is present in body, but log_kept is not (Mantis #1107). - Do not mangle relative paths in symlinks during file copy Previously symlink a -> b was mangled to a -> ./b. (Mantis #1117) - Properly compare 1.0 and 1.0.1 in packages promises. Previously only versions with equal amount of "segments" were comparable (Mantis #890, #1066). Base policy: - Properly set permissions on files for /var/cfengine/lib on HP-UX (Mantis #1114). - Standard library (cfengine_stdlib.cf) is synced with COPBL repository. Misc: - Do not create huge file in case corrupted TokyoCabinet database is detected (Mantis #1106). - Fix file descriptor leak on error paths, may have caused crashes of cf-execd and cf-serverd (Issue #1096). - Fix intermittent segfault in cf-execd (Mantis #1116). - Impose an upper limit on amount of listening sockets reported by cf-monitord. Huge amounts of listening sockets caused cf-agent to segfault on next run (Mantis #1098). - Add missing function prototypes caused errors during compilation on HP-UX (Mantis #1109). - Fix compilation on Solaris 11 (Mantis #1091). 3.3.1 (Bugfix and Stability release) Evaluation of policies: - Do not cut off name of bundle in variables interpolation (Mantis #975). - Do not segfault in function evaluation guarded by ifvaclass clause (Mantis #1084, #864). - Do not segfault if "classes" promise does not declare any value to be evaluated (Mantis #1074). - Do not segfault in database promises if there is no database_operation provided (Mantis #1046). Built-in functions: - Fix countclassesmatching() function which was misbehaving trying to match classes starting with alphanumeric symbol (Mantis #1073). - Fix diskfree() to return kilobytes, as described in documentation (Mantis #980, #955). - Fix hostsseen() function to avoid treating all hosts as not being seen since 1970 (Mantis #886). - Do not output misleading error message if readtcp() is unable to connect (Mantis #1085). Command-line interface: - -d option previously reqired an argument, though help message disagreed (Mantis #1053). - Disable --parse-tree option, not ready for the release (Mantis #1063). - Acept -h as a --help option. - Ensure that cf-execd might be started right after being shut down. Misc: - Plug file descriptor leak after failed file copy (Mantis #990). - Fix unsafe admit rules in default promises.cf (Mantis #1040). - Fix splaytime to match documentation: it is specified in minutes, not seconds (Mantis #1099). Packaging: - Fix owner/group of initscript and profile.d snippet in RPM builds (Mantis #1061, #1058). - Fix location of libvirt socket CFEngine uses to connect to libvirtd (Mantis #1072). - Install CoreBase to /var/cfengine/masterfiles during installation (Mantis #1075). - Do not leave old cf-twin around after upgrade (Mantis #1068) - Do not leave rcS.d symlinks after purging .deb package (Mantis #1092). 3.3.0 New promise types: - Guest environments promises, which allow to manipulate virtual machines using libvirt. - Database promises, which allow to maintain schema of MySQL and PostgreSQL databases. Database promises are in "technical preview" status: this promise type is subject to change in future. - Services promises for Unix, allows abstraction of details on managing any service New built-in functions: - dirname() to complement lastnode() - lsdir() - maplist() to apply functions over lists New features: - Allow defining arrays from modules. - Allow both `process_stop' and `signals' constraints in `processes' promises at the same time. - cf-promises --gcc-brief-format option to output warnings and errors in gcc-compatible syntax which to ease use "go to next error" feature of text editors. - Iteration over lists is now allowed for qualified (non-local) lists. New built-in variables and classes (Linux): - Number of CPUs: $(sys.cpus), 1_cpu, 2_cpus etc New built-in variables and classes (Unices): - $(sys.last_policy_update) - timestamp when last policy change was seen by host - $(sys.hardware_addresses) - list of MAC adresses - $(sys.ip_addresses) - list of IP addresses - $(sys.interfaces) - list of network interfaces - $(sys.hardware_mac[$iface]) - MAC address for network interface - mac_:: - discovered MAC addresses Changes: - Major cleanup of database handling code. Should radically decrease amount of database issues experienced under heavy load. *WARNING*: Berkeley DB and SQLite backends are *removed*, use Tokyo Cabinet or QDBM instead. Both Tokyo Cabinet and QDBM are faster than Berkeley DB in typical CFEngine workloads. Tokyo Cabinet requires C99 environment, so it should be available on every contemporary operating system. For the older systems QDBM, which relies only on C89, is a better replacement, and deemed to be as portable, as Berkeley DB. - Change of lastseen database schema. Should radically decrease I/O contention on lasteen database. - Automatic reload of policies by cf-execd. - Documentation is generated during build, PDF and HTML files are retired from repository. - Rarely used feature retired: peer connectivity intermittency calculation. - Memory and CPU usage improvements. - Testsuite now uses 'make check' convention and does not need root privileges anymore. - cf_promises_validated now filled with timestamp, allows digest-copy for policy instead of mtime copy which is safer when clocks are unsynchronised - The bundled failsafe.cf policy now has trustkey=false to avoid IP spoofing attacks in default policy - See the full list of bugfixes at https://cfengine.com/bugtracker/changelog_page.php 3.2.4 (Bugfix and Stability release) Fixed failure in network transfer in case of misbehaving peer A few tiny memory leaks on error paths fixed 3.2.3 (Bugfix and Stability release) A few tiny memory leaks fixed Improved performance of cf-serverd under heavy load with TokyoCabinet database Full list of issues fixed is available on https://cfengine.com/bugtracker/changelog_page.php 3.2.2 (Bugfix and Stability release) Enabled compilation in "large files" mode under AIX Alleviated problem with broken file transfers over unstable Internet links. Full list of issues fixed is available on https://cfengine.com/bugtracker/changelog_page.php 3.2.1 (Bugfix and Stability release) Fixed compilation under HP-UX and Solaris Enabled compilation using HP ANSI C compiler Full list of issues fixed is available on https://cfengine.com/bugtracker/changelog_page.php 3.2.0 New bootstrap method with single-command bootstrapping: - cf-agent --bootstrap --policy-server 123.456.789.123 - Associated policy template files are added, partially maintained by CFEngine Bug fixes for file-editing, package versioning, and embedded database corruption (We recommend using TokyoCabinet instead of BerkeleyDB if building from source). Improved upgrade path for Nova. Patches for improved run-agent concurrency Reorganization of documentation and community resources 100% on regression test suite on 3 operating systems (Ubuntu, Debian, SuSE on x86-64 hardware) Support for multiple release environments package_policy update and addupdate now check if user-supplied version is larger than currently installed - updates only if so Help text of cf-report -r corrected - a list of key hashes is required, not ip addresses. New Emacs mode for CFEngine policy files (thanks to Ted Zlatanov!) Warnings are on edit_line changes can now give greater degree of information without spamming promise logs Class expressions parser accepts '||' as an alias for '|' again. Invalidation of package list cache on installation/removal of packages. New option cf-key -r to remove host key by IP or hostname. Added detection of network interfaces which belong to BSD jails. Improve robustness of multi-threaded code, in particular fix problems with spurious acces denials in server and losing of authentication rules after policy reload. cf-promises accepts option -b matching cf-agent, which causes it to do not complain about missing bundlesequence. New functions and(), not(), or() and concat() to ease use of ifvarclass() clause. Full list of issues fixed is available on https://cfengine.com/bugtracker/changelog_page.php 3.1.5 New class parser, '||' is no longer allowed in expressions (use '|'). Class setting in the promise types insert_lines, delete_lines, replace_patterns, field_edits, vars, classes is restored. suspiciousnames implemented. New function getvalues(). New functions parse{read,int,string}array to match read{read,int,string}array. Testsuite added to check for core functionality. Syslog prefix is fixed to say 'cf3' instead of 'community'. 3.1.4 (Bugfix and Stability release) Some urgent patches to 3.1.3. Class validation parse bug fixed. Global zone handling error for solaris fixed. Package architectures handled correctly (bug #456). Reading and writing of key name "root-.pub" eliminated (bug #442, #453). cf-serverd crash because of race condition on SERVER_KEYSEEN fixed. Lock purging to avoid remnant complexity explosion (bug #430). Some copyright notices added that got lost. 3.1.3 (Stability release) Major memory leaks in cf-monitord, cf-execd, cf-serverd fixed (bug #427). The daemons now show no growth even with very complex policies. cf-serverd crash due to race condition in DeleteScope() fixed (bug #406). Added 30 second timeout on recv() on Linux. package_noverify_returncode implemented (bug #256). A flexible mechanism for setting classes based on return codes of commands has been introduced. Allows for setting promise kept, repaired or failed based on any return codes. This is currently implemented for commands-promises, package-manager commands and transformer in files. In classes body, see attributes kept_returncodes, repaired_returncodes, failed_returncodes (bug #248, #329). New function ip2host - reverse DNS lookup (bug #146). 3.1.2 (Scalability/efficiency release) Big efficiency improvements by caching output from cf-promises. Can also be used for much more efficent policy deployment (only pull if changed). Caching state of ps command for greater efficiency. Reloaded for each bundle. Index class lookup improves efficiency of class evaluation for huge configurations. Fixed issue where certain promiser strings got corrupted. Minor memory access issues fixed. Iterator bug introduced in 3.1.0 fixed 3.1.1 (Bugfix release) Memory leaks in server tracked down and fixed. List expansion bug (one list items not executed) fixed. Security issue introduced by change of runcommand shell policy fixed. If users defined a runcommand for cf-runagent/cf-serverd communication, possible to execute commands. cf-key -s command for showing key hash/IP address identity pairs 3.1.0 Change in storage of public keys. Cfengine now hashes the public key and uses this as the keyname. Keys will be converted automatically. The old dynamic addresses lists are deprecated. Caching of dns and key information for greater server speed. Change in last-seen format reflects the public key usage. New package policy addupdate - installs package if not there and updates it otherwise. Support for package_changes => "bulk" in file repository as well. New special function readstringarrayidx, similar to readstringarray, but uses integer indices. Very useful if first row elements are not good identifiers (e.g. contains spaces, non-unique, etc.). Change two log formats to use time() instead of date() - filechanges - total compliance Change from using md5 to sha256 as default digest for commercial version, community retains md5 for compat. Commands not returning 0 in commands-promises are flagged as repair_failed. Adjustable timeout on connect(). Defaults to 10 seconds, adjustable with default_timeout in agent control. Redesign of the knowledge map infrastructure. Now possible to use variables to call methods, e.g methods: "name $(list)" usebundle => $(list)("abc"); See reference manual notes Changes to normal ordering to optimize execution. Increased stability by always initializing Attribute and Promise structures. When running cf-promises in dry-run mode (-n), the user does not need to put binaries in WORKDIR/bin. For example, non-privileged users can verify root policies. Source control revision added in version string if run in verbose mode (e.g. "cf-promises -vV"). This needs some refining, uses revision of a header now. New semantics in return values of list functions. Null values are now allowed and there is no iteration over empty lists. The value "cf_null" is reserved for use as a null iterator. 3.0.5p1 Showing paths allowed/denied access to when cf-serverd is run in verbose mode. Bug in server fixed for dynamic addresses. File handle closure bugfix - too many open databases. Seg fault in mount files fix. Twin used in cf-execd without checking. Check_root set wrong directory permissions at source not destination. Error message degraded in body definition. Undefined body not warned as error. Various build enahncements. Package_list_update called only once per manager, and fixed crash. Version number bug in packages. 3.0.5 Encryption problems fixed - client key buffer was uninitialized. Classes-promisers are now automatically canonified when class strings are defined, to simplifying the use of variables in classes. New scalars sys.cf_version and sys.nova_version that hold Cfengine version information. Attribute package_delete_convention added, to allow customizable package name in delete command during update. package_list_update_ifelapsed limit added. Private variable $(firstrepo) is available in package_name_convention and package_delete_convention in order to expand the full path to a package, which is required by some managers. Some of the threading code is rewritten and made more robust. This includes synchronizing access to the lastseen database from the server. Bad initialization of BSD flags fixed Multiple variable expansion issues in control fixed for server and agent Allow ignore_missing_bundles to affect methods: bundles too Run agent trust dialogue fixed Bug in CPU monitoring, increasing time scale caused linear decay of CPU measurement. Bug in Setuid log storage, fix. Hooks added for new Nova virtualization promises. Multithreading mutex failed to collide during cfservd leading to dropped authentication under heavy load. 3.0.4 Class cancellation in promises to create better class feedback, allows emulation of switch/case semantics etc Value of SA measurement promises Special function getenv() which returns the contents of an environment variable (on all platforms). New function translatepath for generic Windows New function escape() to escape literals as regular expressions (like SQL) New function host2ip for caching IP address lookup New function regextract for setting variables with backreferences New variables for the components $(sys.cf_agent), $(sys.cf_know) etc pointing to the binaries. More robust integrated database implementation; closing all handles when receiving signals, self-healing on corruption. Package installation on localhost without a manager like yum completed, multiple repositories searched, and universal methods. Numerous bugfixes 3.0.3 sha256 .. new hashes in openssl included in syntax tree. End of line autocropping in readfile (hopefully intelligent) hashmatch function incorrectly implemented - old debugging code left behind. Fix. sys.crontab variable Unknown user is now interpretated as "same user", so that we give cfengine a chance to fix Unregistered addresses no longer report "(Non registered IP)", but return as the address itself when doing reverse lookups. 3.0.2 IMPORTANT: Change in normal ordering of editing. replace comes after insert lines Much testing and minor bug fixing Memory leaks fixed Many hooks added for Nova enterprise extensions. promise_output reports now placed in WORKDIR/reports directory Initialization correction and self-correx in monitord Many new body constraints added. Code readied for enterprise version Nova. -b option can override the bundlesequence (must not contain parameters yet) collapse_destination_dir option added to copy so that files can be aggregated from subdirectories into a single destination. Preparation for release: unit_accessed_before.cf x unit_accumulated_time.cf x unit_acl.cf x unit_acl_generic.cf x unit_ago.cf x unit_arrays.cf x unit_backreferences_files.cf x unit_badpromise.cf x unit_badtype.cf x unit_bsdflags.cf x unit_cf2_integration.cf x unit_changedbefore.cf x unit_change_detect.cf x unit_chdir.cf x unit_classes_global.cf x unit_classmatch.cf x unit_classvar_convergence.cf x unit_compare.cf x unit_controlclasses.cf x unit_control_expand.cf x unit_copy.cf x unit_copy_edit.cf x unit_copylinks.cf x unit_createdb.cf x unit_create_filedir.cf x unit_definitions.cf x unit_deletelines.cf x unit_disable_and_rotate_files.cf x unit_dollar.cf x unit_edit_column_files.cf x unit_edit_comment_lines.cf x unit_edit_deletenotmatch.cf x unit_edit_insert_lines.cf x unit_edit_insert_lines_silly.cf x unit_edit_replace_string.cf x unit_edit_sectioned_file.cf x unit_edit_setvar.cf x unit_edit_triggerclass.cf x unit-env.cf x unit_epimenides.cf x unit_exec_args.cf x unit_execd.cf x unit_exec_in_sequence.cf x unit_execresult.cf x unit_expand.cf x unit_failsafe.cf x unit_file_change_detection.cf x unit_fileexists.cf x unit_file_owner_list_template.cf x unit_fileperms.cf x unit_filesexist2.cf x unit_filesexist.cf x unit_getgid.cf x unit_getindices.cf x unit_getregistry.cf x unit_getuid.cf x unit_global_list_expansion_2.cf x unit_global_list_expansion.cf x unit_groupexists.cf x unit_hash.cf x unit_hashcomment.cf x unit_hashmatch.cf x unit_helloworld.cf x unit_hostrange.cf x unit_intarray.cf x unit_iprange.cf x unit_irange.cf x unit_isdir.cf x unit_islink.cf x unit_isnewerthan.cf x unit_isplain.cf x unit_isvariable.cf x unit_iteration.cf x unit_knowledge_txt.cf x unit_lastnode.cf x unit_ldap.cf x unit_linking.cf x unit_literal_server.cf x unit_locate_files_and_compress.cf x unit_log_private.cf x unit_loops.cf x unit_measurements.cf x unit_method.cf x unit_method_validate.cf x unit_module_exec_2.cf unit_module_exec.cf unit_mount_fs.cf x unit_neighbourhood_watch.cf x unit_null_config.cf x unit_occurrences.cf x unit_ordering.cf x unit_package_apt.cf x unit_package_hash.cf x unit_package_rpm.cf x unit_package_yum.cf x unit_package_zypper.cf x unit_parallel_exec.cf x unit_pathtype.cf x unit_pattern_and_edit.cf x unit_peers.cf x unit_postfix.cf x unit_process_kill.cf x unit_process_matching2.cf x unit_process_matching.cf x unit_process_signalling.cf x unit_readlist.cf x unit_readtcp.cf x unit_regarray.cf x unit_registry.cf x unit_regline.cf x unit_reglist.cf x unit_remove_deadlinks.cf x unit_rename.cf x unit_report_state.cf x unit_reporttofile.cf x unit_returnszero.cf x unit_select_mode.cf x unit_select_region.cf x unit_selectservers.cf x unit_select_size.cf x unit_server_copy_localhost.cf x unit_server_copy_remote.cf x unit_server_copy_purge.cf x unit_splitstring.cf x unit_sql.cf x unit_storage.cf x unit_strcmp.cf x unit_stringarray.cf x unit_syslog.cf x unit_template.cf x unit_tidy_all_files.cf x unit_user_edit.cf x unit_user_edit_method.cf x unit_userexists.cf x unit_varclass.cf x unit_vars.cf x unit_warnifline.cf x unit_webserver.cf x 3.0.1 First standalone release, independent of cfengine 2 Purge old definitions and check consistency. NB: changed search_mode to be a list of matching values Reporting rationalized in cf-promises with -r only to avoid leaving output files everywhere. Hooks added for upcoming commerical additions to cfengine. Added classify() and hostinnetgroup() functions Added additional change management options for change detection Package management added - generic mechanisms. Limits on backgrounding added to avoid resource contention during cfengine runs. Image type added to cf-know. New classes for quartly shifts: Morning,Afternoon,Evening,Night Bug fixes in editfiles - line insertion for multiple line objects Change the name of the variables and context from the monitord for better separation of data, and shorter names. sys -> mon average -> av, stddev -> dev canonical name for windows changed from "nt" to "windows", also version names added "vista","xp" etc.. License notices updated for dual license editions. 3.0.0 First release of cfengine 3. Known omissions: - no support for ACLs - no support for packages - no support for interface configuration These will be added in the next release. cfengine-3.6.2/libutils/0000775000175100017510000000000012413020721014635 5ustar00a10038a1003800000000000000cfengine-3.6.2/libutils/queue.c0000644000175100017510000000622012316547775016154 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include typedef struct QueueNode_ { void *data; /*!< Pointer to the stored element */ struct QueueNode_ *next; /*!< Next element in the queue or NULL */ struct QueueNode_ *previous; /*!< Pointer to the previous element or NULL */ } QueueNode; struct Queue_ { size_t node_count; /*!< Number of elements in the queue */ QueueItemDestroy *destroy; QueueNode *head; /*!< Pointer to the start of the queue */ QueueNode *tail; /*!< Pointer to the end of the queue */ }; Queue *QueueNew(QueueItemDestroy *item_destroy) { Queue *queue = xcalloc(1, sizeof(Queue)); queue->destroy = item_destroy; return queue; } void QueueDestroy(Queue *q) { if (q) { QueueNode *current = q->head; while (current) { QueueNode *next = current->next; if (q->destroy) { q->destroy(current->data); } free(current); current = next; } free(q); } } static QueueNode *QueueNodeNew(void *element) { QueueNode *node = xmalloc(sizeof(QueueNode)); node->data = element; node->previous = NULL; node->next = NULL; return node; } void QueueEnqueue(Queue *q, void *element) { assert(q); QueueNode *node = QueueNodeNew(element); if (q->tail) { q->tail->next = node; node->previous = q->tail; q->tail = node; } else { q->tail = node; q->head = node; } ++q->node_count; } void *QueueDequeue(Queue *q) { assert(q); QueueNode *node = q->head; void *data = node->data; q->head = node->next; if (q->head) { q->head->previous = NULL; } else { /* Empty queue */ q->head = NULL; q->tail = NULL; } --q->node_count; /* Free the node */ free(node); /* Return the data */ return data; } void *QueueHead(Queue *q) { assert(q); return q->head->data; } int QueueCount(const Queue *q) { assert(q); return q->node_count; } bool QueueIsEmpty(const Queue *q) { assert(q); return q->node_count == 0; } cfengine-3.6.2/libutils/pcre_include.h0000664000175100017510000000042412411001073017437 0ustar00a10038a1003800000000000000/* * PCRE in RHEL4 is within a subdirectory itself. We do the inclusion here so * that you can just do #include "pcre_include.h" instead of ifdef'ing all the * time. */ #ifdef HAVE_PCRE_H # include #endif #ifdef HAVE_PCRE_PCRE_H # include #endif cfengine-3.6.2/libutils/string_lib.h0000664000175100017510000001266112400110676017155 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_STRING_LIB_H #define CFENGINE_STRING_LIB_H #include #include #include #include typedef struct { const char *data; size_t len; } StringRef; unsigned int StringHash(const char *str, unsigned int seed, unsigned int max); char ToLower(char ch); char ToUpper(char ch); void ToUpperStrInplace(char *str); void ToLowerStrInplace(char *str); long StringToLong(const char *str); char *StringFromLong(long number); double StringToDouble(const char *str); char *StringFromDouble(double number); char *NULLStringToEmpty(char *str); bool StringIsNumeric(const char *name); bool StringIsPrintable(const char *name); bool EmptyString(const char *s); size_t StringBytesToHex(char *dst, size_t dst_size, const unsigned char *src_bytes, size_t src_len); char *SafeStringDuplicate(const char *str); int SafeStringLength(const char *str); int StringSafeCompare(const char *a, const char *b); bool StringSafeEqual(const char *a, const char *b); char *StringConcatenate(size_t count, const char *first, ...); char *StringSubstring(const char *source, size_t source_len, int start, int len); /* Allocates the result */ char *SearchAndReplace(const char *source, const char *search, const char *replace); bool ReplaceStr(const char *in, char *out, int outSz, const char *from, const char *to); bool IsStrIn(const char *str, const char *const strs[]); bool IsStrCaseIn(const char *str, const char *const strs[]); size_t StringCountTokens(const char *str, size_t len, const char *seps); StringRef StringGetToken(const char *str, size_t len, size_t index, const char *seps); char **String2StringArray(const char *str, char separator); void FreeStringArray(char **strs); int CountChar(const char *string, char sp); void ReplaceChar(char *in, char *out, int outSz, char from, char to); void ReplaceTrailingChar(char *str, char from, char to); char *EscapeCharCopy(const char *str, char to_escape, char escape_with); int StringInArray(char **array, char *string); char *ScanPastChars(char *scanpast, char *input); /** * @brief Strips the newline character off a string, in place * @param str The string to strip * @param max_length Maximum length of input string * @return 0 if successful, -1 if the input string was longer than allowed (max_length). */ int StripTrailingNewline(char *str, size_t max_length); /** * @brief Remove trailing spaces * @param str * @param max_length Maximum length of input string * @return 0 if successful, -1 if Chop was called on a string that seemed to have no terminator */ int Chop(char *str, size_t max_length); /** * @brief Check if a string ends with the given suffix * @param str * @param suffix * @return True if suffix matches */ bool StringEndsWith(const char *str, const char *suffix); /** * @brief Check if a string starts with the given prefix * @param str * @param prefix * @return True if prefix matches */ bool StringStartsWith(const char *str, const char *prefix); /** * @brief Format string like vsprintf and return formatted string allocated * on heap as a return value. */ char *StringVFormat(const char *fmt, va_list ap); /** * @brief Format string like sprintf and return formatted string allocated on * heap as a return value. * * @param format Formatting string * @return formatted string (on heap) or NULL in case of error. errno is set in * the latter case (see errno codes for sprintf). */ char *StringFormat(const char *fmt, ...) FUNC_ATTR_PRINTF(1, 2); /** * @brief Find the initial segment of memory (up to #n bytes) consisting of character #c. * * @return first byte which is not #c, or #mem + #n if all bytes in memory segment are #c */ void *MemSpan(const void *mem, char c, size_t n); /** * @brief Find the initial segment of memory (up to #n bytes) consisting not of character #c. * * @return first byte which is #c, or #mem + #n if none of bytes in memory segment are #c */ void *MemSpanInverse(const void *mem, char c, size_t n); bool StringNotMatchingSetCapped(const char *isp, int limit, const char *exclude, char *obuf); /** * @brief Appends src to dst, but will not exceed n bytes in dst, including the terminating null. * @param dst Destination string. * @param src Source string. * @param n Total size of dst buffer. The string will be truncated if this is exceeded. * @return True if append was successful, false if the operation caused an overflow. */ bool StringAppend(char *dst, const char *src, size_t n); #endif cfengine-3.6.2/libutils/file_lib.c0000664000175100017510000004634712411001073016561 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include bool FileCanOpen(const char *path, const char *modes) { FILE *test = NULL; if ((test = fopen(path, modes)) != NULL) { fclose(test); return true; } else { return false; } } #define READ_BUFSIZE 4096 Writer *FileRead(const char *filename, size_t max_size, bool *truncated) { int fd = safe_open(filename, O_RDONLY); if (fd == -1) { return NULL; } Writer *w = FileReadFromFd(fd, max_size, truncated); close(fd); return w; } Writer *FileReadFromFd(int fd, size_t max_size, bool *truncated) { if (truncated) { *truncated = false; } Writer *w = StringWriter(); for (;;) { char buf[READ_BUFSIZE]; /* Reading more data than needed is deliberate. It is a truncation detection. */ ssize_t read_ = read(fd, buf, READ_BUFSIZE); if (read_ == 0) { /* Done. */ return w; } else if (read_ < 0) { if (errno != EINTR) { /* Something went wrong. */ WriterClose(w); return NULL; } /* Else: interrupted - try again. */ } else if (read_ + StringWriterLength(w) > max_size) { WriterWriteLen(w, buf, max_size - StringWriterLength(w)); /* Reached limit - stop. */ if (truncated) { *truncated = true; } return w; } else /* Filled buffer; copy and ask for more. */ { WriterWriteLen(w, buf, read_); } } } int FullWrite(int desc, const char *ptr, size_t len) { int total_written = 0; while (len > 0) { int written = write(desc, ptr, len); if (written < 0) { if (errno == EINTR) { continue; } return written; } total_written += written; ptr += written; len -= written; } return total_written; } int FullRead(int fd, char *ptr, size_t len) { int total_read = 0; while (len > 0) { int bytes_read = read(fd, ptr, len); if (bytes_read < 0) { if (errno == EINTR) { continue; } return -1; } if (bytes_read == 0) { return total_read; } total_read += bytes_read; ptr += bytes_read; len -= bytes_read; } return total_read; } /** * @return 1 if dir, 0 if not, -1 in case of error. * @note difference with files_names.h:IsDir() is that this doesn't * follow symlinks, so a symlink is never a directory... */ int IsDirReal(const char *path) { struct stat s; if (lstat(path, &s) == -1) { return -1; } return (S_ISDIR(s.st_mode) != 0); } #ifndef __MINGW32__ NewLineMode FileNewLineMode(ARG_UNUSED const char *file) { return NewLineMode_Unix; } #endif // !__MINGW32__ bool IsAbsoluteFileName(const char *f) { int off = 0; // Check for quoted strings for (off = 0; f[off] == '\"'; off++) { } #ifdef _WIN32 if (IsFileSep(f[off]) && IsFileSep(f[off + 1])) { return true; } if (isalpha(f[off]) && f[off + 1] == ':' && IsFileSep(f[off + 2])) { return true; } #endif if (IsFileSep(f[off])) { return true; } return false; } /* We assume that s is at least MAX_FILENAME large. * MapName() is thread-safe, but the argument is modified. */ #ifdef _WIN32 # if defined(__MINGW32__) char *MapNameCopy(const char *s) { char *str = xstrdup(s); char *c = str; while ((c = strchr(c, '/'))) { *c = '\\'; } return str; } char *MapName(char *s) { char *c = s; while ((c = strchr(c, '/'))) { *c = '\\'; } return s; } # elif defined(__CYGWIN__) char *MapNameCopy(const char *s) { Writer *w = StringWriter(); /* c:\a\b -> /cygdrive/c\a\b */ if (s[0] && isalpha(s[0]) && s[1] == ':') { WriterWriteF(w, "/cygdrive/%c", s[0]); s += 2; } for (; *s; s++) { /* a//b//c -> a/b/c */ /* a\\b\\c -> a\b\c */ if (IsFileSep(*s) && IsFileSep(*(s + 1))) { continue; } /* a\b\c -> a/b/c */ WriterWriteChar(w, *s == '\\' ? '/' : *s); } return StringWriterClose(w); } char *MapName(char *s) { char *ret = MapNameCopy(s); if (strlcpy(s, ret, MAX_FILENAME) >= MAX_FILENAME) { FatalError(ctx, "Expanded path (%s) is longer than MAX_FILENAME (" TOSTRING(MAX_FILENAME) ") characters", ret); } free(ret); return s; } # else/* !__MINGW32__ && !__CYGWIN__ */ # error Unknown NT-based compilation environment # endif/* __MINGW32__ || __CYGWIN__ */ #else /* !_WIN32 */ char *MapName(char *s) { return s; } char *MapNameCopy(const char *s) { return xstrdup(s); } #endif /* !_WIN32 */ char *MapNameForward(char *s) /* Like MapName(), but maps all slashes to forward */ { while ((s = strchr(s, '\\'))) { *s = '/'; } return s; } #ifdef TEST_SYMLINK_ATOMICITY void switch_symlink_hook(); #define TEST_SYMLINK_SWITCH_POINT switch_symlink_hook(); #else #define TEST_SYMLINK_SWITCH_POINT #endif /** * Opens a file safely. It will follow symlinks, but only if the symlink is trusted, * that is, if the owner of the symlink and the owner of the target are the same. * All components are checked, even symlinks encountered in earlier parts of the * path name. * * It should always be used when opening a file or directory that is not guaranteed * to be owned by root. * * @param pathname The path to open. * @param flags Same flags as for system open(). * @param ... Optional mode argument, as per system open(). * @return Same errors as open(). */ int safe_open(const char *pathname, int flags, ...) { if (!pathname) { errno = EINVAL; return -1; } if (*pathname == '\0') { errno = ENOENT; return -1; } mode_t mode; if (flags & O_CREAT) { va_list ap; va_start(ap, flags); mode = va_arg(ap, int); va_end(ap); } else { mode = 0; } #ifdef __MINGW32__ // Windows gets off easy. No symlinks there. return open(pathname, flags, mode); #else // !__MINGW32__ char path[strlen(pathname) + 1]; strcpy(path, pathname); int currentfd; const char *first_dir; char *next_component; bool trunc = false; int orig_flags = flags; if (flags & O_TRUNC) { trunc = true; /* We need to check after we have opened the file whether we opened the * right one. But if we truncate it, the damage is already done, we have * destroyed the contents. So save that flag and apply the truncation * afterwards instead. */ flags &= ~O_TRUNC; } next_component = path; if (*next_component == '/') { first_dir = "/"; // Eliminate double slashes. while (*(++next_component) == '/') { /*noop*/ } if (!*next_component) { next_component = NULL; } } else { first_dir = "."; } currentfd = openat(AT_FDCWD, first_dir, O_RDONLY); if (currentfd < 0) { return -1; } while (next_component) { char *component = next_component; next_component = strchr(component + 1, '/'); // Used to restore the slashes in the final path component. char *restore_slash = NULL; if (next_component) { restore_slash = next_component; *next_component = '\0'; // Eliminate double slashes. while (*(++next_component) == '/') { /*noop*/ } if (!*next_component) { next_component = NULL; } else { restore_slash = NULL; } } // In cases of a race condition when creating a file, our attempt to open it may fail // (see O_EXCL and O_CREAT flags below). However, this can happen even under normal // circumstances, if we are unlucky; it does not mean that someone is up to something bad. // So retry it a few times before giving up. int attempts = 3; while (true) { if (restore_slash) { *restore_slash = '\0'; } struct stat stat_before, stat_after; int stat_before_result = fstatat(currentfd, component, &stat_before, AT_SYMLINK_NOFOLLOW); if (stat_before_result < 0 && (errno != ENOENT || next_component // Meaning "not a leaf". || !(flags & O_CREAT))) { close(currentfd); return -1; } TEST_SYMLINK_SWITCH_POINT if (!next_component) { // Last component. if (stat_before_result < 0) { // Doesn't exist. Make *sure* we create it. flags |= O_EXCL; } else { // Already exists. Make sure we *don't* create it. flags &= ~O_CREAT; } if (restore_slash) { *restore_slash = '/'; } int filefd = openat(currentfd, component, flags, mode); if (filefd < 0) { if ((stat_before_result < 0 && !(orig_flags & O_EXCL) && errno == EEXIST) || (stat_before_result >= 0 && orig_flags & O_CREAT && errno == ENOENT)) { if (--attempts >= 0) { // Might be our fault. Try again. flags = orig_flags; continue; } else { // Too many attempts. Give up. errno = EACCES; } } close(currentfd); return -1; } close(currentfd); currentfd = filefd; } else { int new_currentfd = openat(currentfd, component, O_RDONLY); close(currentfd); if (new_currentfd < 0) { return -1; } currentfd = new_currentfd; } if (stat_before_result == 0) { if (fstat(currentfd, &stat_after) < 0) { close(currentfd); return -1; } if (stat_before.st_uid != stat_after.st_uid || stat_before.st_gid != stat_after.st_gid) { close(currentfd); errno = EACCES; return -1; } } // If we got here, we've been successful, so don't try again. break; } } if (trunc) { if (ftruncate(currentfd, 0) < 0) { close(currentfd); return -1; } } return currentfd; #endif // !__MINGW32__ } /** * Opens a file safely. It will follow symlinks, but only if the symlink is trusted, * that is, if the owner of the symlink and the owner of the target are the same. * All components are checked, even symlinks encountered in earlier parts of the * path name. * * It should always be used when opening a directory that is not guaranteed to be * owned by root. * * @param pathname The path to open. * @param flags Same mode as for system fopen(). * @return Same errors as fopen(). */ FILE *safe_fopen(const char *path, const char *mode) { if (!path || !mode) { errno = EINVAL; return NULL; } int flags = 0; for (int c = 0; mode[c]; c++) { switch (mode[c]) { case 'r': flags |= O_RDONLY; break; case 'w': flags |= O_WRONLY | O_TRUNC | O_CREAT; break; case 'a': flags |= O_WRONLY | O_CREAT; break; case '+': flags &= ~(O_RDONLY | O_WRONLY); flags |= O_RDWR; break; case 'b': flags |= O_BINARY; break; case 't': flags |= O_TEXT; break; default: break; } } int fd = safe_open(path, flags, 0666); if (fd < 0) { return NULL; } FILE *ret = fdopen(fd, mode); if (!ret) { close(fd); return NULL; } if (mode[0] == 'a') { if (fseek(ret, 0, SEEK_END) < 0) { fclose(ret); return NULL; } } return ret; } /** * Use this instead of chdir(). It changes into the directory safely, using safe_open(). * @param path Path to change into. * @return Same return values as chdir(). */ int safe_chdir(const char *path) { #ifdef __MINGW32__ return chdir(path); #else // !__MINGW32__ int fd = safe_open(path, O_RDONLY); if (fd < 0) { return -1; } if (fchdir(fd) < 0) { close(fd); return -1; } close(fd); return 0; #endif // !__MINGW32__ } /** * Use this instead of chown(). It changes file owner safely, using safe_open(). * @param path Path to operate on. * @param owner Owner. * @param group Group. * @return Same return values as chown(). */ int safe_chown(const char *path, uid_t owner, gid_t group) { #ifdef __MINGW32__ return chown(path, owner, group); #else // !__MINGW32__ int fd = safe_open(path, 0); if (fd < 0) { return -1; } int ret = fchown(fd, owner, group); close(fd); return ret; #endif // !__MINGW32__ } /** * Use this instead of lchown(). It changes file owner safely, using safe_open(). * @param path Path to operate on. * @param owner Owner. * @param group Group. * @return Same return values as lchown(). */ #ifndef __MINGW32__ int safe_lchown(const char *path, uid_t owner, gid_t group) { if (*path == '\0') { errno = EINVAL; return -1; } size_t orig_size = strlen(path); char parent_dir[orig_size + 1]; char *slash_pos = strrchr(path, '/'); const char *leaf; if (slash_pos) { strcpy(parent_dir, path); // Same value, but relative to parent_dir. leaf = slash_pos = &parent_dir[slash_pos - path]; leaf++; // Remove all superflous slashes, but not if it's the root slash. while (*slash_pos == '/' && slash_pos != parent_dir) { *(slash_pos--) = '\0'; } } else { parent_dir[0] = '.'; parent_dir[1] = '\0'; leaf = path; } int parent_fd = safe_open(parent_dir, O_RDONLY); if (parent_fd < 0) { return -1; } int ret = fchownat(parent_fd, leaf, owner, group, AT_SYMLINK_NOFOLLOW); close(parent_fd); return ret; } #endif // !__MINGW32__ /** * Use this instead of chmod(). It changes file permissions safely, using safe_open(). * @param path Path to operate on. * @param mode Permissions. * @return Same return values as chmod(). */ int safe_chmod(const char *path, mode_t mode) { #ifdef __MINGW32__ return chmod(path, mode); #else // !__MINGW32__ int fd = safe_open(path, 0); if (fd < 0) { return -1; } int ret = fchmod(fd, mode); close(fd); return ret; #endif // !__MINGW32__ } /** * Use this instead of creat(). It creates a file safely, using safe_open(). * @param path Path to operate on. * @param mode Permissions. * @return Same return values as creat(). */ int safe_creat(const char *pathname, mode_t mode) { return safe_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); } static bool DeleteDirectoryTreeInternal(const char *basepath, const char *path) { Dir *dirh = DirOpen(path); const struct dirent *dirp; bool failed = false; if (dirh == NULL) { if (errno == ENOENT) { /* Directory disappeared on its own */ return true; } Log(LOG_LEVEL_INFO, "Unable to open directory '%s' during purge of directory tree '%s' (opendir: %s)", path, basepath, GetErrorStr()); return false; } for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (!strcmp(dirp->d_name, ".") || !strcmp(dirp->d_name, "..")) { continue; } char subpath[PATH_MAX]; snprintf(subpath, sizeof(subpath), "%s" FILE_SEPARATOR_STR "%s", path, dirp->d_name); struct stat lsb; if (lstat(subpath, &lsb) == -1) { if (errno == ENOENT) { /* File disappeared on its own */ continue; } Log(LOG_LEVEL_VERBOSE, "Unable to stat file '%s' during purge of directory tree '%s' (lstat: %s)", path, basepath, GetErrorStr()); failed = true; } else { if (S_ISDIR(lsb.st_mode)) { if (!DeleteDirectoryTreeInternal(basepath, subpath)) { failed = true; } if (rmdir(subpath) == -1) { failed = true; } } else { if (unlink(subpath) == -1) { if (errno == ENOENT) { /* File disappeared on its own */ continue; } Log(LOG_LEVEL_VERBOSE, "Unable to remove file '%s' during purge of directory tree '%s'. (unlink: %s)", subpath, basepath, GetErrorStr()); failed = true; } } } } DirClose(dirh); return !failed; } bool DeleteDirectoryTree(const char *path) { return DeleteDirectoryTreeInternal(path, path); } cfengine-3.6.2/libutils/csv_writer.h0000644000175100017510000000313012316547775017221 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CSV_WRITER_H #define CFENGINE_CSV_WRITER_H /* * This writer implements CSV as in RFC 4180 */ #include #include typedef struct CsvWriter_ CsvWriter; CsvWriter *CsvWriterOpen(Writer *w); void CsvWriterField(CsvWriter *csvw, const char *str); void CsvWriterFieldF(CsvWriter *csvw, const char *fmt, ...) FUNC_ATTR_PRINTF(2, 3); void CsvWriterNewRecord(CsvWriter *csvw); /* Does not close underlying Writer, but flushes all pending data */ void CsvWriterClose(CsvWriter *csvw); /** * @return The instance of the underlying writer */ Writer *CsvWriterGetWriter(CsvWriter *csvw); #endif cfengine-3.6.2/libutils/mustache.c0000664000175100017510000004434312411001073016617 0ustar00a10038a1003800000000000000#include #include #include #include #include typedef enum { TAG_TYPE_VAR, TAG_TYPE_VAR_UNESCAPED, TAG_TYPE_SECTION, TAG_TYPE_SECTION_END, TAG_TYPE_INVERTED, TAG_TYPE_COMMENT, TAG_TYPE_DELIM, TAG_TYPE_ERR, TAG_TYPE_NONE } TagType; typedef struct { TagType type; const char *begin; const char *end; const char *content; size_t content_len; } Mustache; #define MUSTACHE_MAX_DELIM_SIZE 10 static bool IsSpace(char c) { return c == '\t' || c == ' '; } static bool IsTagStandalone(const char *start, const char *tag_start, const char *tag_end, const char **line_begin, const char **line_end) { assert(start <= tag_start); *line_begin = start; for (const char *cur = tag_start - 1; cur >= start; cur--) { if (IsSpace(*cur)) { *line_begin = cur; if (cur == start) { break; } continue; } else if (*cur == '\n') { *line_begin = cur + 1; break; } else { return false; } } *line_end = NULL; for (const char *cur = tag_end; true; cur++) { if (IsSpace(*cur)) { continue; } else if (*cur == '\n') { *line_end = cur + 1; break; } else if (*cur == '\r') { if (*(cur + 1) == '\n') { *line_end = cur + 2; break; } continue; } else if (*cur == '\0') { *line_end = cur; break; } else { return false; } } assert(*line_end); return true; } static bool IsTagTypeRenderable(TagType type) { switch (type) { case TAG_TYPE_COMMENT: case TAG_TYPE_DELIM: case TAG_TYPE_ERR: case TAG_TYPE_INVERTED: case TAG_TYPE_SECTION: case TAG_TYPE_SECTION_END: return false; default: return true; } } static JsonElement *LookupVariable(Seq *hash_stack, const char *name, size_t name_len) { assert(SeqLength(hash_stack) > 0); size_t num_comps = StringCountTokens(name, name_len, "."); JsonElement *base_var = NULL; { StringRef base_comp = StringGetToken(name, name_len, 0, "."); char *base_comp_str = xstrndup(base_comp.data, base_comp.len); for (ssize_t i = SeqLength(hash_stack) - 1; i >= 0; i--) { JsonElement *hash = SeqAt(hash_stack, i); if (!hash) { continue; } if (JsonGetElementType(hash) == JSON_ELEMENT_TYPE_CONTAINER && JsonGetContainerType(hash) == JSON_CONTAINER_TYPE_OBJECT) { JsonElement *var = JsonObjectGet(hash, base_comp_str); if (var) { base_var = var; break; } } } free(base_comp_str); } if (!base_var) { return NULL; } for (size_t i = 1; i < num_comps; i++) { if (JsonGetElementType(base_var) != JSON_ELEMENT_TYPE_CONTAINER || JsonGetContainerType(base_var) != JSON_CONTAINER_TYPE_OBJECT) { return NULL; } StringRef comp = StringGetToken(name, name_len, i, "."); char *comp_str = xstrndup(comp.data, comp.len); base_var = JsonObjectGet(base_var, comp_str); free(comp_str); if (!base_var) { return NULL; } } assert(base_var); return base_var; } static Mustache NextTag(const char *input, const char *delim_start, size_t delim_start_len, const char *delim_end, size_t delim_end_len) { Mustache ret; ret.type = TAG_TYPE_NONE; ret.begin = strstr(input, delim_start); if (!ret.begin) { return ret; } ret.content = ret.begin + delim_start_len; char *extra_end = NULL; switch (ret.content[0]) { case '#': ret.type = TAG_TYPE_SECTION; ret.content++; break; case '^': ret.type = TAG_TYPE_INVERTED; ret.content++; break; case '/': ret.type = TAG_TYPE_SECTION_END; ret.content++; break; case '!': ret.type = TAG_TYPE_COMMENT; ret.content++; break; case '=': extra_end = "="; ret.type = TAG_TYPE_DELIM; ret.content++; break; case '{': extra_end = "}"; case '&': ret.type = TAG_TYPE_VAR_UNESCAPED; ret.content++; break; default: ret.type = TAG_TYPE_VAR; break; } if (extra_end) { const char *escape_end = strstr(ret.content, extra_end); if (!escape_end || strncmp(escape_end + 1, delim_end, delim_end_len) != 0) { Log(LOG_LEVEL_WARNING, "Broken mustache template, couldn't find end tag for quoted begin tag at '%20s'...", input); ret.type = TAG_TYPE_ERR; return ret; } ret.content_len = escape_end - ret.content; ret.end = escape_end + 1 + delim_end_len; } else { ret.end = strstr(ret.content, delim_end); if (!ret.end) { Log(LOG_LEVEL_WARNING, "Broken Mustache template, could not find end delimiter after reading start delimiter at '%20s'...", input); ret.type = TAG_TYPE_ERR; return ret; } ret.content_len = ret.end - ret.content; ret.end += delim_end_len; } while (*ret.content == ' ' || *ret.content == '\t') { ret.content++; ret.content_len--; } while (ret.content[ret.content_len - 1] == ' ' || ret.content[ret.content_len - 1] == '\t') { ret.content_len--; } return ret; } static void RenderHTMLContent(Buffer *out, const char *input, size_t len) { for (size_t i = 0; i < len; i++) { switch (input[i]) { case '&': BufferAppendString(out, "&"); break; case '"': BufferAppendString(out, """); break; case '<': BufferAppendString(out, "<"); break; case '>': BufferAppendString(out, ">"); break; default: BufferAppendChar(out, input[i]); break; } } } static void RenderContent(Buffer *out, const char *content, size_t len, bool html, bool skip_content) { if (skip_content) { return; } if (html) { RenderHTMLContent(out, content, len); } else { BufferAppend(out, content, len); } } static bool RenderVariablePrimitive(Buffer *out, const JsonElement *primitive, const bool escaped) { switch (JsonGetPrimitiveType(primitive)) { case JSON_PRIMITIVE_TYPE_STRING: if (escaped) { RenderHTMLContent(out, JsonPrimitiveGetAsString(primitive), strlen(JsonPrimitiveGetAsString(primitive))); } else { BufferAppendString(out, JsonPrimitiveGetAsString(primitive)); } return true; case JSON_PRIMITIVE_TYPE_INTEGER: { char *str = StringFromLong(JsonPrimitiveGetAsInteger(primitive)); BufferAppendString(out, str); free(str); } return true; case JSON_PRIMITIVE_TYPE_REAL: { char *str = StringFromDouble(JsonPrimitiveGetAsReal(primitive)); BufferAppendString(out, str); free(str); } return true; case JSON_PRIMITIVE_TYPE_BOOL: BufferAppendString(out, JsonPrimitiveGetAsBool(primitive) ? "true" : "false"); return true; case JSON_PRIMITIVE_TYPE_NULL: return true; default: assert(!"Unrecognised JSON primitive type"); } return false; } static bool RenderVariable(Buffer *out, const char *content, size_t content_len, bool escaped, Seq *hash_stack) { JsonElement *var = NULL; if (strncmp(content, ".", content_len) == 0) { var = SeqAt(hash_stack, SeqLength(hash_stack) - 1); } else { var = LookupVariable(hash_stack, content, content_len); } if (!var) { return true; } switch (JsonGetElementType(var)) { case JSON_ELEMENT_TYPE_PRIMITIVE: return RenderVariablePrimitive(out, var, escaped); case JSON_ELEMENT_TYPE_CONTAINER: assert(false); return false; } assert(false); return false; } static bool SetDelimiters(const char *content, size_t content_len, char *delim_start, size_t *delim_start_len, char *delim_end, size_t *delim_end_len) { size_t num_tokens = StringCountTokens(content, content_len, " \t"); if (num_tokens != 2) { Log(LOG_LEVEL_WARNING, "Could not parse delimiter mustache, number of tokens is %zd, expected 2 in '%s'", num_tokens, content); return false; } StringRef first = StringGetToken(content, content_len, 0, " \t"); if (first.len > MUSTACHE_MAX_DELIM_SIZE) { Log(LOG_LEVEL_WARNING, "New mustache start delimiter exceeds the allowed size of %d in '%s'", MUSTACHE_MAX_DELIM_SIZE, content); return false; } strncpy(delim_start, first.data, first.len); delim_start[first.len] = '\0'; *delim_start_len = first.len; StringRef second = StringGetToken(content, content_len, 1, " \t"); if (second.len > MUSTACHE_MAX_DELIM_SIZE) { Log(LOG_LEVEL_WARNING, "New mustache start delimiter exceeds the allowed size of %d in '%s'", MUSTACHE_MAX_DELIM_SIZE, content); return false; } strncpy(delim_end, second.data, second.len); delim_end[second.len] = '\0'; *delim_end_len = second.len; return true; } static bool Render(Buffer *out, const char *start, const char *input, Seq *hash_stack, char *delim_start, size_t *delim_start_len, char *delim_end, size_t *delim_end_len, bool skip_content, const char *section, const char **section_end) { while (true) { if (!input) { Log(LOG_LEVEL_ERR, "Unexpected end to Mustache template"); return false; } Mustache tag = NextTag(input, delim_start, *delim_start_len, delim_end, *delim_end_len); { const char *line_begin = NULL; const char *line_end = NULL; if (!IsTagTypeRenderable(tag.type) && IsTagStandalone(start, tag.begin, tag.end, &line_begin, &line_end)) { RenderContent(out, input, line_begin - input, false, skip_content); input = line_end; } else { RenderContent(out, input, tag.begin - input, false, skip_content); input = tag.end; } } switch (tag.type) { case TAG_TYPE_ERR: return false; case TAG_TYPE_DELIM: if (!SetDelimiters(tag.content, tag.content_len, delim_start, delim_start_len, delim_end, delim_end_len)) { return false; } continue; case TAG_TYPE_COMMENT: continue; case TAG_TYPE_NONE: return true; case TAG_TYPE_VAR_UNESCAPED: case TAG_TYPE_VAR: if (!skip_content) { if (tag.content_len > 0) { if (!RenderVariable(out, tag.content, tag.content_len, tag.type == TAG_TYPE_VAR, hash_stack)) { return false; } } else { RenderContent(out, delim_start, *delim_start_len, false, false); RenderContent(out, delim_end, *delim_end_len, false, false); } } continue; case TAG_TYPE_INVERTED: case TAG_TYPE_SECTION: { char *section = xstrndup(tag.content, tag.content_len); JsonElement *var = LookupVariable(hash_stack, tag.content, tag.content_len); SeqAppend(hash_stack, var); if (!var) { const char *cur_section_end = NULL; if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len, skip_content || tag.type != TAG_TYPE_INVERTED, section, &cur_section_end)) { free(section); return false; } free(section); input = cur_section_end; continue; } switch (JsonGetElementType(var)) { case JSON_ELEMENT_TYPE_PRIMITIVE: switch (JsonGetPrimitiveType(var)) { case JSON_PRIMITIVE_TYPE_BOOL: { bool skip = skip_content || (!JsonPrimitiveGetAsBool(var) ^ (tag.type == TAG_TYPE_INVERTED)); const char *cur_section_end = NULL; if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len, skip, section, &cur_section_end)) { free(section); return false; } free(section); input = cur_section_end; } continue; default: Log(LOG_LEVEL_WARNING, "Mustache sections can only take a boolean or a container (array or map) value, but section '%s' isn't getting one of those.", section); return false; } break; case JSON_ELEMENT_TYPE_CONTAINER: switch (JsonGetContainerType(var)) { case JSON_CONTAINER_TYPE_OBJECT: { const char *cur_section_end = NULL; if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len, skip_content || tag.type == TAG_TYPE_INVERTED, section, &cur_section_end)) { free(section); return false; } free(section); input = cur_section_end; } break; case JSON_CONTAINER_TYPE_ARRAY: if (JsonLength(var) > 0) { const char *cur_section_end = NULL; for (size_t i = 0; i < JsonLength(var); i++) { JsonElement *child_hash = JsonAt(var, i); SeqAppend(hash_stack, child_hash); if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len, skip_content || tag.type == TAG_TYPE_INVERTED, section, &cur_section_end)) { free(section); return false; } } input = cur_section_end; free(section); } else { const char *cur_section_end = NULL; if (!Render(out, start, input, hash_stack, delim_start, delim_start_len, delim_end, delim_end_len, tag.type != TAG_TYPE_INVERTED, section, &cur_section_end)) { free(section); return false; } free(section); input = cur_section_end; } break; } break; } } continue; case TAG_TYPE_SECTION_END: if (!section) { char *varname = xstrndup(tag.content, tag.content_len); Log(LOG_LEVEL_WARNING, "Unknown section close in mustache template '%s'", varname); free(varname); return false; } else { SeqRemove(hash_stack, SeqLength(hash_stack) - 1); *section_end = input; return true; } break; default: assert(false); return false; } } assert(false); } bool MustacheRender(Buffer *out, const char *input, const JsonElement *hash) { char delim_start[MUSTACHE_MAX_DELIM_SIZE] = "{{"; size_t delim_start_len = strlen(delim_start); char delim_end[MUSTACHE_MAX_DELIM_SIZE] = "}}"; size_t delim_end_len = strlen(delim_end); Seq *hash_stack = SeqNew(10, NULL); SeqAppend(hash_stack, (JsonElement*)hash); bool success = Render(out, input, input, hash_stack, delim_start, &delim_start_len, delim_end, &delim_end_len, false, NULL, NULL); SeqDestroy(hash_stack); return success; } cfengine-3.6.2/libutils/writer.c0000664000175100017510000001462312400110676016330 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include typedef enum { WT_STRING, WT_FILE, } WriterType; typedef struct { char *data; size_t len; /* Does not include trailing zero */ size_t allocated; /* Includes trailing zero */ } StringWriterImpl; struct Writer_ { WriterType type; union { StringWriterImpl string; FILE *file; }; }; /*********************************************************************/ Writer *FileWriter(FILE *file) { Writer *writer = xcalloc(1, sizeof(Writer)); writer->type = WT_FILE; writer->file = file; return writer; } /*********************************************************************/ Writer *StringWriter(void) { Writer *writer = xcalloc(1, sizeof(Writer)); writer->type = WT_STRING; writer->string.data = xstrdup(""); writer->string.allocated = 1; writer->string.len = 0; return writer; } /*********************************************************************/ static void StringWriterReallocate(Writer *writer, size_t extra_length) { writer->string.allocated = MAX(writer->string.allocated * 2, writer->string.len + extra_length + 1); writer->string.data = xrealloc(writer->string.data, writer->string.allocated); } static size_t StringWriterWriteChar(Writer *writer, char c) { if (writer->string.len + 2 > writer->string.allocated) { StringWriterReallocate(writer, 2); } writer->string.data[writer->string.len] = c; writer->string.data[writer->string.len + 1] = '\0'; writer->string.len++; return 1; } static size_t StringWriterWriteLen(Writer *writer, const char *str, size_t len_) { /* NB: str[:len_] may come from read(), which hasn't '\0'-terminated */ size_t len = strnlen(str, len_); if (writer->string.len + len + 1 > writer->string.allocated) { StringWriterReallocate(writer, len); } memcpy(writer->string.data + writer->string.len, str, len); writer->string.data[writer->string.len + len] = '\0'; writer->string.len += len; return len; } /*********************************************************************/ static size_t FileWriterWriteF(Writer *writer, const char *fmt, va_list ap) { return vfprintf(writer->file, fmt, ap); } /*********************************************************************/ static size_t FileWriterWriteLen(Writer *writer, const char *str, size_t len_) { size_t len = strnlen(str, len_); #ifdef CFENGINE_TEST return CFENGINE_TEST_fwrite(str, 1, len, writer->file); #else return fwrite(str, 1, len, writer->file); #endif } /*********************************************************************/ size_t WriterWriteF(Writer *writer, const char *fmt, ...) { va_list ap; va_start(ap, fmt); size_t size = WriterWriteVF(writer, fmt, ap); va_end(ap); return size; } /*********************************************************************/ size_t WriterWriteVF(Writer *writer, const char *fmt, va_list ap) { if (writer->type == WT_STRING) { char *str = NULL; xvasprintf(&str, fmt, ap); size_t size = StringWriterWriteLen(writer, str, INT_MAX); free(str); return size; } else { return FileWriterWriteF(writer, fmt, ap); } } /*********************************************************************/ size_t WriterWriteLen(Writer *writer, const char *str, size_t len) { if (writer->type == WT_STRING) { return StringWriterWriteLen(writer, str, len); } else { return FileWriterWriteLen(writer, str, len); } } /*********************************************************************/ size_t WriterWrite(Writer *writer, const char *str) { return WriterWriteLen(writer, str, INT_MAX); } /*********************************************************************/ size_t WriterWriteChar(Writer *writer, char c) { if (writer->type == WT_STRING) { return StringWriterWriteChar(writer, c); } else { char s[2] = { c, '\0' }; return FileWriterWriteLen(writer, s, 1); } } /*********************************************************************/ size_t StringWriterLength(const Writer *writer) { if (writer->type != WT_STRING) { ProgrammingError("Wrong writer type"); } return writer->string.len; } /*********************************************************************/ const char *StringWriterData(const Writer *writer) { if (writer->type != WT_STRING) { ProgrammingError("Wrong writer type"); } return writer->string.data; } /*********************************************************************/ void WriterClose(Writer *writer) { if (writer->type == WT_STRING) { free(writer->string.data); } else { #ifdef CFENGINE_TEST CFENGINE_TEST_fclose(writer->file); #else fclose(writer->file); #endif } free(writer); } /*********************************************************************/ char *StringWriterClose(Writer *writer) // NOTE: transfer of ownership for allocated return value { if (writer->type != WT_STRING) { ProgrammingError("Wrong writer type"); } char *data = writer->string.data; free(writer); return data; } FILE *FileWriterDetach(Writer *writer) { if (writer->type != WT_FILE) { ProgrammingError("Wrong writer type"); } FILE *file = writer->file; free(writer); return file; } cfengine-3.6.2/libutils/statistics.c0000664000175100017510000000365112243421446017212 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /**********************************************************************/ double GAverage(double anew, double aold, double p) /* return convex mixture - p is the trust/confidence in the new value */ { return (p * anew + (1.0 - p) * aold); } /* * expected(Q) = p*Q_new + (1-p)*expected(Q) * variance(Q) = p*(Q_new - expected(Q))^2 + (1-p)*variance(Q) */ /**********************************************************************/ QPoint QAverage(QPoint old, double new_q, double p) { QPoint new = { .q = new_q, }; double devsquare = (new.q - old.expect) * (new.q - old.expect); new.dq = new.q - old.q; new.expect = GAverage(new.q, old.expect, p); new.var = GAverage(devsquare, old.var, p); return new; } /**********************************************************************/ QPoint QDefinite(double q) { return (QPoint) { .q = q, .dq = 0.0, .expect = q, .var = 0.0 }; } cfengine-3.6.2/libutils/hashes.c0000664000175100017510000000345112400110676016264 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include int FileChecksum(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1]) { FILE *file = safe_fopen(filename, "rb"); if (!file) { printf("%s can't be opened\n", filename); return 0; } else { const EVP_MD *md = EVP_get_digestbyname("md5"); if (!md) { fclose(file); return 0; } EVP_MD_CTX context; EVP_DigestInit(&context, md); int len = 0; unsigned char buffer[1024]; while ((len = fread(buffer, 1, 1024, file))) { EVP_DigestUpdate(&context, buffer, len); } unsigned int md_len = 0; EVP_DigestFinal(&context, digest, &md_len); fclose(file); return md_len; } } cfengine-3.6.2/libutils/statistics.h0000664000175100017510000000242312243421446017213 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_STATISTICS_H #define CFENGINE_STATISTICS_H typedef struct { double q; double expect; double var; double dq; } QPoint; double GAverage(double anew, double aold, double p); QPoint QAverage(QPoint old_value, double new_value, double p); QPoint QDefinite(double value); #endif cfengine-3.6.2/libutils/xml_writer.h0000664000175100017510000000353212243421446017217 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_XML_WRITER_H #define CFENGINE_XML_WRITER_H #include #include typedef struct { const char *name; const char *value; } XmlAttribute; void XmlComment(Writer *writer, const char *comment); /* INSERT START XML ELEMENT -> */ /* TAKE PARAM attr_cnt, STRUCT XmlAttribute, STRUCT XmlAttribute ... */ void XmlStartTag(Writer *writer, const char *tag_name, int attr_cnt, ...); void XmlEndTag(Writer *writer, const char *tag_name); /* INSERT XML TAG -> value */ /* TAKE PARAM attr_cnt, STRUCT XmlAttribute, STRUCT XmgAttribute ... */ void XmlTag(Writer *writer, const char *tag_name, const char *value, int attr_cnt, ...); /* String content, properly escaped */ void XmlContent(Writer *writer, const char *value); #endif cfengine-3.6.2/libutils/logging.h0000664000175100017510000000450112411001073016431 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LOGGING_H #define CFENGINE_LOGGING_H #include #include // Does not include timezone, since it is hard to match on Windows. #define LOGGING_TIMESTAMP_REGEX "^20[0-9][0-9]-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" typedef enum { LOG_LEVEL_NOTHING = -1, LOG_LEVEL_CRIT, LOG_LEVEL_ERR, LOG_LEVEL_WARNING, LOG_LEVEL_NOTICE, LOG_LEVEL_INFO, LOG_LEVEL_VERBOSE, LOG_LEVEL_DEBUG } LogLevel; const char *LogLevelToString(LogLevel level); /** * @brief Return the standard timestamp format used in logging. * @param dest Output buffer * @param n size of output buffer * @param timestamp Timespec to format * @return True if successful, otherwise "" will be printed to buffer */ bool LoggingFormatTimestamp(char dest[64], size_t n, struct tm *timestamp); void Log(LogLevel level, const char *fmt, ...) FUNC_ATTR_PRINTF(2, 3); void LogRaw(LogLevel level, const char *prefix, const void *buf, size_t buflen); void VLog(LogLevel level, const char *fmt, va_list ap); void LogSetGlobalLevel(LogLevel level); LogLevel LogGetGlobalLevel(void); void LoggingSetColor(bool enabled); /* * Portable syslog() */ void LogToSystemLog(const char *msg, LogLevel level); /* * Portable strerror(errno) */ const char *GetErrorStr(void); const char *GetErrorStrFromCode(int error_code); #endif cfengine-3.6.2/libutils/hash.c0000664000175100017510000002123312411001073015722 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* EVP_* */ #include /* BN_bn2bin */ #include #include #include static const char *const CF_DIGEST_TYPES[10] = { "md5", "sha224", "sha256", "sha384", "sha512", "sha1", "sha", "best", "crypt", NULL }; static const int CF_DIGEST_SIZES[10] = { CF_MD5_LEN, CF_SHA224_LEN, CF_SHA256_LEN, CF_SHA384_LEN, CF_SHA512_LEN, CF_SHA1_LEN, CF_SHA_LEN, CF_BEST_LEN, CF_CRYPT_LEN, CF_NO_HASH }; struct Hash { unsigned char digest[EVP_MAX_MD_SIZE]; char printable[EVP_MAX_MD_SIZE * 4]; HashMethod method; HashSize size; }; /* * These methods are not exported through the public API. * These are internal methods used by the constructors of a * Hash object. Do not export them since they have very little * meaning outside of the constructors. */ Hash *HashBasicInit(HashMethod method) { Hash *hash = xcalloc (1, sizeof(Hash)); hash->size = CF_DIGEST_SIZES[method]; hash->method = method; return hash; } void HashCalculatePrintableRepresentation(Hash *hash) { switch (hash->method) { case HASH_METHOD_MD5: strcpy(hash->printable, "MD5="); break; case HASH_METHOD_SHA224: case HASH_METHOD_SHA256: case HASH_METHOD_SHA384: case HASH_METHOD_SHA512: case HASH_METHOD_SHA: case HASH_METHOD_SHA1: strcpy(hash->printable, "SHA="); break; default: strcpy(hash->printable, "UNK="); break; } unsigned int i; for (i = 0; i < hash->size; i++) { snprintf(hash->printable + 4 + 2 * i, sizeof(hash->printable) - (4 + 2 * i), "%02x", hash->digest[i]); } hash->printable[4 + 2 * hash->size] = '\0'; } /* * Constructors * All constructors call two common methods: HashBasicInit(...) and HashCalculatePrintableRepresentation(...). * Each constructor reads the data to create the Hash from different sources so after the basic * initialization and up to the point where the hash is computed, each follows its own path. */ Hash *HashNew(const char *data, const unsigned int length, HashMethod method) { if (!data || (length == 0)) { return NULL; } if (method >= HASH_METHOD_NONE) { return NULL; } /* * OpenSSL documentation marked EVP_DigestInit and EVP_DigestFinal functions as deprecated and * recommends moving to EVP_DigestInit_ex and EVP_DigestFinal_ex. */ EVP_MD_CTX *context = NULL; const EVP_MD *md = NULL; int md_len = 0; md = EVP_get_digestbyname(CF_DIGEST_TYPES[method]); if (md == NULL) { Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", CF_DIGEST_TYPES[method]); return NULL; } Hash *hash = HashBasicInit(method); context = EVP_MD_CTX_create(); EVP_DigestInit_ex(context, md, NULL); EVP_DigestUpdate(context, data, (size_t) length); EVP_DigestFinal_ex(context, hash->digest, &md_len); EVP_MD_CTX_destroy(context); /* Update the printable representation */ HashCalculatePrintableRepresentation(hash); /* Return the hash */ return hash; } Hash *HashNewFromDescriptor(const int descriptor, HashMethod method) { if (descriptor < 0) { return NULL; } if (method >= HASH_METHOD_NONE) { return NULL; } char buffer[1024]; int read_count = 0; EVP_MD_CTX *context = NULL; const EVP_MD *md = NULL; int md_len = 0; md = EVP_get_digestbyname(CF_DIGEST_TYPES[method]); if (md == NULL) { Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", CF_DIGEST_TYPES[method]); return NULL; } Hash *hash = HashBasicInit(method); context = EVP_MD_CTX_create(); EVP_DigestInit_ex(context, md, NULL); do { read_count = read(descriptor, buffer, 1024); EVP_DigestUpdate(context, buffer, (size_t) read_count); } while (read_count > 0); EVP_DigestFinal_ex(context, hash->digest, &md_len); EVP_MD_CTX_destroy(context); /* Update the printable representation */ HashCalculatePrintableRepresentation(hash); /* Return the hash */ return hash; } Hash *HashNewFromKey(const RSA *rsa, HashMethod method) { if (!rsa) { return NULL; } if (method >= HASH_METHOD_NONE) { return NULL; } EVP_MD_CTX *context = NULL; const EVP_MD *md = NULL; int md_len = 0; unsigned char *buffer = NULL; int buffer_length = 0; int actual_length = 0; if (rsa->n) { buffer_length = (size_t) BN_num_bytes(rsa->n); } else { buffer_length = 0; } if (rsa->e) { if (buffer_length < (size_t) BN_num_bytes(rsa->e)) { buffer_length = (size_t) BN_num_bytes(rsa->e); } } md = EVP_get_digestbyname(CF_DIGEST_TYPES[method]); if (md == NULL) { Log(LOG_LEVEL_INFO, "Digest type %s not supported by OpenSSL library", CF_DIGEST_TYPES[method]); return NULL; } Hash *hash = HashBasicInit(method); context = EVP_MD_CTX_create(); EVP_DigestInit_ex(context, md, NULL); buffer = xmalloc(buffer_length); actual_length = BN_bn2bin(rsa->n, buffer); EVP_DigestUpdate(context, buffer, actual_length); actual_length = BN_bn2bin(rsa->e, buffer); EVP_DigestUpdate(context, buffer, actual_length); EVP_DigestFinal_ex(context, hash->digest, &md_len); EVP_MD_CTX_destroy(context); free (buffer); /* Update the printable representation */ HashCalculatePrintableRepresentation(hash); /* Return the hash */ return hash; } void HashDestroy(Hash **hash) { if (!hash || !*hash) { return; } free (*hash); *hash = NULL; } int HashCopy(Hash *origin, Hash **destination) { if (!origin || !destination) { return -1; } *destination = xmalloc(sizeof(Hash)); memcpy((*destination)->digest, origin->digest, origin->size); strlcpy((*destination)->printable, origin->printable, (EVP_MAX_MD_SIZE * 4)); (*destination)->method = origin->method; (*destination)->size = origin->size; return 0; } int HashEqual(const Hash *a, const Hash *b) { if (!a && !b) { return true; } if (!a && b) { return false; } if (a && !b) { return false; } if (a->method != b->method) { return false; } int i = 0; for (i = 0; i < a->size; ++i) { if (a->digest[i] != b->digest[i]) { return false; } } return true; } const unsigned char *HashData(const Hash *hash, unsigned int *length) { if (!hash || !length) { return NULL; } *length = hash->size; return hash->digest; } const char *HashPrintable(const Hash *hash) { return hash ? hash->printable : NULL; } HashMethod HashType(const Hash *hash) { return hash ? hash->method : HASH_METHOD_NONE; } HashSize HashLength(const Hash *hash) { return hash ? hash->size : CF_NO_HASH; } /* Class methods */ HashMethod HashIdFromName(const char *hash_name) { int i; for (i = 0; CF_DIGEST_TYPES[i] != NULL; i++) { if (hash_name && (strcmp(hash_name, CF_DIGEST_TYPES[i]) == 0)) { return (HashMethod) i; } } return HASH_METHOD_NONE; } const char *HashNameFromId(HashMethod hash_id) { return (hash_id >= HASH_METHOD_NONE) ? NULL : CF_DIGEST_TYPES[hash_id]; } HashSize HashSizeFromId(HashMethod hash_id) { return (hash_id >= HASH_METHOD_NONE) ? CF_NO_HASH : CF_DIGEST_SIZES[hash_id]; } cfengine-3.6.2/libutils/printsize.h0000644000175100017510000000610412332665147017055 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PRINTSIZE_H #define CFENGINE_PRINTSIZE_H /** Size of buffer needed to sprintf() an integral value. * * The constant 53/22 is a (very slightly) high approximation to * log(256)/log(10), the number of decimal digits needed per byte of * the value. The offset of 3 accounts for: rounding details, the * '\0' you need at the end of the buffer and the sign. The last is a * wasted byte when using "%u", but it's simpler this way ! * * This macro should be preferred over using a char [64] buffer (or * 128 or 32 or whatever guess you've made at "big enough") and * trusting that your integer shall fit - for now it saves wasting * stack space; one day it may even (when we have bigger integral * types) save us a buffer over-run. Limitation: if CHAR_BIT ever * isn't 8, we should change the / 22 to * CHAR_BIT / 176. * * This deals with the simple case of a "%d", possibly with type * modifiers (jhzl, etc.) or sign (%+d). If you're using fancier * modifiers (e.g. field-width), you need to think about what effect * they have on the print width (max of field-width and this macro); * if there is other text in your format, you need to allow space for * it, too. * * If you are casting the value to be formatted (e.g. because there's * no modifier for its type), applying this macro to the value shall * get the maximum size that a %d-based format can produce for it (its * value can't be any bigger, even if it's cast to a huge type); but, * if you're using a %u-based format and the value is signed, you * should call this macro on the type to which you're casting it * (because, if it's negative, it'll wrap to a huge value of the cast * type). * * @param #what The integral expression or its type. Is not evaluated * at run-time, only passed to sizeof() at compile-time. * * @return The size for a buffer big enough to hold sprintf()'s * representation of an integer of this type. This is a compile-time * constant, so can be used in static array declarations or struct * member array declarations. */ #define PRINTSIZE(what) (3 + 53 * sizeof(what) / 22) #endif /* CFENGINE_PRINTSIZE_H */ cfengine-3.6.2/libutils/sequence.c0000644000175100017510000001635412352557236016642 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static const size_t EXPAND_FACTOR = 2; Seq *SeqNew(size_t initialCapacity, void (ItemDestroy) (void *item)) { Seq *seq = xmalloc(sizeof(Seq)); if (initialCapacity <= 0) { initialCapacity = 1; } seq->capacity = initialCapacity; seq->length = 0; seq->data = xcalloc(sizeof(void *), initialCapacity); seq->ItemDestroy = ItemDestroy; return seq; } static void DestroyRange(Seq *seq, size_t start, size_t end) { if (seq->ItemDestroy) { for (size_t i = start; i <= end; i++) { seq->ItemDestroy(seq->data[i]); } } } void SeqDestroy(Seq *seq) { if (seq && seq->length > 0) { DestroyRange(seq, 0, seq->length - 1); } SeqSoftDestroy(seq); } void SeqSoftDestroy(Seq *seq) { if (seq) { free(seq->data); free(seq); } } static void ExpandIfNeccessary(Seq *seq) { assert(seq->length <= seq->capacity); if (seq->length == seq->capacity) { seq->capacity *= EXPAND_FACTOR; seq->data = xrealloc(seq->data, sizeof(void *) * seq->capacity); } } void SeqSet(Seq *seq, size_t index, void *item) { assert(index < SeqLength(seq)); if (seq->ItemDestroy) { seq->ItemDestroy(seq->data[index]); } seq->data[index] = item; } void SeqAppend(Seq *seq, void *item) { ExpandIfNeccessary(seq); seq->data[seq->length] = item; ++(seq->length); } void SeqAppendSeq(Seq *seq, const Seq *items) { for (size_t i = 0; i < SeqLength(items); i++) { SeqAppend(seq, SeqAt(items, i)); } } void SeqRemoveRange(Seq *seq, size_t start, size_t end) { assert(seq); assert(start >= 0); assert(end < seq->length); assert(start <= end); DestroyRange(seq, start, end); size_t rest_len = seq->length - end - 1; if (rest_len > 0) { memmove(seq->data + start, seq->data + end + 1, sizeof(void *) * rest_len); } seq->length -= end - start + 1; } void SeqRemove(Seq *seq, size_t index) { SeqRemoveRange(seq, index, index); } void *SeqLookup(Seq *seq, const void *key, SeqItemComparator Compare) { for (size_t i = 0; i < seq->length; i++) { if (Compare(key, seq->data[i], NULL) == 0) { return seq->data[i]; } } return NULL; } void *SeqBinaryLookup(Seq *seq, const void *key, SeqItemComparator Compare) { ssize_t index = SeqBinaryIndexOf(seq, key, Compare); if (index == -1) { return NULL; } else { return seq->data[index]; } } ssize_t SeqIndexOf(Seq *seq, const void *key, SeqItemComparator Compare) { for (size_t i = 0; i < seq->length; i++) { if (Compare(key, seq->data[i], NULL) == 0) { return i; } } return -1; } ssize_t SeqBinaryIndexOf(Seq *seq, const void *key, SeqItemComparator Compare) { if (seq->length == 0) { return -1; } size_t low = 0; size_t high = seq->length; while (low < high) { // Invariant: low <= middle < high size_t middle = low + ((high - low) >> 1); // ">> 1" is division by 2. int result = Compare(key, seq->data[middle], NULL); if (result == 0) { return middle; } if (result > 0) { low = middle + 1; } else { high = middle; } } // Not found. return -1; } static void Swap(void **l, void **r) { void *t = *l; *l = *r; *r = t; } // adopted from http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#C static void QuickSortRecursive(void **data, int n, SeqItemComparator Compare, void *user_data, size_t maxterm) { assert(maxterm < 1000); if (n < 2) { return; } void *pivot = data[n / 2]; void **l = data; void **r = data + n - 1; while (l <= r) { while (Compare(*l, pivot, user_data) < 0) { ++l; } while (Compare(*r, pivot, user_data) > 0) { --r; } if (l <= r) { Swap(l, r); ++l; --r; } } QuickSortRecursive(data, r - data + 1, Compare, user_data, maxterm + 1); QuickSortRecursive(l, data + n - l, Compare, user_data, maxterm + 1); } void SeqSort(Seq *seq, SeqItemComparator Compare, void *user_data) { QuickSortRecursive(seq->data, seq->length, Compare, user_data, 0); } Seq *SeqSoftSort(const Seq *seq, SeqItemComparator compare, void *user_data) { size_t length = SeqLength(seq); if (length == 0) { return SeqNew(0, NULL); } Seq *sorted_seq = SeqGetRange(seq, 0, length - 1); SeqSort(sorted_seq, compare, user_data); return sorted_seq; } void SeqSoftRemoveRange(Seq *seq, size_t start, size_t end) { assert(seq); assert(start >= 0); assert(end < seq->length); assert(start <= end); size_t rest_len = seq->length - end - 1; if (rest_len > 0) { memmove(seq->data + start, seq->data + end + 1, sizeof(void *) * rest_len); } seq->length -= end - start + 1; } void SeqClear(Seq *seq) { if (SeqLength(seq) > 0) { SeqRemoveRange(seq, 0, SeqLength(seq) - 1); } } void SeqSoftRemove(Seq *seq, size_t index) { SeqSoftRemoveRange(seq, index, index); } void SeqReverse(Seq *seq) { for (size_t i = 0; i < (seq->length / 2); i++) { Swap(&seq->data[i], &seq->data[seq->length - 1 - i]); } } size_t SeqLength(const Seq *seq) { assert(seq); return seq->length; } void SeqShuffle(Seq *seq, unsigned int seed) { /* Store current random number state for being reset at the end of function */ int rand_state = rand(); srand(seed); for (size_t i = SeqLength(seq) - 1; i > 0; i--) { size_t j = rand() % (i + 1); Swap(seq->data + i, seq->data + j); } /* Restore previous random number state */ srand(rand_state); } Seq *SeqGetRange(const Seq *seq, size_t start, size_t end) { assert (seq); if ((start > end) || (seq->length < start) || (seq->length < end)) { return NULL; } Seq *sub = SeqNew(end - start + 1, seq->ItemDestroy); for (size_t i = start; i <= end; i++) { SeqAppend(sub, SeqAt(seq, i)); } return sub; } cfengine-3.6.2/libutils/bool.h0000664000175100017510000000247012243421446015756 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_BOOL_H #define CFENGINE_BOOL_H #include #ifdef HAVE_STDBOOL_H # include #else # ifndef HAVE__BOOL # ifdef __cplusplus typedef bool _Bool; # else # define _Bool signed char # endif # endif # define bool _Bool # define false 0 # define true 1 # define __bool_true_false_are_defined 1 #endif #endif cfengine-3.6.2/libutils/rb-tree.h0000664000175100017510000000265512411001073016353 0ustar00a10038a1003800000000000000#ifndef CFENGINE_RB_TREE_H #define CFENGINE_RB_TREE_H #include typedef struct RBTree_ RBTree; typedef struct RBTreeIterator_ RBTreeIterator; typedef void *RBTreeKeyCopyFn(const void *key); typedef int RBTreeKeyCompareFn(const void *a, const void *b); typedef void RBTreeKeyDestroyFn(void *key); typedef void *RBTreeValueCopyFn(const void *key); typedef int RBTreeValueCompareFn(const void *a, const void *b); typedef void RBTreeValueDestroyFn(void *key); typedef bool RBTreePredicate(const void *key, const void *value, void *user_data); RBTree *RBTreeNew(RBTreeKeyCopyFn *key_copy, RBTreeKeyCompareFn *key_compare, RBTreeKeyDestroyFn *key_destroy, RBTreeValueCopyFn *value_copy, RBTreeValueCompareFn *value_compare, RBTreeValueDestroyFn *value_destroy); RBTree *RBTreeCopy(const RBTree *tree, RBTreePredicate *filter, void *user_data); bool RBTreeEqual(const void *a, const void *b); void RBTreeDestroy(void *rb_tree); bool RBTreePut(RBTree *tree, const void *key, const void *value); void *RBTreeGet(const RBTree *tree, const void *key); bool RBTreeRemove(RBTree *tree, const void *key); void RBTreeClear(RBTree *tree); size_t RBTreeSize(const RBTree *tree); RBTreeIterator *RBTreeIteratorNew(const RBTree *tree); bool RBTreeIteratorNext(RBTreeIterator *iter, void **key, void **value); void RBTreeIteratorDestroy(void *_rb_iter); #endif cfengine-3.6.2/libutils/encode.c0000664000175100017510000000364412400110676016252 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* BUF_MEM */ #include /* BIO_* */ #include /* BIO_f_base64 */ #include char *StringEncodeBase64(const char *str, size_t len) { assert(str); if (!str) { return NULL; } if (len == 0) { return xcalloc(1, sizeof(char)); } BIO *b64 = BIO_new(BIO_f_base64()); BIO *bio = BIO_new(BIO_s_mem()); b64 = BIO_push(b64, bio); BIO_write(b64, str, len); if (!BIO_flush(b64)) { assert(false && "Unable to encode string to base64" && str); return NULL; } BUF_MEM *buffer = NULL; BIO_get_mem_ptr(b64, &buffer); char *out = xcalloc(1, buffer->length); memcpy(out, buffer->data, buffer->length - 1); out[buffer->length - 1] = '\0'; BIO_free_all(b64); return out; } cfengine-3.6.2/libutils/file_lib.h0000644000175100017510000000713612352557236016602 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_FILE_LIB_H #define CFENGINE_FILE_LIB_H #include #include typedef enum { NewLineMode_Unix, // LF everywhere NewLineMode_Native // CRLF on Windows, LF elsewhere } NewLineMode; /** * Reads up to size_max bytes from filename and returns a Writer. */ Writer *FileRead(const char *filename, size_t size_max, bool *truncated); /** * Reads up to size_max bytes from fd and returns a Writer. */ Writer *FileReadFromFd(int fd, size_t size_max, bool *truncated); bool FileCanOpen(const char *path, const char *modes); /* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted. Return LEN upon success, write's (negative) error code otherwise. */ int FullWrite(int desc, const char *ptr, size_t len); /* Read up to LEN bytes (or EOF) to PTR from descriptor DESC, retrying if interrupted. Return amount of bytes read upon success, -1 otherwise */ int FullRead(int desc, char *ptr, size_t len); int IsDirReal(const char *path); /** * Returns what type of line endings the file is using. * * @param file File to check. * @return Always returns NewLineMode_Unix on Unix. On Windows it may return * NewLineMode_Native if the file has CRLF line endings. * If the file cannot be opened, or the line endings are mixed it will * return NewLineMode_Native. Note that only the first CF_BUFSIZE bytes * are checked. */ NewLineMode FileNewLineMode(const char *file); /* File node separator (cygwin can use \ or / but prefer \ for communicating * with native windows commands). */ #ifdef _WIN32 # define IsFileSep(c) ((c) == '\\' || (c) == '/') # define FILE_SEPARATOR '\\' # define FILE_SEPARATOR_STR "\\" #else # define IsFileSep(c) ((c) == '/') # define FILE_SEPARATOR '/' # define FILE_SEPARATOR_STR "/" #endif bool IsAbsoluteFileName(const char *f); char *MapName(char *s); char *MapNameCopy(const char *s); char *MapNameForward(char *s); int safe_open(const char *pathname, int flags, ...); FILE *safe_fopen(const char *path, const char *mode); int safe_chdir(const char *path); int safe_chown(const char *path, uid_t owner, gid_t group); int safe_chmod(const char *path, mode_t mode); #ifndef __MINGW32__ int safe_lchown(const char *path, uid_t owner, gid_t group); #endif int safe_creat(const char *pathname, mode_t mode); /** * @brief Deletes directory path recursively. Symlinks are not followed. * Note that this function only deletes the contents of the directory, not the directory itself. * @param path * @return true if directory was deleted successfully, false if one or more files were not deleted. */ bool DeleteDirectoryTree(const char *path); #endif cfengine-3.6.2/libutils/csv_writer.c0000644000175100017510000000675312316547775017232 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include struct CsvWriter_ { Writer *w; bool beginning_of_line; }; /*****************************************************************************/ static void WriteCsvEscapedString(Writer *w, const char *str); static void CsvWriterFieldVF(CsvWriter * csvw, const char *fmt, va_list ap) FUNC_ATTR_PRINTF(2, 0); /*****************************************************************************/ CsvWriter *CsvWriterOpen(Writer *w) { CsvWriter *csvw = xmalloc(sizeof(CsvWriter)); csvw->w = w; csvw->beginning_of_line = true; return csvw; } /*****************************************************************************/ void CsvWriterField(CsvWriter * csvw, const char *str) { if (csvw->beginning_of_line) { csvw->beginning_of_line = false; } else { WriterWriteChar(csvw->w, ','); } if (strpbrk(str, "\",\r\n")) { WriteCsvEscapedString(csvw->w, str); } else { WriterWrite(csvw->w, str); } } /*****************************************************************************/ void CsvWriterFieldF(CsvWriter * csvw, const char *fmt, ...) { va_list ap; va_start(ap, fmt); CsvWriterFieldVF(csvw, fmt, ap); va_end(ap); } /*****************************************************************************/ void CsvWriterNewRecord(CsvWriter * csvw) { WriterWrite(csvw->w, "\r\n"); csvw->beginning_of_line = true; } /*****************************************************************************/ void CsvWriterClose(CsvWriter * csvw) { if (!csvw->beginning_of_line) { WriterWrite(csvw->w, "\r\n"); } free(csvw); } /*****************************************************************************/ static void CsvWriterFieldVF(CsvWriter * csvw, const char *fmt, va_list ap) { /* * We are unable to avoid allocating memory here, as we need full string * contents before deciding whether there is a " in string, and hence whether * the field needs to be escaped in CSV */ char *str; xvasprintf(&str, fmt, ap); CsvWriterField(csvw, str); free(str); } /*****************************************************************************/ static void WriteCsvEscapedString(Writer *w, const char *s) { WriterWriteChar(w, '"'); while (*s) { if (*s == '"') { WriterWriteChar(w, '"'); } WriterWriteChar(w, *s); s++; } WriterWriteChar(w, '"'); } Writer *CsvWriterGetWriter(CsvWriter *csvw) { return csvw->w; } cfengine-3.6.2/libutils/list.h0000664000175100017510000003315612243421446016003 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LIST_H #define CFENGINE_LIST_H #include #include /** @brief Double linked list implementation. A linked list is to be used when data needs to be stored and then sequentially processed, not for quick lookups. Prime examples of bad usage of a linked list is for instance having a list of files and then iterating over the list to find a particular file based on the name. A Map will be much better for this type of usage. A good usage for a linked list is to store a list of files that need to be changed sequentially. For instance a list of files that need to change permissions. A linked list should not be used when fast retrieval is important, for that it is better to use a Map. The implementation of the list is kept intentionally opaque, so we can change it in the future. It provides a reference counted list with copy on write. In order for this to work the user needs to provide at least a copy function. The List is used at its full potential if the user provides three helper functions: - copy(void *source, void **destination) - compare(void *a, void *b) - destroy(void *element) It is highly recommend to at least implement the copy function, since that is the key for the copy on write implementation. The destroy function is recommended to avoid leaking memory whenever an element is destroyed. Notice that the list never copies the elements, so as long as the user still has access to the elements this function does not need to be implemented and the user then needs to delete the elements afterwards. The compare function is a nice to have function. It is used when the user wants to remove elements, in order to find the right element to delete. If this function is not provided, then the list will try to match the pointer. These three helper functions can assume that they will never be called with NULL pointers. A special note on the copy function. The copy function is analog to the copy constructor in C++, it takes a properly constructed element and produces a newly created element that is a copy of the previous one. The copy function needs to allocate memory for the new element and then fill it with the proper data. It should be avoid moving pointers around, it should copy the content to the new element so the new element is not tied to the previous element. The list can have many iterators, but only one mutable iterator at any given time. The difference between a normal iterator and a mutable iterator is the fact that with normal iterators only additions can be performed to the list without invalidating the iterator, while the mutable iterator allows any kind of change. Be aware that removing from the list, either by using remove or via the mutable iterator will invalidate all the normal iterators. Simple way to iterate over the list: ListIterator *i = ListIteratorGet(list); int r = 0; for (r = ListIteratorFirst(i); r == 0; r = ListIteratorNext(i)) { MyData = ListIteratorData(i); ... Do something with the data. ... } */ typedef struct List List; typedef struct ListMutableIterator ListMutableIterator; typedef struct ListIterator ListIterator; /** @brief Initialization of a linked list. @param compare Compare functions for the elements of the list. Same semantic as strcmp. @param copy Copies one element into a new element. @param destroy Destroys an element. @return A fully initialized list ready to be used or -1 in case of error. */ List *ListNew(int (*compare)(const void *, const void *), void (*copy)(const void *source, void **destination), void (*destroy)(void *)); /** @brief Destroy a linked list. @param list List to be destroyed. It can be a NULL pointer. @return 0 if destroyed, -1 otherwise. */ int ListDestroy(List **list); /** @brief Performs a shallow copy of a linked list. A shallow copy is a copy that does not copy the elements but only the list structure. This is done by internal reference counting. If any of the lists is modified afterwards then a deep copy of the list is triggered and all the elements are copied. @param origin Original list to be copied. @param destination List to be copied to. @return 0 if copied, -1 otherwise. @remark If no copy function is provided, then this function returns -1. */ int ListCopy(List *origin, List **destination); /** @brief Adds an element to the beginning of the list. Notice that we do not copy the element, so if the original element is free'd there will be a dangling pointer. We used to change the state of the list after adding an element, but now we don't do it. The reason is because adding an element is not destructive, no iterators will be affected by this, while removing it is destructive. An iterator might be pointing to the dark side of the moon after a removal operation. If the list is shared this will trigger a deep copy of the list. @param list Linked list. @param payload Data to be added. @return 0 if prepended, -1 otherwise. */ int ListPrepend(List *list, void *payload); /** @brief Adds an element to the end of the list. Notice that we do not copy the element, so if the original element is free'd there will be a dangling pointer. We used to change the state of the list after adding an element, but now we don't do it. The reason is because adding an element is not destructive, no iterators will be affected by this, while removing it is destructive. An iterator might be pointing to the dark side of the moon after a removal operation. If the list is shared this will trigger a deep copy of the list. @param list Linked list. @param payload Data to be added. @return 0 if appended, -1 otherwise. */ int ListAppend(List *list, void *payload); /** @brief Removes an element from the linked list. Removes the first element that matches the payload. It starts looking from the beginning of the list. Notice that this might trigger a deep copy of the list. This only happens if the list was copied before. @param list Linked list. @param payload Data to be removed. @return 0 if removed, -1 otherwise. */ int ListRemove(List *list, void *payload); /** @brief Returns the number of elements on a given linked list. @param list Linked list. @return The number of elements on the list. */ int ListCount(const List *list); /** @brief Gets an iterator for a given linked list. This iterator will be invalid if data is removed from the list. It will still be valid after a new addition though. @note After creation the iterator will be pointing to the first item of the list. @param list Linked list @param iterator Iterator. @return A fully initialized iterator or NULL in case of error. */ ListIterator *ListIteratorGet(const List *list); /** @brief Releases the memory associated with an iterator. This function exists only to free the memory associated with the iterator, there is no strong connection between the iterator and the list. @note It is not possible to get an iterator for an empty list. @param iterator Iterator. @return 0 if released, -1 otherwise. */ int ListIteratorDestroy(ListIterator **iterator); /** @brief Moves the iterator to the first element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListIteratorFirst(ListIterator *iterator); /** @brief Moves the iterator to the last element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListIteratorLast(ListIterator *iterator); /** @brief Moves the iterator to the next element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListIteratorNext(ListIterator *iterator); /** @brief Moves the iterator to the previous element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListIteratorPrevious(ListIterator *iterator); /** @brief Returns the data associated with the current element. @param iterator Iterator. @return Pointer to the data or NULL if it was not possible. */ void *ListIteratorData(const ListIterator *iterator); /** @brief Checks if the iterator has a next element @return True if it has a next element or False if not. */ bool ListIteratorHasNext(const ListIterator *iterator); /** @brief Checks if the iterator has a previous element @return True if it has a previous element or False if not. */ bool ListIteratorHasPrevious(const ListIterator *iterator); /** @brief Creates a new mutable iterator. A mutable iterator can be used for the same kind of operations as a normal iterator, but it can also be used to add and remove elements while iterating over the list. Any removal operation will invalidate all the normal iterators though. Since there can be only one mutable iterator for a list at any given time, the creation of a second iterator will fail. @note After creation the iterator will be pointing to the first item of the list. @param iterator Iterator to be initialized. @return A fully initialized iterator or NULL in case of error. */ ListMutableIterator *ListMutableIteratorGet(List *list); /** @brief Releases the memory associated with an iterator. This function has to be called for mutable iterators, otherwise the list will think there is already one mutable iterator and the creation of new mutable iterators will not be possible. @note It is not possible to get an iterator for an empty list. @param iterator Iterator. @return 0 if released, -1 otherwise. */ int ListMutableIteratorRelease(ListMutableIterator **iterator); /** @brief Moves the iterator to the first element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListMutableIteratorFirst(ListMutableIterator *iterator); /** @brief Moves the iterator to the last element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListMutableIteratorLast(ListMutableIterator *iterator); /** @brief Moves the iterator to the next element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListMutableIteratorNext(ListMutableIterator *iterator); /** @brief Moves the iterator to the previous element of the list. @param iterator Iterator. @return 0 if it was possible to move, -1 otherwise. */ int ListMutableIteratorPrevious(ListMutableIterator *iterator); /** @brief Returns the data associated with the current element. @param iterator Iterator. @return Pointer to the data or NULL if it was not possible. */ void *ListMutableIteratorData(const ListMutableIterator *iterator); /** @brief Removes the current element from the list. After this operation all the normal iterators are invalid. The iterator might be pointing to the next element, or in the case of removing the last element, to the previous element. Although it is supported to remove elements from the list bypassing the iterator, i.e. calling ListRemove, this might bring unintended side effects. The iterator might be moved to another element, therefore special care must be taken when mixing removal both from the list and from the iterator. @param iterator Iterator @return 0 if removed, -1 otherwise. */ int ListMutableIteratorRemove(ListMutableIterator *iterator); /** @brief Prepends element on front of the element pointed by the iterator. An important clarification, the iterator still points to the same element after this operation. It is up to the user to move the iterator to the prepended element. All the light operators are still valid after this operation. @param iterator Iterator @param payload Element to be prepended. @return 0 if prepended, -1 in case of error. */ int ListMutableIteratorPrepend(ListMutableIterator *iterator, void *payload); /** @brief Appends element after the element pointed by the iterator. An important clarification, the iterator still points to the same element after this operation. It is up to the user to move the iterator to the appended element. All the light operators are still valid after this operation. @param iterator Iterator @param payload Element to be appended. @return 0 if appended, -1 in case of error. */ int ListMutableIteratorAppend(ListMutableIterator *iterator, void *payload); /** @brief Checks if the iterator has a next element @return True if it has a next element or False if not. */ bool ListMutableIteratorHasNext(const ListMutableIterator *iterator); /** @brief Checks if the iterator has a previous element @return True if it has a previous element or False if not. */ bool ListMutableIteratorHasPrevious(const ListMutableIterator *iterator); #endif // CFENGINE_LIST_H cfengine-3.6.2/libutils/buffer.h0000664000175100017510000002066612411001073016266 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_BUFFER_H #define CFENGINE_BUFFER_H #include #include /** @brief Buffer implementation The buffer structure acts as a byte container. It can contains any bytes and it is not restricted to C strings (by default it acts as a C String). If an error arises while doing something, we do everything we can to restore things to its previous state. Unfortunately not all errors are recoverable. Since we do not have a proper errno system, we just return -1. For security reasons, there is a memory cap on each buffer. At creation time each buffer gets assigned a certain amount of memory, can be checked via BufferGeneralMemoryCap(). This general cap can be raised or lowered by calling BufferSetGeneralMemoryCap(unsigned int cap). After changing the cap, only newly allocated buffers will have the new cap as default, all the previous buffers will have the old cap. This can be changed on a per instance basis. */ typedef enum { BUFFER_BEHAVIOR_CSTRING // buffer2 */ int BufferCompare(const Buffer *buffer1, const Buffer *buffer2); /** @brief Replaces the current content of the buffer with the given string. In CString mode the content of bytes is copied until length bytes have been copied or a '\0' is found, whatever happens first. In ByteArray mode length bytes are copied regardless of if there are '\0' or not. @note The content of the buffer are overwritten with the new content, it is not possible to access them afterwards. @note For complex data it is preferable to use Printf since that will make sure that all data is represented properly. @note The data will be preserved if this operation fails, although it might be in a detached state. @param buffer Buffer to be used. @param bytes Collection of bytes to be copied into the buffer. @param length Length of the collection of bytes. */ void BufferSet(Buffer *buffer, const char *bytes, unsigned int length); char *BufferGet(Buffer *buffer); void BufferAppend(Buffer *buffer, const char *bytes, unsigned int length); void BufferAppendChar(Buffer *buffer, char byte); void BufferAppendF(Buffer *buffer, const char *format, ...); void BufferAppendString(Buffer *buffer, const char *str); /** @brief Stores complex data on the buffer. This function uses the same semantic and flags as printf. Internally it might or not call sprintf, so do not depend on obscure sprintf/printf behaviors. @note This function can be used both in CString mode and in ByteArray mode. The only difference is the presence of the final '\0' character. @note The data will be preserved if this operation fails, although it might be in a detached state. @param buffer @param format @return The number of bytes written to the buffer or 0 if the operation needs to be retried. In case of error -1 is returned. */ int BufferPrintf(Buffer *buffer, const char *format, ...) FUNC_ATTR_PRINTF(2, 3); /** @brief Stores complex data on the buffer. This function uses the same semantic and flags as printf. Internally it might or not call sprintf, so do not depend on obscure sprintf/printf behaviors. This function uses a va_list instead of variable arguments. @note This function can be used both in CString mode and in ByteArray mode. The only difference is the presence of the final '\0' character. @note The data will be preserved if this operation fails, although it might be in a detached state. @param buffer @param format @return The number of bytes written to the buffer or 0 if the operation needs to be retried. In case of error -1 is returned. */ int BufferVPrintf(Buffer *buffer, const char *format, va_list ap); /** @brief Clears the buffer. Clearing the buffer does not mean destroying the data. The data might be still present after this function is called, although it might not be accessible. This function never fails. If a NULL pointer is given it will politely ignore the call. @note This function might trigger a deep copy and a memory allocation if the buffer is shared. @param buffer Buffer to clear. */ void BufferClear(Buffer *buffer); /** @brief Returns the size of the buffer. @param buffer @return The size of the buffer, that is the number of bytes contained on it. */ unsigned int BufferSize(Buffer *buffer); void BufferSetCapacity(Buffer *buffer, unsigned int capacity); unsigned BufferCapacity(const Buffer *buffer); /** @brief Returns the current mode of operation of the buffer. @param buffer The buffer to operate on. @return The current mode of operation. */ BufferBehavior BufferMode(Buffer *buffer); /** @brief Sets the operational mode of the buffer. Although there are no problems changing the operational mode once the buffer is in use, there might be some obscure side effects. The data will not be changed but the interpretation of it will, therefore it might be possible that some data is lost when switching from ByteArray mode to CString mode, since '\0' are allowed in ByteArray mode but not in CString mode. @param buffer The buffer to operate on. @param mode The new mode of operation. */ void BufferSetMode(Buffer *buffer, BufferBehavior mode); /** @brief Provides a pointer to the internal data. This is a const pointer and it is not supposed to be used to write data to the buffer, doing so will lead to undefined behavior and most likely segmentation faults. Use the proper functions to write data to the buffer. @param buffer @return A const char pointer to the data contained on the buffer. */ const char *BufferData(Buffer *buffer); #endif cfengine-3.6.2/libutils/unicode.c0000644000175100017510000000323712352022221016431 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include void ConvertFromCharToWChar(int16_t *dst, const char *src, size_t size) { int c; size--; // Room for '\0'. for (c = 0; src[c] && c < size; c++) { dst[c] = (int16_t)src[c]; } dst[c] = '\0'; } bool ConvertFromWCharToChar(char *dst, const int16_t *src, size_t size) { bool clean = true; int c; size--; // Room for '\0'. for (c = 0; src[c] && c < size; c++) { // We only consider unsigned values. if (src[c] < 0 || src[c] >= 0x100) { clean = false; dst[c] = '_'; } else { dst[c] = (char)src[c]; } } dst[c] = '\0'; return clean; } cfengine-3.6.2/libutils/config.h.in0000664000175100017510000007112312412324527016676 0ustar00a10038a1003800000000000000/* libutils/config.h.in. Generated from configure.ac by autoheader. */ /* Absolute path of source tree */ #undef ABS_TOP_SRCDIR /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Special CFEngine symbol */ #undef AUTOCONF_HOSTNAME /* Speial CFEngine symbol */ #undef AUTOCONF_SYSNAME /* "Software build year" */ #undef BUILD_YEAR /* Define if you want builtin Enterprise extensions */ #undef BUILTIN_EXTENSIONS /* Path to chpasswd tool */ #undef CHPASSWD /* Define to 1 if using `getloadavg.c'. */ #undef C_GETLOADAVG /* Define to 1 for DGUX with . */ #undef DGUX /* Whether endnetgrent returns int */ #undef ENDNETGRENT_RETURNS_INT /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ #undef GETLOADAVG_PRIVILEGED /* Define to 1 if you have the header file. */ #undef HAVE_ACL_H /* Define to 1 if you have the header file. */ #undef HAVE_ACL_LIBACL_H /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_ATTR_XATTR_H /* Define to 1 if you have the header file. */ #undef HAVE_AVAHI_CLIENT_CLIENT_H /* Define to 1 if you have the header file. */ #undef HAVE_AVAHI_COMMON_ADDRESS_H /* Define to 1 if you have the `chflags' function. */ #undef HAVE_CHFLAGS /* Define if chpasswd tool is present */ #undef HAVE_CHPASSWD /* Define to 1 if the system has the type `clockid_t'. */ #undef HAVE_CLOCKID_T /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the declaration of `alarm', and to 0 if you don't. */ #undef HAVE_DECL_ALARM /* Define to 1 if you have the declaration of `chmod', and to 0 if you don't. */ #undef HAVE_DECL_CHMOD /* Define to 1 if you have the declaration of `chown', and to 0 if you don't. */ #undef HAVE_DECL_CHOWN /* Define to 1 if you have the declaration of `clock_gettime', and to 0 if you don't. */ #undef HAVE_DECL_CLOCK_GETTIME /* Define to 1 if you have the declaration of `dirfd', and to 0 if you don't. */ #undef HAVE_DECL_DIRFD /* Define to 1 if you have the declaration of `drand48', and to 0 if you don't. */ #undef HAVE_DECL_DRAND48 /* Define to 1 if you have the declaration of `endnetgrent', and to 0 if you don't. */ #undef HAVE_DECL_ENDNETGRENT /* Define to 1 if you have the declaration of `fchownat', and to 0 if you don't. */ #undef HAVE_DECL_FCHOWNAT /* Define to 1 if you have the declaration of `fgetgrent', and to 0 if you don't. */ #undef HAVE_DECL_FGETGRENT /* Define to 1 if you have the declaration of `fstatat', and to 0 if you don't. */ #undef HAVE_DECL_FSTATAT /* Define to 1 if you have the declaration of `fsync', and to 0 if you don't. */ #undef HAVE_DECL_FSYNC /* Define to 1 if you have the declaration of `getaddrinfo', and to 0 if you don't. */ #undef HAVE_DECL_GETADDRINFO /* Define to 1 if you have the declaration of `getgid', and to 0 if you don't. */ #undef HAVE_DECL_GETGID /* Define to 1 if you have the declaration of `getline', and to 0 if you don't. */ #undef HAVE_DECL_GETLINE /* Define to 1 if you have the declaration of `getloadavg', and to 0 if you don't. */ #undef HAVE_DECL_GETLOADAVG /* Define to 1 if you have the declaration of `getnetgrent', and to 0 if you don't. */ #undef HAVE_DECL_GETNETGRENT /* Define to 1 if you have the declaration of `getuid', and to 0 if you don't. */ #undef HAVE_DECL_GETUID /* Define to 1 if you have the declaration of `glob', and to 0 if you don't. */ #undef HAVE_DECL_GLOB /* Define to 1 if you have the declaration of `gmtime_r', and to 0 if you don't. */ #undef HAVE_DECL_GMTIME_R /* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you don't. */ #undef HAVE_DECL_INET_NTOP /* Define to 1 if you have the declaration of `inet_pton', and to 0 if you don't. */ #undef HAVE_DECL_INET_PTON /* Define to 1 if you have the declaration of `isfinite', and to 0 if you don't. */ #undef HAVE_DECL_ISFINITE /* Define to 1 if you have the declaration of `le32toh', and to 0 if you don't. */ #undef HAVE_DECL_LE32TOH /* Define to 1 if you have the declaration of `localtime_r', and to 0 if you don't. */ #undef HAVE_DECL_LOCALTIME_R /* Define to 1 if you have the declaration of `log2', and to 0 if you don't. */ #undef HAVE_DECL_LOG2 /* Define to 1 if you have the declaration of `lstat', and to 0 if you don't. */ #undef HAVE_DECL_LSTAT /* Define to 1 if you have the declaration of `memdup', and to 0 if you don't. */ #undef HAVE_DECL_MEMDUP /* Define to 1 if you have the declaration of `memmem', and to 0 if you don't. */ #undef HAVE_DECL_MEMMEM /* Define to 1 if you have the declaration of `memrchr', and to 0 if you don't. */ #undef HAVE_DECL_MEMRCHR /* Define to 1 if you have the declaration of `mkdtemp', and to 0 if you don't. */ #undef HAVE_DECL_MKDTEMP /* Define to 1 if you have the declaration of `nanosleep', and to 0 if you don't. */ #undef HAVE_DECL_NANOSLEEP /* Define to 1 if you have the declaration of `openat', and to 0 if you don't. */ #undef HAVE_DECL_OPENAT /* Define to 1 if you have the declaration of `pthread_attr_setstacksize', and to 0 if you don't. */ #undef HAVE_DECL_PTHREAD_ATTR_SETSTACKSIZE /* Define to 1 if you have the declaration of `pthread_sigmask', and to 0 if you don't. */ #undef HAVE_DECL_PTHREAD_SIGMASK /* Define to 1 if you have the declaration of `realpath', and to 0 if you don't. */ #undef HAVE_DECL_REALPATH /* Define to 1 if you have the declaration of `round', and to 0 if you don't. */ #undef HAVE_DECL_ROUND /* Define to 1 if you have the declaration of `setlinebuf', and to 0 if you don't. */ #undef HAVE_DECL_SETLINEBUF /* Define to 1 if you have the declaration of `setnetgrent', and to 0 if you don't. */ #undef HAVE_DECL_SETNETGRENT /* Define to 1 if you have the declaration of `socketpair', and to 0 if you don't. */ #undef HAVE_DECL_SOCKETPAIR /* Define to 1 if you have the declaration of `srand48', and to 0 if you don't. */ #undef HAVE_DECL_SRAND48 /* Define to 1 if you have the declaration of `SSL_CTX_clear_options', and to 0 if you don't. */ #undef HAVE_DECL_SSL_CTX_CLEAR_OPTIONS /* Define to 1 if you have the declaration of `strcasecmp', and to 0 if you don't. */ #undef HAVE_DECL_STRCASECMP /* Define to 1 if you have the declaration of `strcasestr', and to 0 if you don't. */ #undef HAVE_DECL_STRCASESTR /* Define to 1 if you have the declaration of `strdup', and to 0 if you don't. */ #undef HAVE_DECL_STRDUP /* Define to 1 if you have the declaration of `strerror', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR /* Define to 1 if you have the declaration of `strlcat', and to 0 if you don't. */ #undef HAVE_DECL_STRLCAT /* Define to 1 if you have the declaration of `strlcpy', and to 0 if you don't. */ #undef HAVE_DECL_STRLCPY /* Define to 1 if you have the declaration of `strncasecmp', and to 0 if you don't. */ #undef HAVE_DECL_STRNCASECMP /* Define to 1 if you have the declaration of `strndup', and to 0 if you don't. */ #undef HAVE_DECL_STRNDUP /* Define to 1 if you have the declaration of `strnlen', and to 0 if you don't. */ #undef HAVE_DECL_STRNLEN /* Define to 1 if you have the declaration of `strrstr', and to 0 if you don't. */ #undef HAVE_DECL_STRRSTR /* Define to 1 if you have the declaration of `strsep', and to 0 if you don't. */ #undef HAVE_DECL_STRSEP /* Define to 1 if you have the declaration of `strsignal', and to 0 if you don't. */ #undef HAVE_DECL_STRSIGNAL /* Define to 1 if you have the declaration of `strstr', and to 0 if you don't. */ #undef HAVE_DECL_STRSTR /* Define to 1 if you have the declaration of `uname', and to 0 if you don't. */ #undef HAVE_DECL_UNAME /* Define to 1 if you have the declaration of `unsetenv', and to 0 if you don't. */ #undef HAVE_DECL_UNSETENV /* Define to 1 if you have the header file. */ #undef HAVE_DEPOT_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the `dirfd' function. */ #undef HAVE_DIRFD /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `door' function. */ #undef HAVE_DOOR /* Define to 1 if you have the `drand48' function. */ #undef HAVE_DRAND48 /* Define to 1 if you have the header file. */ #undef HAVE_DUSTAT_H /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H /* Define to 1 if you have the `endnetgrent' function. */ #undef HAVE_ENDNETGRENT /* Define to 1 if you have the `endpwent' function. */ #undef HAVE_ENDPWENT /* Define to 1 if you have the `fchmod' function. */ #undef HAVE_FCHMOD /* Define to 1 if you have the `fchownat' function. */ #undef HAVE_FCHOWNAT /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Whether to use fexecve(3) to execute a new process */ #undef HAVE_FEXECVE /* Define to 1 if you have the `fgetgrent' function. */ #undef HAVE_FGETGRENT /* Define to 1 if you have the `fgetpwent' function. */ #undef HAVE_FGETPWENT /* Define to 1 if you have the `fgetspent' function. */ #undef HAVE_FGETSPENT /* Define to 1 if you have the `fpathconf' function. */ #undef HAVE_FPATHCONF /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO /* Define to 1 if you have the `fstatat' function. */ #undef HAVE_FSTATAT /* Define to 1 if you have the `gethostent' function. */ #undef HAVE_GETHOSTENT /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `getifaddrs' function. */ #undef HAVE_GETIFADDRS /* Define to 1 if you have the `getline' function. */ #undef HAVE_GETLINE /* Define to 1 if you have the `getloadavg' function. */ #undef HAVE_GETLOADAVG /* Define to 1 if you have the `getnetgrent' function. */ #undef HAVE_GETNETGRENT /* Define to 1 if you have the `getprocs64' function. */ #undef HAVE_GETPROCS64 /* Define to 1 if you have the `getpwent' function. */ #undef HAVE_GETPWENT /* Define to 1 if you have the `getzoneid' function. */ #undef HAVE_GETZONEID /* Define to 1 if you have the `getzonenamebyid' function. */ #undef HAVE_GETZONENAMEBYID /* Define to 1 if you have the `gmtime_r' function. */ #undef HAVE_GMTIME_R /* Define to 1 if you have the header file. */ #undef HAVE_IEEEFP_H /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the `inet_pton' function. */ #undef HAVE_INET_PTON /* Define to 1 if the system has the type `intmax_t'. */ #undef HAVE_INTMAX_T /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `jail_get' function. */ #undef HAVE_JAIL_GET /* Define to 1 if you have the header file. */ #undef HAVE_KSTAT_H /* Whether to use lchown(3) to change ownerships */ #undef HAVE_LCHOWN /* Define to 1 if you have the `lckpwdf' function. */ #undef HAVE_LCKPWDF /* Define to 1 if you have the `acl' library (-lacl). */ #undef HAVE_LIBACL /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO /* Define to 1 if you have the `dgc' library (-ldgc). */ #undef HAVE_LIBDGC /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `kstat' library (-lkstat). */ #undef HAVE_LIBKSTAT /* Define to 1 if you have the `lmdb' library (-llmdb). */ #undef HAVE_LIBLMDB /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `mysqlclient' library (-lmysqlclient). */ #undef HAVE_LIBMYSQLCLIENT /* Define to 1 if you have the `nss_nis' library (-lnss_nis). */ #undef HAVE_LIBNSS_NIS /* Define to 1 if you have the `pam' library (-lpam). */ #undef HAVE_LIBPAM /* Define to 1 if you have the `pcre' library (-lpcre). */ #undef HAVE_LIBPCRE /* Define to 1 if you have the `pq' library (-lpq). */ #undef HAVE_LIBPQ /* Define to 1 if you have the header file. */ #undef HAVE_LIBPQ_FE_H /* Define to 1 if you have the `qdbm' library (-lqdbm). */ #undef HAVE_LIBQDBM /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the `ssl' library (-lssl). */ #undef HAVE_LIBSSL /* Define to 1 if you have the `tokyocabinet' library (-ltokyocabinet). */ #undef HAVE_LIBTOKYOCABINET /* Define to 1 if you have the `virt' library (-lvirt). */ #undef HAVE_LIBVIRT /* Define to 1 if you have the header file. */ #undef HAVE_LIBVIRT_LIBVIRT_H /* Define to 1 if you have the `xml2' library (-lxml2). */ #undef HAVE_LIBXML2 /* Define to 1 if you have the header file. */ #undef HAVE_LIBXML_XMLWRITER_H /* Define to 1 if you have the `listxattr' function. */ #undef HAVE_LISTXATTR /* Define to 1 if you have the header file. */ #undef HAVE_LMDB_H /* Define to 1 if you have the `localeconv' function. */ #undef HAVE_LOCALECONV /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* Define to 1 if you have the `log2' function. */ #undef HAVE_LOG2 /* Define to 1 if the system has the type `long double'. */ #undef HAVE_LONG_DOUBLE /* Define to 1 if the system has the type `long long int'. */ #undef HAVE_LONG_LONG_INT /* Define to 1 if you have the header file. */ #undef HAVE_MACH_MACH_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memdup' function. */ #undef HAVE_MEMDUP /* Define to 1 if you have the `memmem' function. */ #undef HAVE_MEMMEM /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR /* Define to 1 if you have the `mkdtemp' function. */ #undef HAVE_MKDTEMP /* Define to 1 if you have the `mkfifo' function. */ #undef HAVE_MKFIFO /* Define to 1 if you have the header file. */ #undef HAVE_MYSQL_H /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_DL_H /* Define to 1 if you have the header file. */ #undef HAVE_NLIST_H /* Define to 1 if you have the `openat' function. */ #undef HAVE_OPENAT /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_OPENSSLV_H /* The old route entry structure in newer BSDs */ #undef HAVE_ORTENTRY /* Define to 1 if you have the header file. */ #undef HAVE_PCRE_H /* Define to 1 if you have the header file. */ #undef HAVE_PCRE_PCRE_H /* Define to 1 if you have the `pstat_getdynamic' function. */ #undef HAVE_PSTAT_GETDYNAMIC /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Define to 1 if you have the `pthread_attr_setstacksize' function. */ #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE /* Define to 1 if you have the `pthread_sigmask' function. */ #undef HAVE_PTHREAD_SIGMASK /* Define to 1 if the system has the type `ptrdiff_t'. */ #undef HAVE_PTRDIFF_T /* Define if pwdadm tool is present */ #undef HAVE_PWDADM /* Define to 1 if you have the `round' function. */ #undef HAVE_ROUND /* Do we have any route entry structure? */ #undef HAVE_RTENTRY /* Define to 1 if you have the header file. */ #undef HAVE_SECURITY_PAM_APPL_H /* Define to 1 if you have the `sendto' function. */ #undef HAVE_SENDTO /* Define to 1 if you have the `setegid' function. */ #undef HAVE_SETEGID /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID /* Define to 1 if you have the `setlinebuf' function. */ #undef HAVE_SETLINEBUF /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE /* Define to 1 if you have the `setnetgrent' function. */ #undef HAVE_SETNETGRENT /* Define to 1 if you have the `setpwent' function. */ #undef HAVE_SETPWENT /* Define to 1 if you have the `setregid' function. */ #undef HAVE_SETREGID /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID /* Define to 1 if you have the `setsockopt' function. */ #undef HAVE_SETSOCKOPT /* Define to 1 if you have the header file. */ #undef HAVE_SHADOW_H /* Define to 1 if you have the `sleep' function. */ #undef HAVE_SLEEP /* Define to 1 if you have a C99 compliant `snprintf' function. */ #undef HAVE_SNPRINTF /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if the system has the type `socklen_t'. */ #undef HAVE_SOCKLEN_T /* Define to 1 if you have the `srand48' function. */ #undef HAVE_SRAND48 /* Define to 1 if you have the `statfs' function. */ #undef HAVE_STATFS /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if stdbool.h conforms to C99. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strcasestr' function. */ #undef HAVE_STRCASESTR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcat' function. */ #undef HAVE_STRLCAT /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if you have the `strncasecmp' function. */ #undef HAVE_STRNCASECMP /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN /* Define to 1 if you have the `strrstr' function. */ #undef HAVE_STRRSTR /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if you have the `strsignal' function. */ #undef HAVE_STRSIGNAL /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if `ifr_hwaddr' is a member of `struct ifreq'. */ #undef HAVE_STRUCT_IFREQ_IFR_HWADDR /* Define to 1 if `decimal_point' is a member of `struct lconv'. */ #undef HAVE_STRUCT_LCONV_DECIMAL_POINT /* Define to 1 if `thousands_sep' is a member of `struct lconv'. */ #undef HAVE_STRUCT_LCONV_THOUSANDS_SEP /* Define to 1 if `n_un.n_name' is a member of `struct nlist'. */ #undef HAVE_STRUCT_NLIST_N_UN_N_NAME /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ #undef HAVE_STRUCT_SOCKADDR_SA_LEN /* Define to 1 if the system has the type `struct sockaddr_storage'. */ #undef HAVE_STRUCT_SOCKADDR_STORAGE /* Define to 1 if `st_mtim' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIM /* Define to 1 if `st_mtimespec' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIMESPEC /* Define to 1 if `uptime' is a member of `struct sysinfo'. */ #undef HAVE_STRUCT_SYSINFO_UPTIME /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the `sysinfo' function. */ #undef HAVE_SYSINFO /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ACL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILESYS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_JAIL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_LOADAVG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MPCTL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSCTL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSTEMINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_UIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_XATTR_H /* Define to 1 if you have the header file. */ #undef HAVE_TCHDB_H /* Define to 1 if you have the header file. */ #undef HAVE_TCUTIL_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if the system has the type `uintmax_t'. */ #undef HAVE_UINTMAX_T /* Define to 1 if the system has the type `uintptr_t'. */ #undef HAVE_UINTPTR_T /* Define to 1 if you have the `ulckpwdf' function. */ #undef HAVE_ULCKPWDF /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `unsetenv' function. */ #undef HAVE_UNSETENV /* Define to 1 if the system has the type `unsigned long long int'. */ #undef HAVE_UNSIGNED_LONG_LONG_INT /* Define if useradd tool is present */ #undef HAVE_USERADD /* Define if userdel tool is present */ #undef HAVE_USERDEL /* Define if usermod tool is present */ #undef HAVE_USERMOD /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H /* Define to 1 if you have the header file. */ #undef HAVE_UTMPX_H /* Define to 1 if you have the header file. */ #undef HAVE_UTMP_H /* Define to 1 if you have the header file. */ #undef HAVE_VARARGS_H /* Define to 1 if you have the `vasprintf' function. */ #undef HAVE_VASPRINTF /* Define to 1 if you have the `va_copy' function or macro. */ #undef HAVE_VA_COPY /* Define to 1 if you have the header file. */ #undef HAVE_VFS_H /* Define to 1 if you have a C99 compliant `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_WINSOCK2_H /* Define to 1 if you have the header file. */ #undef HAVE_WS2TCPIP_H /* Define to 1 if you have the header file. */ #undef HAVE_ZONE_H /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL /* Define to 1 if you have the `__va_copy' function or macro. */ #undef HAVE___VA_COPY /* Define to 1 if you have properly defined `ctime' function */ #undef HAVE_ctime_PROPER /* Define to 1 if you have properly defined `mkdir' function */ #undef HAVE_mkdir_PROPER /* Define to 1 if you have properly defined `rename' function */ #undef HAVE_rename_PROPER /* Define to 1 if you have properly defined `stat' function */ #undef HAVE_stat_PROPER /* Inputs directory location */ #undef INPUTDIR /* Define if Lightning MDB is available */ #undef LMDB /* Logdir location */ #undef LOGDIR /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Masterfiles directory location */ #undef MASTERDIR /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ #undef NLIST_NAME_UNION /* Define if non deprecated API is available. */ #undef OPENSSL_NO_DEPRECATED /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* piddir location */ #undef PIDDIR /* Define to necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Path to pwdadm tool */ #undef PWDADM /* Define if QDBM is available */ #undef QDB /* Whether sendto does not returns ssize_t */ #undef SENDTO_RETURNS_SSIZE_T /* Whether setnetgrent returns int */ #undef SETNETGRENT_RETURNS_INT /* Path to the POSIX-compatible shell */ #undef SHELL_PATH /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 on System V Release 4. */ #undef SVR4 /* Define if Tokyo Cabinet is available. */ #undef TCDB /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 for Encore UMAX. */ #undef UMAX /* Define to 1 for Encore UMAX 4.3 that has instead of . */ #undef UMAX4_3 /* Path to useradd tool */ #undef USERADD /* Path to userdel tool */ #undef USERDEL /* Path to usermod tool */ #undef USERMOD /* Version number of package */ #undef VERSION /* Define if you have a libc that supports extended attributes */ #undef WITH_XATTR /* Define if your xattr implementation has extra arguments */ #undef WITH_XATTR_EXTRA_ARGS /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Workdir location */ #undef WORKDIR /* Define if XEN cpuid-based HVM detection is available. */ #undef XEN_CPUID_SUPPORT /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* SUSv3 */ #undef _XOPEN_SOURCE /* Extended UNIX 98 interfaces */ #undef __EXTENSIONS__ /* Define to rpl_asprintf if the replacement function should be used. */ #undef asprintf /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to rpl_fprintf if the replacement function should be used. */ #undef fprintf /* Define to `int' if doesn't define. */ #undef gid_t /* Define to the widest signed integer type if and do not define. */ #undef intmax_t /* Define to `int' if does not define. */ #undef mode_t /* Define to `long int' if does not define. */ #undef off_t /* Define to `int' if does not define. */ #undef pid_t /* Define to rpl_printf if the replacement function should be used. */ #undef printf /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to rpl_snprintf if the replacement function should be used. */ #undef snprintf /* Define to `int' if doesn't define. */ #undef uid_t /* Define to the widest unsigned integer type if and do not define. */ #undef uintmax_t /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ #undef uintptr_t /* Define to rpl_vasprintf if the replacement function should be used. */ #undef vasprintf /* Define to rpl_vfprintf if the replacement function should be used. */ #undef vfprintf /* Define to rpl_vprintf if the replacement function should be used. */ #undef vprintf /* Define to rpl_vsnprintf if the replacement function should be used. */ #undef vsnprintf cfengine-3.6.2/libutils/man.h0000644000175100017510000000253312316547775015613 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MAN_H #define CFENGINE_MAN_H #include #include void ManPageWrite(Writer *out, const char *program, time_t last_modified, const char *short_description, const char *long_description, const struct option options[], const char *const option_hints[], bool accepts_file_argument); #endif cfengine-3.6.2/libutils/cfversion.c0000664000175100017510000001647112400110676017015 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include struct Version { uint8_t major; uint8_t minor; uint8_t patch; uint8_t extra; uint8_t build; }; #define Char2Dec(o, c) \ (o * 10) + c - '0' Version *VersionNew() { Version *version = NULL; version = xmalloc(sizeof(Version)); version->major = 0; version->minor = 0; version->patch = 0; version->extra = 0; version->build = 0; return version; } Version *VersionNewFromCharP(const char *version, unsigned int size) { if (!version) { return NULL; } /* * Parse the version string * * +-> Done * '.' '.' '-' | * 0 ---- > 1 ----> 2 ----> 3 <-+ * | '.' | * +-----> 4 --+ */ uint16_t major = 0; uint16_t minor = 0; uint16_t patch = 0; uint16_t extra = 0; uint16_t build = 0; uint16_t value = 0; unsigned int i = 0; int state = 0; int error_condition = 0; for (i = 0; i < size; ++i) { int is_period = 0; int is_number = 0; int is_dash = 0; char current = 0; current = version[i]; is_period = (current == '.') ? 1 : 0; is_number = isdigit(current); is_dash = (current == '-') ? 1 : 0; if (value > 255) { error_condition = 1; break; } switch (state) { case 0: if (is_period) { state = 1; major = (uint8_t)value; value = 0; break; } if (is_number) { value = Char2Dec(value, current); } else { error_condition = 1; i = size + 1; break; } break; case 1: if (is_period) { state = 2; minor = (uint8_t)value; value = 0; break; } if (is_number) { value = Char2Dec(value, current); } else { error_condition = 1; i = size + 1; break; } break; case 2: if (is_period) { state = 4; patch = (uint8_t)value; value = 0; break; } if (is_dash) { state = 3; patch = value; value = 0; break; } if (is_number) { value = Char2Dec(value, current); } else { error_condition = 1; i = size + 1; break; } break; case 3: if (is_number) { value = Char2Dec(value, current); } else { error_condition = 1; i = size + 1; break; } break; case 4: if (is_dash) { state = 3; extra = (uint8_t)value; value = 0; break; } if (is_number) { value = Char2Dec(value, current); } else { error_condition = 1; i = size + 1; break; } break; default: error_condition = 1; break; } } if (error_condition) { return NULL; } /* There are two valid exit states: 2 & 3, all other states indicate error */ if ((state == 2) || (state == 3)) { if (state == 2) { if (value > 255) { return NULL; } patch = (uint8_t)value; } else { if (value > 255) { return NULL; } build = (uint8_t)value; } } else { return NULL; } Version *v = VersionNew(); v->major = major; v->minor = minor; v->patch = patch; v->extra = extra; v->build = build; return v; } Version *VersionNewFrom(Buffer *buffer) { if (!buffer) { return NULL; } return VersionNewFromCharP(BufferData(buffer), BufferSize(buffer)); } void VersionDestroy(Version **version) { if (!version || !(*version)) { return; } free (*version); *version = NULL; } int VersionCompare(Version *a, Version *b) { int comparison = 0; if (a->major < b->major) { comparison = -10; } else if (a->major == b->major) { if (a->minor < b->minor) { comparison = -10; } else if (a->minor == b->minor) { if (a->patch < b->patch) { comparison = -10; } else if (a->patch == b->patch) { if (a->build < b->build) { comparison = -10; } else if (a->build == b->build) { comparison = 0; } else { comparison = 10; } } else { comparison = 10; } } else { comparison = 10; } } else { comparison = 10; } return comparison; } int VersionMajor(Version *version) { if (!version) { return -1; } return (int)version->major; } int VersionMinor(Version *version) { if (!version) { return -1; } return (int)version->minor; } int VersionPatch(Version *version) { if (!version) { return -1; } return (int)version->patch; } int VersionExtra(Version *version) { if (!version) { return -1; } return (int)version->extra; } int VersionBuild(Version *version) { if (!version) { return -1; } return (int)version->build; } cfengine-3.6.2/libutils/proc_keyvalue.h0000664000175100017510000000306112243421446017670 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PROC_KEYVALUE_H #define CFENGINE_PROC_KEYVALUE_H #include /* * Parser for line-oriented key-value formats found in Linux /proc filesystem. */ typedef bool (*KeyNumericValueCallback) (const char *field, off_t value, void *param); /* * Returns false on syntax error */ bool ParseKeyNumericValue(FILE *fd, KeyNumericValueCallback callback, void *param); typedef bool (*KeyValueCallback) (const char *field, const char *value, void *param); /* * Returns false on syntax error */ bool ParseKeyValue(FILE *fd, KeyValueCallback callback, void *param); #endif cfengine-3.6.2/libutils/alloc.h0000644000175100017510000000514212316547775016131 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ALLOC_H #define CFENGINE_ALLOC_H #include #include void *xcalloc(size_t nmemb, size_t size); void *xmalloc(size_t size); void *xrealloc(void *ptr, size_t size); char *xstrdup(const char *str); char *xstrndup(const char *str, size_t n); void *xmemdup(const void *mem, size_t size); int xasprintf(char **strp, const char *fmt, ...) FUNC_ATTR_PRINTF(2, 3); int xvasprintf(char **strp, const char *fmt, va_list ap) FUNC_ATTR_PRINTF(2, 0); /* * Prevent any code from using un-wrapped allocators. * * Use x* equivalents instead. */ /** * Currently regular malloc() calls are allowed for mission-critical code that * can somehow recover, like cf-serverd dropping connections or cf-execd * postponing its scheduled actions. * * @note for 99% of the cases (libpromises, cf-agent etc) use xmalloc() and * friends. **/ #if 0 # undef malloc # undef calloc # undef realloc # undef strdup # undef strndup # undef memdup # undef asprintf # undef vasprintf # define malloc __error_unchecked_malloc # define calloc __error_unchecked_calloc # define realloc __error_unchecked_realloc # define strdup __error_unchecked_strdup # define strndup __error_unchecked_strndup # define memdup __error_unchecked_memdup # define asprintf __error_unchecked_asprintf # define vasprintf __error_unchecked_vasprintf void __error_unchecked_malloc(void); void __error_unchecked_calloc(void); void __error_unchecked_realloc(void); void __error_unchecked_strdup(void); void __error_unchecked_strndup(void); void __error_unchecked_memdup(void); void __error_unchecked_asprintf(void); void __error_unchecked_vasprintf(void); #endif #endif cfengine-3.6.2/libutils/xml_writer.c0000664000175100017510000001004412243421446017206 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include static void WriteEscaped(Writer *writer, const char *source); /*****************************************************************************/ void XmlComment(Writer *writer, const char *comment) { if (writer == NULL) { ProgrammingError("NULL writer passed to XmlWriter"); } WriterWrite(writer, "\n"); } /*****************************************************************************/ static void XmlEmitStartTag(Writer *writer, const char *tag_name, int attr_cnt, va_list args) { WriterWriteF(writer, "<%s", tag_name); if (attr_cnt > 0) { WriterWrite(writer, " "); } for (int i = 0; i < attr_cnt; ++i) { XmlAttribute attr = va_arg(args, XmlAttribute); WriterWriteF(writer, "%s=\"%s\" ", attr.name, attr.value); } WriterWrite(writer, ">"); } /*****************************************************************************/ void XmlStartTag(Writer *writer, const char *tag_name, int attr_cnt, ...) { va_list args; if ((writer == NULL) || (tag_name == NULL) || (attr_cnt < 0)) { ProgrammingError("writer, tag_name or attr_cnt in XmlStartTag are wrong"); } va_start(args, attr_cnt); XmlEmitStartTag(writer, tag_name, attr_cnt, args); va_end(args); WriterWrite(writer, "\n"); } /*****************************************************************************/ void XmlEndTag(Writer *writer, const char *tag_name) { if ((writer == NULL) || (tag_name == NULL)) { ProgrammingError("writer or tag_name are missing"); } WriterWriteF(writer, "\n", tag_name); } /*****************************************************************************/ void XmlTag(Writer *writer, const char *tag_name, const char *value, int attr_cnt, ...) { va_list args; if ((writer == NULL) || (tag_name == NULL) || (attr_cnt < 0)) { return; } va_start(args, attr_cnt); XmlEmitStartTag(writer, tag_name, attr_cnt, args); va_end(args); if (value != NULL) { WriteEscaped(writer, value); } XmlEndTag(writer, tag_name); } /*****************************************************************************/ void XmlContent(Writer *writer, const char *value) { if (writer == NULL) { ProgrammingError("writer is NULL"); } WriteEscaped(writer, value); } /*****************************************************************************/ static void WriteEscaped(Writer *w, const char *source) { for (const char *s = source; *s; s++) { switch (*s) { case '&': WriterWrite(w, "&"); break; case '>': WriterWrite(w, ">"); break; case '"': WriterWrite(w, """); break; case '\'': WriterWrite(w, "'"); break; case '<': WriterWrite(w, "<"); break; default: WriterWriteChar(w, *s); } } } cfengine-3.6.2/libutils/hash_map.c0000664000175100017510000001446312400110676016576 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* FIXME: make configurable and move to map.c */ #define HASHMAP_BUCKETS 8192 HashMap *HashMapNew(MapHashFn hash_fn, MapKeyEqualFn equal_fn, MapDestroyDataFn destroy_key_fn, MapDestroyDataFn destroy_value_fn) { HashMap *map = xcalloc(1, sizeof(HashMap)); map->hash_fn = hash_fn; map->equal_fn = equal_fn; map->destroy_key_fn = destroy_key_fn; map->destroy_value_fn = destroy_value_fn; map->buckets = xcalloc(1, sizeof(BucketListItem *) * HASHMAP_BUCKETS); return map; } static unsigned int HashMapGetBucket(const HashMap *map, const void *key) { return map->hash_fn(key, 0, HASHMAP_BUCKETS); } bool HashMapInsert(HashMap *map, void *key, void *value) { unsigned bucket = HashMapGetBucket(map, key); for (BucketListItem *i = map->buckets[bucket]; i != NULL; i = i->next) { if (map->equal_fn(i->value.key, key)) { map->destroy_key_fn(key); map->destroy_value_fn(i->value.value); i->value.value = value; return true; } } BucketListItem *i = xcalloc(1, sizeof(BucketListItem)); i->value.key = key; i->value.value = value; i->next = map->buckets[bucket]; map->buckets[bucket] = i; return false; } bool HashMapRemove(HashMap *map, const void *key) { unsigned bucket = HashMapGetBucket(map, key); /* * prev points to a previous "next" pointer to rewrite it in case value need * to be deleted */ for (BucketListItem **prev = &map->buckets[bucket]; *prev != NULL; prev = &((*prev)->next)) { BucketListItem *cur = *prev; if (map->equal_fn(cur->value.key, key)) { map->destroy_key_fn(cur->value.key); map->destroy_value_fn(cur->value.value); *prev = cur->next; free(cur); return true; } } return false; } MapKeyValue *HashMapGet(const HashMap *map, const void *key) { unsigned bucket = HashMapGetBucket(map, key); for (BucketListItem *cur = map->buckets[bucket]; cur != NULL; cur = cur->next) { if (map->equal_fn(cur->value.key, key)) { return &cur->value; } } return NULL; } static void FreeBucketListItem(HashMap *map, BucketListItem *item) { if (item->next) { FreeBucketListItem(map, item->next); } map->destroy_key_fn(item->value.key); map->destroy_value_fn(item->value.value); free(item); } /* Do not destroy value item */ static void FreeBucketListItemSoft(HashMap *map, BucketListItem *item) { if (item->next) { FreeBucketListItemSoft(map, item->next); } map->destroy_key_fn(item->value.key); free(item); } void HashMapClear(HashMap *map) { for (int i = 0; i < HASHMAP_BUCKETS; ++i) { if (map->buckets[i]) { FreeBucketListItem(map, map->buckets[i]); } map->buckets[i] = NULL; } } void HashMapSoftDestroy(HashMap *map) { if (map) { for (int i = 0; i < HASHMAP_BUCKETS; ++i) { if (map->buckets[i]) { FreeBucketListItemSoft(map, map->buckets[i]); } map->buckets[i] = NULL; } free(map->buckets); free(map); } } void HashMapDestroy(HashMap *map) { if (map) { HashMapClear(map); free(map->buckets); free(map); } } void HashMapPrintStats(const HashMap *hmap, FILE *f) { size_t bucket_lengths[HASHMAP_BUCKETS] = { 0 }; size_t num_el = 0; size_t num_buckets = 0; for (int i = 0; i < HASHMAP_BUCKETS; i++) { BucketListItem *b = hmap->buckets[i]; if (b != NULL) { num_buckets++; } while (b != NULL) { num_el++; bucket_lengths[i]++; b = b->next; } } fprintf(f, "\tTotal number of buckets: %5d\n", HASHMAP_BUCKETS); fprintf(f, "\tNumber of non-empty buckets: %5zu\n", num_buckets); fprintf(f, "\tTotal number of elements: %5zu\n", num_el); fprintf(f, "\tAverage elements per non-empty bucket (load factor): %5.2f\n", (float) num_el / num_buckets); fprintf(f, "\tThe 10 longest buckets are: \n"); for (int j = 0; j < 10; j++) { /* Find the maximum 10 times, zeroing it after printing it. */ int longest_bucket_id = 0; for (int i = 0; i < HASHMAP_BUCKETS; i++) { if (bucket_lengths[i] > bucket_lengths[longest_bucket_id]) { longest_bucket_id = i; } } fprintf(f, "\t\tbucket %5d with %zu elements\n", longest_bucket_id, bucket_lengths[longest_bucket_id]); bucket_lengths[longest_bucket_id] = 0; } } /******************************************************************************/ HashMapIterator HashMapIteratorInit(HashMap *map) { return (HashMapIterator) { map, map->buckets[0], 0 }; } MapKeyValue *HashMapIteratorNext(HashMapIterator *i) { while (i->cur == NULL) { if (++i->bucket >= HASHMAP_BUCKETS) { return NULL; } i->cur = i->map->buckets[i->bucket]; } MapKeyValue *ret = &i->cur->value; i->cur = i->cur->next; return ret; } cfengine-3.6.2/libutils/refcount.c0000644000175100017510000000727212316547775016665 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include void RefCountNew(RefCount **ref) { if (!ref) { return; } *ref = (RefCount *)xmalloc(sizeof(RefCount)); (*ref)->user_count = 0; (*ref)->users = NULL; (*ref)->last = NULL; } void RefCountDestroy(RefCount **ref) { if (ref && *ref) { // Destroying a refcount which has more than one user is a bug, but we let it // pass in production code (memory leak). assert((*ref)->user_count <= 1); if ((*ref)->user_count > 1) return; if ((*ref)->users) free((*ref)->users); free(*ref); *ref = NULL; } } void RefCountAttach(RefCount *ref, void *owner) { if (!ref || !owner) { ProgrammingError("Either refcount or owner is NULL (or both)"); } ref->user_count++; RefCountNode *node = (RefCountNode *)xmalloc(sizeof(RefCountNode)); node->next = NULL; node->user = owner; if (ref->last) { ref->last->next = node; node->previous = ref->last; } else { ref->users = node; node->previous = NULL; } ref->last = node; } void RefCountDetach(RefCount *ref, void *owner) { if (!ref || !owner) { ProgrammingError("Either refcount or owner is NULL (or both)"); } if (ref->user_count <= 1) { /* * Semantics: If 1 that means that we are the only users, if 0 nobody is using it. * In either case it is safe to destroy the refcount. */ return; } RefCountNode *p = NULL; int found = 0; for (p = ref->users; p; p = p->next) { if (p->user == owner) { found = 1; if (p->previous && p->next) { p->previous->next = p->next; p->next->previous = p->previous; } else if (p->previous && !p->next) { // Last node p->previous->next = NULL; ref->last = p->previous; } else if (!p->previous && p->next) { // First node ref->users = p->next; p->next->previous = NULL; } else { // Only one node, we cannot detach from ourselves. return; } free(p); break; } } if (!found) { ProgrammingError("The object is not attached to the RefCount object"); } ref->user_count--; } bool RefCountIsShared(RefCount *ref) { return ref && (ref->user_count > 1); } bool RefCountIsEqual(RefCount *a, RefCount *b) { return (a && b) && (a == b); } cfengine-3.6.2/libutils/queue.h0000644000175100017510000000255712316547775016172 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #ifndef CFENGINE_QUEUE_H #define CFENGINE_QUEUE_H typedef struct Queue_ Queue; typedef void QueueItemDestroy(void *); Queue *QueueNew(QueueItemDestroy *item_destroy); void QueueDestroy(Queue *q); void QueueEnqueue(Queue *q, void *element); void *QueueDequeue(Queue *q); void *QueueHead(Queue *q); int QueueCount(const Queue *q); bool QueueIsEmpty(const Queue *q); #endif cfengine-3.6.2/libutils/dir_priv.h0000644000175100017510000000213712352557236016647 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_DIR_IMPL_H #define CFENGINE_DIR_IMPL_H struct dirent *AllocateDirentForFilename(const char *filename); #endif cfengine-3.6.2/libutils/encode.h0000664000175100017510000000220512400110676016247 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ENCODE_H #define CFENGINE_ENCODE_H #include char *StringEncodeBase64(const char *str, size_t len); #endif /* CFENGINE_ENCODE_H */ cfengine-3.6.2/libutils/map.h0000664000175100017510000002102612400110676015571 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MAP_H #define CFENGINE_MAP_H #include #include /* * Map structure. Details are encapsulated. */ typedef struct Map_ Map; Map *MapNew(MapHashFn hash_fn, MapKeyEqualFn equal_fn, MapDestroyDataFn destroy_key_fn, MapDestroyDataFn destroy_value_fn); /* * If the key is in the map, value get replaced. Old value is destroyed. */ void MapInsert(Map *map, void *key, void *value); /* * Returns whether the key is in the map. */ bool MapHasKey(const Map *map, const void *key); /* * Returns the value if the key is in map, NULL otherwise. To distinguish * between NULL as a value and NULL as a lack of entry, use MapHasKey. */ void *MapGet(Map *map, const void *key); /* * Remove key/value pair from the map. Returns 'true' if key was present in the * map. */ bool MapRemove(Map *map, const void *key); size_t MapSize(const Map *map); /* * MapIterator i = MapIteratorInit(map); * MapKeyValue *item; * while ((item = MapIteratorNext(&i))) * { * // do something with item->key, item->value * } */ typedef struct { bool is_array; union { ArrayMapIterator arraymap_iter; HashMapIterator hashmap_iter; }; } MapIterator; MapIterator MapIteratorInit(Map *map); MapKeyValue *MapIteratorNext(MapIterator *i); /* * Clear the whole map */ void MapClear(Map *map); /* * Destroy the map object. */ void MapDestroy(Map *map); /* * Destroy the map object without removing values. */ void MapSoftDestroy(Map *map); /** * Returns whether the two maps contain the same keys. * The values DO NOT have to be equal, just the keys. */ bool MapContainsSameKeys(const Map *map1, const Map *map2); void MapPrintStats(const Map *map, FILE *f); #define TYPED_MAP_DECLARE(Prefix, KeyType, ValueType) \ typedef struct \ { \ Map *impl; \ } Prefix##Map; \ \ Prefix##Map *Prefix##MapNew(void); \ void Prefix##MapInsert(const Prefix##Map *map, KeyType key, ValueType value); \ bool Prefix##MapHasKey(const Prefix##Map *map, const KeyType key); \ ValueType Prefix##MapGet(const Prefix##Map *map, const KeyType key); \ bool Prefix##MapRemove(const Prefix##Map *map, const KeyType key); \ void Prefix##MapClear(Prefix##Map *map); \ size_t Prefix##MapSize(const Prefix##Map *map); \ void Prefix##MapDestroy(Prefix##Map *map); \ void Prefix##MapSoftDestroy(Prefix##Map *map); \ bool Prefix##MapContainsSameKeys(const Prefix##Map *map1, const Prefix##Map *map2); \ void Prefix##MapPrintStats(const Prefix##Map *map, FILE *f); \ #define TYPED_MAP_DEFINE(Prefix, KeyType, ValueType, hash_fn, equal_fn, \ destroy_key_fn, destroy_value_fn) \ \ Prefix##Map *Prefix##MapNew(void) \ { \ Prefix##Map *map = xcalloc(1, sizeof(Prefix##Map)); \ map->impl = MapNew(hash_fn, equal_fn, \ destroy_key_fn, destroy_value_fn); \ return map; \ } \ \ void Prefix##MapInsert(const Prefix##Map *map, KeyType key, ValueType value) \ { \ MapInsert(map->impl, key, value); \ } \ \ bool Prefix##MapHasKey(const Prefix##Map *map, const KeyType key) \ { \ return MapHasKey(map->impl, key); \ } \ \ ValueType Prefix##MapGet(const Prefix##Map *map, const KeyType key) \ { \ return MapGet(map->impl, key); \ } \ \ bool Prefix##MapRemove(const Prefix##Map *map, const KeyType key) \ { \ return MapRemove(map->impl, key); \ } \ \ void Prefix##MapClear(Prefix##Map *map) \ { \ MapClear(map->impl); \ } \ \ size_t Prefix##MapSize(const Prefix##Map *map) \ { \ return MapSize(map->impl); \ } \ \ void Prefix##MapDestroy(Prefix##Map *map) \ { \ MapDestroy(map->impl); \ free(map); \ } \ \ void Prefix##MapSoftDestroy(Prefix##Map *map) \ { \ MapSoftDestroy(map->impl); \ free(map); \ } \ \ bool Prefix##MapContainsSameKeys(const Prefix##Map *map1, const Prefix##Map *map2) \ { \ return MapContainsSameKeys(map1->impl, map2->impl); \ } \ \ void Prefix##MapPrintStats(const Prefix##Map *map, FILE *f) \ { \ return MapPrintStats(map->impl, f); \ } \ TYPED_MAP_DECLARE(String, char *, char *) #endif cfengine-3.6.2/libutils/array_map_priv.h0000644000175100017510000000400612316547775020050 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ARRAY_MAP_PRIV_H #define CFENGINE_ARRAY_MAP_PRIV_H #include typedef struct { MapKeyEqualFn equal_fn; MapDestroyDataFn destroy_key_fn; MapDestroyDataFn destroy_value_fn; MapKeyValue *values; short size; } ArrayMap; typedef struct { ArrayMap *map; int pos; } ArrayMapIterator; ArrayMap *ArrayMapNew(MapKeyEqualFn equal_fn, MapDestroyDataFn destroy_key_fn, MapDestroyDataFn destroy_value_fn); /* * Returns false if the limit of the array size has been reached. */ bool ArrayMapInsert(ArrayMap *map, void *key, void *value); bool ArrayMapRemove(ArrayMap *map, const void *key); MapKeyValue *ArrayMapGet(const ArrayMap *map, const void *key); void ArrayMapClear(ArrayMap *map); void ArrayMapSoftDestroy(ArrayMap *map); void ArrayMapDestroy(ArrayMap *map); /******************************************************************************/ ArrayMapIterator ArrayMapIteratorInit(ArrayMap *map); MapKeyValue *ArrayMapIteratorNext(ArrayMapIterator *i); #endif cfengine-3.6.2/libutils/misc_lib.h0000664000175100017510000000507312400110676016601 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MISC_LIB_H #define CFENGINE_MISC_LIB_H #include #include #define ProgrammingError(...) __ProgrammingError(__FILE__, __LINE__, __VA_ARGS__) #define UnexpectedError(...) __UnexpectedError(__FILE__, __LINE__, __VA_ARGS__) #ifndef NDEBUG # define CF_ASSERT(condition, ...) \ do { \ if (!(condition)) \ ProgrammingError(__VA_ARGS__); \ } while(0) #else /* TODO in non-debug builds, this could be UnexpectedError(), but it needs * to be rate limited to avoid spamming the console. */ # define CF_ASSERT(condition, ...) (void)(0) #endif /* In contrast to the standard C modulus operator (%), this gives you an unsigned modulus. So where -1 % 3 => -1, UnsignedModulus(-1, 3) => 2. */ unsigned long UnsignedModulus(long dividend, long divisor); size_t UpperPowerOfTwo(size_t v); void __ProgrammingError(const char *file, int lineno, const char *format, ...) \ FUNC_ATTR_PRINTF(3, 4) FUNC_ATTR_NORETURN; void __UnexpectedError(const char *file, int lineno, const char *format, ...) \ FUNC_ATTR_PRINTF(3, 4); /** * Unchecked versions of common functions, i.e. functions that no longer * return anything, but try to continue in case of failure. * * @NOTE call these only with arguments that will always succeed! */ void xclock_gettime(clockid_t clk_id, struct timespec *ts); void xsnprintf(char *str, size_t str_size, const char *format, ...); #endif cfengine-3.6.2/libutils/man.c0000644000175100017510000001765212316547775015616 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include static void WriteCopyright(Writer *out) { static const char *const copyright = ".\\\"Copyright (C) CFEngine AS\n" ".\\\"\n" ".\\\"This file is part of CFEngine 3 - written and maintained by CFEngine AS.\n" ".\\\"\n" ".\\\"This program is free software; you can redistribute it and/or modify it\n" ".\\\"under the terms of the GNU General Public License as published by the\n" ".\\\"Free Software Foundation; version 3.\n" ".\\\"\n" ".\\\"This program is distributed in the hope that it will be useful,\n" ".\\\"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" ".\\\"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" ".\\\"GNU General Public License for more details.\n" ".\\\"\n" ".\\\"You should have received a copy of the GNU General Public License\n" ".\\\"along with this program; if not, write to the Free Software\n" ".\\\"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n" ".\\\"\n" ".\\\"To the extent this program is licensed as part of the Enterprise\n" ".\\\"versions of CFEngine, the applicable Commercial Open Source License\n" ".\\\"(COSL) may apply to this file if you as a licensee so wish it. See\n" ".\\\"included file COSL.txt.\n"; WriterWrite(out, copyright); } static void WriteHeader(Writer *out, const char *program, time_t last_modified) { char program_upper[256] = { 0 }; snprintf(program_upper, 255, "%s", program); ToUpperStrInplace(program_upper); char date_modified[20] = { 0 }; { struct tm t; gmtime_r(&last_modified, &t); strftime(date_modified, 19, "%Y-%m-%d", &t); } WriterWriteF(out, ".TH %s 8 \"%s\" \"CFEngine\" \"System Administration\"\n", program_upper, date_modified); } static void WriteAvailability(Writer *out, const char *program) { static const char *const availability = ".SH AVAILABILITY\n" "%s is part of CFEngine.\n" ".br\n" "Binary packages may be downloaded from http://cfengine.com/downloads/.\n" ".br\n" "The source code is available at http://github.com/cfengine/\n"; WriterWriteF(out, availability, program); } static void WriteAuthor(Writer *out) { static const char *const author = ".SH AUTHOR\n" "Mark Burgess and CFEngine AS\n"; WriterWrite(out, author); } static void WriteName(Writer *out, const char *program, const char *short_description) { static const char *const author = ".SH NAME\n" "%s \\- %s\n"; WriterWriteF(out, author, program, short_description); } static void WriteSynopsis(Writer *out, const char *program, bool accepts_file_argument) { static const char *const synopsis = ".SH SYNOPSIS\n" ".B %s\n" ".RI [ OPTION ]...\n"; WriterWriteF(out, synopsis, program); if (accepts_file_argument) { WriterWrite(out, ".RI [ FILE ]\n"); } else { WriterWrite(out, "\n"); } } static void WriteDescription(Writer *out, const char *description) { WriterWriteF(out, ".SH DESCRIPTION\n%s\n", description); } static void WriteOptions(Writer *out, const struct option options[], const char *const option_hints[]) { WriterWrite(out, ".SH OPTIONS\n"); for (int i = 0; options[i].name != NULL; i++) { if (options[i].has_arg) { WriterWriteF(out, ".IP \"--%s, -%c\" value\n%s\n", options[i].name, (char) options[i].val, option_hints[i]); } else { WriterWriteF(out, ".IP \"--%s, -%c\"\n%s\n", options[i].name, (char) options[i].val, option_hints[i]); } } } static void WriteSeeAlso(Writer *out) { static const char *const see_also = ".SH \"SEE ALSO\"\n" ".BR cf-promises (8),\n" ".BR cf-agent (8),\n" ".BR cf-serverd (8),\n" ".BR cf-execd (8),\n" ".BR cf-monitord (8),\n" ".BR cf-runagent (8),\n" ".BR cf-key (8)\n"; WriterWrite(out, see_also); } static void WriteBugs(Writer *out) { static const char *const bugs = ".SH BUGS\n" "Please see the public bug-tracker at http://bug.cfengine.com/.\n" ".br\n" "GitHub pull-requests may be submitted to http://github.com/cfengine/core/.\n"; WriterWrite(out, bugs); } static void WriteCFEngine(Writer *out) { static const char *const cfengine = ".SH CFENGINE\n" "CFEngine provides automated configuration management of large-scale computer systems. A system administrator " "describes the desired state of a system using CFEngine policy code. The program \\fBcf-agent\\fR reads policy code " "and attempts to bring the current system state to the desired state described. Policy code is downloaded by " "\\fBcf-agent\\fR from a \\fBcf-serverd\\fR daemon. The daemon \\fBcf-execd\\fR is responsible for running " "\\fBcf-agent\\fR periodically.\n" ".br\n" "Documentation for CFEngine is available at http://cfengine.com/documentation/.\n"; WriterWrite(out, cfengine); } static void WritePromiseTheory(Writer *out) { static const char *const promise_theory = ".SH PROMISE THEORY\n" "CFEngine is built on principles from promise theory, proposed by Mark Burgess in 2004. " "Promise theory is a model of voluntary cooperation between individual, autonomous " "actors or agents who publish their intentions to one another in the form of promises. " "A promise is a declaration of intent whose purpose is to increase the recipient's certainty " "about a claim of past, present or future behaviour. For a promise to increase certainty, " "the recipient needs to trust the promiser, but trust can also be built on the verification " "that previous promises have been kept, thus trust plays a symbiotic relationship with promises. \n" ".br\n" "For an introduction to promise theory, please see http://arxiv.org/abs/0810.3294/\n"; WriterWrite(out, promise_theory); } void ManPageWrite(Writer *out, const char *program, time_t last_modified, const char *short_description, const char *long_description, const struct option options[], const char *const option_hints[], bool accepts_file_argument) { WriteCopyright(out); WriteHeader(out, program, last_modified); WriteName(out, program, short_description); WriteSynopsis(out, program, accepts_file_argument); WriteDescription(out, long_description); WriteOptions(out, options, option_hints); WriteCFEngine(out); WritePromiseTheory(out); WriteAvailability(out, program); WriteBugs(out); WriteSeeAlso(out); WriteAuthor(out); } cfengine-3.6.2/libutils/writer.h0000644000175100017510000000404212316547775016351 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_WRITER_H #define CFENGINE_WRITER_H /* * Abstract "writer". * * Writes passed data either to * passed FILE*, or * memory buffer */ typedef struct Writer_ Writer; #include #include Writer *FileWriter(FILE *); Writer *StringWriter(void); size_t WriterWriteF(Writer *writer, const char *fmt, ...) FUNC_ATTR_PRINTF(2, 3); size_t WriterWriteVF(Writer *writer, const char *fmt, va_list ap) FUNC_ATTR_PRINTF(2, 0); size_t WriterWrite(Writer *writer, const char *str); size_t WriterWriteLen(Writer *writer, const char *str, size_t len); size_t WriterWriteChar(Writer *writer, char c); size_t StringWriterLength(const Writer *writer); const char *StringWriterData(const Writer *writer); void WriterClose(Writer *writer); /* Returns modifiable string and destroys itself */ char *StringWriterClose(Writer *writer) FUNC_WARN_UNUSED_RESULT; /* Returns the open file and destroys itself */ FILE *FileWriterDetach(Writer *writer); /* Commonly used on a FileWriter(stdout), ignoring return; so don't * try to warn on unused result ! */ #endif cfengine-3.6.2/libutils/Makefile.in0000664000175100017510000006377012412324464016731 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @NT_FALSE@am__append_1 = unix_dir.c @CYGWIN_TRUE@am__append_2 = unix_dir.c subdir = libutils DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/config.h.in $(srcdir)/config.post.h.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = config.post.h CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libutils_la_DEPENDENCIES = ../libcompat/libcompat.la am__libutils_la_SOURCES_DIST = alloc.c alloc.h atexit.c atexit.h \ compiler.h deprecated.h dir.h dir_priv.h hashes.c hashes.h \ hash_method.h sequence.c sequence.h set.c set.h statistics.c \ statistics.h string_lib.c string_lib.h pcre_include.h \ platform.h proc_keyvalue.c proc_keyvalue.h bool.h json.c \ json.h refcount.c refcount.h list.c list.h logging.c logging.h \ logging_priv.h buffer.c buffer.h ip_address.c ip_address.h \ map.c map.h map_common.h array_map.c array_map_priv.h \ hash_map.c hash_map_priv.h misc_lib.c misc_lib.h writer.c \ writer.h csv_writer.c csv_writer.h csv_parser.c csv_parser.h \ xml_writer.c xml_writer.h file_lib.c file_lib.h man.c man.h \ rb-tree.c rb-tree.h mustache.c mustache.h cfversion.c \ cfversion.h unicode.c unicode.h hash.c hash.h queue.c queue.h \ ring_buffer.c ring_buffer.h regex.c regex.h encode.c encode.h \ printsize.h unix_dir.c @NT_FALSE@am__objects_1 = unix_dir.lo @CYGWIN_TRUE@am__objects_2 = unix_dir.lo am_libutils_la_OBJECTS = alloc.lo atexit.lo hashes.lo sequence.lo \ set.lo statistics.lo string_lib.lo proc_keyvalue.lo json.lo \ refcount.lo list.lo logging.lo buffer.lo ip_address.lo map.lo \ array_map.lo hash_map.lo misc_lib.lo writer.lo csv_writer.lo \ csv_parser.lo xml_writer.lo file_lib.lo man.lo rb-tree.lo \ mustache.lo cfversion.lo unicode.lo hash.lo queue.lo \ ring_buffer.lo regex.lo encode.lo $(am__objects_1) \ $(am__objects_2) libutils_la_OBJECTS = $(am_libutils_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libutils_la_SOURCES) DIST_SOURCES = $(am__libutils_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libutils.la # TODO remove the openssl dependency! It's only there for base64 encoding. AM_CFLAGS = $(PCRE_CFLAGS) $(OPENSSL_CFLAGS) AM_CPPFLAGS = $(PCRE_CPPFLAGS) $(OPENSSL_CPPFLAGS) AM_LDFLAGS = $(PCRE_LDFLAGS) $(OPENSSL_LDFLAGS) libutils_la_LIBADD = ../libcompat/libcompat.la libutils_la_LIBS = $(PCRE_LIBS) $(OPENSSL_LIBS) libutils_la_SOURCES = alloc.c alloc.h atexit.c atexit.h compiler.h \ deprecated.h dir.h dir_priv.h hashes.c hashes.h hash_method.h \ sequence.c sequence.h set.c set.h statistics.c statistics.h \ string_lib.c string_lib.h pcre_include.h platform.h \ proc_keyvalue.c proc_keyvalue.h bool.h json.c json.h \ refcount.c refcount.h list.c list.h logging.c logging.h \ logging_priv.h buffer.c buffer.h ip_address.c ip_address.h \ map.c map.h map_common.h array_map.c array_map_priv.h \ hash_map.c hash_map_priv.h misc_lib.c misc_lib.h writer.c \ writer.h csv_writer.c csv_writer.h csv_parser.c csv_parser.h \ xml_writer.c xml_writer.h file_lib.c file_lib.h man.c man.h \ rb-tree.c rb-tree.h mustache.c mustache.h cfversion.c \ cfversion.h unicode.c unicode.h hash.c hash.h queue.c queue.h \ ring_buffer.c ring_buffer.h regex.c regex.h encode.c encode.h \ printsize.h $(am__append_1) $(am__append_2) CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = config.h.in all: config.h $(MAKE) $(AM_MAKEFLAGS) 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) --foreign libutils/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libutils/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): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status libutils/config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 config.post.h: $(top_builddir)/config.status $(srcdir)/config.post.h.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libutils.la: $(libutils_la_OBJECTS) $(libutils_la_DEPENDENCIES) $(EXTRA_libutils_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libutils_la_OBJECTS) $(libutils_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array_map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atexit.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv_writer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash_map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_address.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/man.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mustache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc_keyvalue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rb-tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refcount.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ring_buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sequence.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistics.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_lib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unicode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix_dir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/writer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xml_writer.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) config.h 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr 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: all install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-hdr 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 tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/libutils/hash_map_priv.h0000664000175100017510000000432512400110676017637 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_HASH_MAP_PRIV_H #define CFENGINE_HASH_MAP_PRIV_H #include typedef struct BucketListItem_ { MapKeyValue value; struct BucketListItem_ *next; } BucketListItem; typedef unsigned int (*MapHashFn) (const void *p, unsigned int seed, unsigned int max); typedef struct { MapHashFn hash_fn; MapKeyEqualFn equal_fn; MapDestroyDataFn destroy_key_fn; MapDestroyDataFn destroy_value_fn; BucketListItem **buckets; } HashMap; typedef struct { HashMap *map; BucketListItem *cur; int bucket; } HashMapIterator; HashMap *HashMapNew(MapHashFn hash_fn, MapKeyEqualFn equal_fn, MapDestroyDataFn destroy_key_fn, MapDestroyDataFn destroy_value_fn); bool HashMapInsert(HashMap *map, void *key, void *value); bool HashMapRemove(HashMap *map, const void *key); MapKeyValue *HashMapGet(const HashMap *map, const void *key); void HashMapClear(HashMap *map); void HashMapSoftDestroy(HashMap *map); void HashMapDestroy(HashMap *map); void HashMapPrintStats(const HashMap *hmap, FILE *f); /******************************************************************************/ HashMapIterator HashMapIteratorInit(HashMap *m); MapKeyValue *HashMapIteratorNext(HashMapIterator *i); #endif cfengine-3.6.2/libutils/buffer.c0000664000175100017510000002711512411001073016255 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include Buffer *BufferNewWithCapacity(unsigned int initial_capacity) { Buffer *buffer = xmalloc(sizeof(Buffer)); buffer->capacity = initial_capacity; buffer->buffer = xmalloc(buffer->capacity); buffer->buffer[0] = '\0'; buffer->mode = BUFFER_BEHAVIOR_CSTRING; buffer->used = 0; return buffer; } Buffer *BufferNew(void) { return BufferNewWithCapacity(DEFAULT_BUFFER_CAPACITY); } static void ExpandIfNeeded(Buffer *buffer, unsigned int needed) { if (needed >= buffer->capacity) { size_t new_capacity = UpperPowerOfTwo(needed + 1); buffer->buffer = xrealloc(buffer->buffer, new_capacity); buffer->capacity = new_capacity; } } Buffer* BufferNewFrom(const char *data, unsigned int length) { Buffer *buffer = BufferNewWithCapacity(length + 1); BufferAppend(buffer, data, length); return buffer; } void BufferDestroy(Buffer *buffer) { if (buffer) { free(buffer->buffer); free(buffer); } } char *BufferClose(Buffer *buffer) { char *detached = buffer->buffer; free(buffer); return detached; } Buffer *BufferCopy(const Buffer *source) { return BufferNewFrom(source->buffer, source->used); } int BufferCompare(const Buffer *buffer1, const Buffer *buffer2) { assert(buffer1); assert(buffer2); /* * Rules for comparison: * 2. Check the content * 2.1. If modes are different, check until the first '\0' * 2.2. If sizes are different, check until the first buffer ends. */ if (buffer1->mode == buffer2->mode) { if (buffer1->mode == BUFFER_BEHAVIOR_CSTRING) { /* * C String comparison */ return strcmp(buffer1->buffer, buffer2->buffer); } else { /* * BUFFER_BEHAVIOR_BYTEARRAY * Byte by byte comparison */ unsigned int i = 0; if (buffer1->used < buffer2->used) { for (i = 0; i < buffer1->used; ++i) { if (buffer1->buffer[i] < buffer2->buffer[i]) { return -1; } else if (buffer1->buffer[i] > buffer2->buffer[i]) { return 1; } } return -1; } else if (buffer1->used == buffer2->used) { for (i = 0; i < buffer1->used; ++i) { if (buffer1->buffer[i] < buffer2->buffer[i]) { return -1; } else if (buffer1->buffer[i] > buffer2->buffer[i]) { return 1; } } } else { for (i = 0; i < buffer2->used; ++i) { if (buffer1->buffer[i] < buffer2->buffer[i]) { return -1; } else if (buffer1->buffer[i] > buffer2->buffer[i]) { return 1; } } return 1; } } } else { /* * Mixed comparison * Notice that every BYTEARRAY was born as a CSTRING. * When we switch back to CSTRING we adjust the length to * match the first '\0'. */ unsigned int i = 0; if (buffer1->used < buffer2->used) { for (i = 0; i < buffer1->used; ++i) { if (buffer1->buffer[i] < buffer2->buffer[i]) { return -1; } else if (buffer1->buffer[i] > buffer2->buffer[i]) { return 1; } } return -1; } else if (buffer1->used == buffer2->used) { for (i = 0; i < buffer1->used; ++i) { if (buffer1->buffer[i] < buffer2->buffer[i]) { return -1; } else if (buffer1->buffer[i] > buffer2->buffer[i]) { return 1; } } } else { for (i = 0; i < buffer2->used; ++i) { if (buffer1->buffer[i] < buffer2->buffer[i]) { return -1; } else if (buffer1->buffer[i] > buffer2->buffer[i]) { return 1; } } return 1; } } /* * We did all we could and the buffers seems to be equal. */ return 0; } void BufferSet(Buffer *buffer, const char *bytes, unsigned int length) { assert(buffer); assert(bytes); BufferClear(buffer); BufferAppend(buffer, bytes, length); } char *BufferGet(Buffer *buffer) { assert(buffer); buffer->unsafe = true; return buffer->buffer; } void BufferAppendString(Buffer *buffer, const char *str) { size_t len = strlen(str); ExpandIfNeeded(buffer, buffer->used + len + 1); memcpy(buffer->buffer + buffer->used, str, len); buffer->used += len; buffer->buffer[buffer->used] = '\0'; } void BufferAppend(Buffer *buffer, const char *bytes, unsigned int length) { assert(buffer); assert(bytes); if (length == 0) { return; } switch (buffer->mode) { case BUFFER_BEHAVIOR_CSTRING: { size_t actual_length = strnlen(bytes, length); ExpandIfNeeded(buffer, buffer->used + actual_length + 1); memcpy(buffer->buffer + buffer->used, bytes, actual_length); buffer->used += actual_length; buffer->buffer[buffer->used] = '\0'; } break; case BUFFER_BEHAVIOR_BYTEARRAY: ExpandIfNeeded(buffer, buffer->used + length); memcpy(buffer->buffer + buffer->used, bytes, length); buffer->used += length; break; } } void BufferAppendChar(Buffer *buffer, char byte) { if (buffer->used < (buffer->capacity - 1)) { buffer->buffer[buffer->used] = byte; buffer->used++; if (buffer->mode == BUFFER_BEHAVIOR_CSTRING) { buffer->buffer[buffer->used] = '\0'; } } else { BufferAppend(buffer, &byte, 1); } } void BufferAppendF(Buffer *buffer, const char *format, ...) { assert(buffer); assert(format); va_list ap; va_list aq; va_start(ap, format); va_copy(aq, ap); int printed = vsnprintf(buffer->buffer + buffer->used, buffer->capacity - buffer->used, format, aq); if (printed >= (buffer->capacity - buffer->used)) { /* * Allocate a larger buffer and retry. * Now is when having a copy of the list pays off :-) */ ExpandIfNeeded(buffer, buffer->used + printed); buffer->used = 0; printed = vsnprintf(buffer->buffer + buffer->used, buffer->capacity - buffer->used, format, ap); buffer->used += printed; } else { buffer->used += printed; } va_end(aq); va_end(ap); } int BufferPrintf(Buffer *buffer, const char *format, ...) { assert(buffer); assert(format); /* * We declare two lists, in case we need to reiterate over the list because the buffer was * too small. */ va_list ap; va_list aq; va_start(ap, format); va_copy(aq, ap); /* * We don't know how big of a buffer we will need. It might be that we have enough space * or it might be that we don't have enough space. Unfortunately, we cannot reiterate over * a va_list, so our only solution is to tell the caller to retry the call. We signal this * by returning zero. Before doing that we increase the buffer to a suitable size. * The tricky part is the implicit sharing and the reference counting, if we are not shared then * everything is easy, however if we are shared then we need a different strategy. */ int printed = vsnprintf(buffer->buffer, buffer->capacity, format, aq); if (printed >= buffer->capacity) { /* * Allocate a larger buffer and retry. * Now is when having a copy of the list pays off :-) */ ExpandIfNeeded(buffer, printed); buffer->used = 0; printed = vsnprintf(buffer->buffer, buffer->capacity, format, ap); buffer->used = printed; } else { buffer->used = printed; } va_end(aq); va_end(ap); return printed; } int BufferVPrintf(Buffer *buffer, const char *format, va_list ap) { va_list aq; va_copy(aq, ap); /* * We don't know how big of a buffer we will need. It might be that we have enough space * or it might be that we don't have enough space. Unfortunately, we cannot reiterate over * a va_list, so our only solution is to tell the caller to retry the call. We signal this * by returning zero. Before doing that we increase the buffer to a suitable size. * The tricky part is the implicit sharing and the reference counting, if we are not shared then * everything is easy, however if we are shared then we need a different strategy. */ int printed = vsnprintf(buffer->buffer, buffer->capacity, format, aq); if (printed >= buffer->capacity) { ExpandIfNeeded(buffer, printed); buffer->used = 0; printed = vsnprintf(buffer->buffer, buffer->capacity, format, ap); buffer->used = printed; } else { buffer->used = printed; } return printed; } void BufferClear(Buffer *buffer) { buffer->used = 0; buffer->buffer[0] = '\0'; } unsigned int BufferSize(Buffer *buffer) { return buffer->used; } const char *BufferData(Buffer *buffer) { return buffer->buffer; } BufferBehavior BufferMode(Buffer *buffer) { return buffer->mode; } void BufferSetMode(Buffer *buffer, BufferBehavior mode) { assert(mode == BUFFER_BEHAVIOR_CSTRING || mode == BUFFER_BEHAVIOR_BYTEARRAY); /* * If we switch from BYTEARRAY mode to CSTRING then we need to adjust the * length to the first '\0'. This makes our life easier in the long run. */ if (BUFFER_BEHAVIOR_CSTRING == mode) { for (unsigned int i = 0; i < buffer->used; ++i) { if (buffer->buffer[i] == '\0') { buffer->used = i; break; } } } buffer->mode = mode; } cfengine-3.6.2/libutils/ip_address.h0000664000175100017510000000625212411001073017125 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_IP_ADDRESS_H #define CFENGINE_IP_ADDRESS_H #include typedef struct IPAddress IPAddress; typedef enum { IP_ADDRESS_TYPE_IPV4, IP_ADDRESS_TYPE_IPV6 } IPAddressVersion; /** @brief Creates a new IPAddress object from a string. @param source Buffer containing the string representation of the ip address. @return A fully formed IPAddress object or NULL if there was an error parsing the source. */ IPAddress *IPAddressNew(Buffer *source); /** @brief Destroys an IPAddress object. @param address IPAddress object to be destroyed. */ int IPAddressDestroy(IPAddress **address); /** @brief Returns the type of address. @param address Address object. @return The type of address or -1 in case of error. */ int IPAddressType(IPAddress *address); /** @brief Produces a fully usable IPV6 or IPV4 address string representation. @param address IPAddress object. @return A buffer containing an IPV4 or IPV6 address or NULL in case the given address was invalid. */ Buffer *IPAddressGetAddress(IPAddress *address); /** @brief Recovers the appropriate port from the given address. @param address IPAddress object. @return A valid port for connections or -1 if it was not available. */ int IPAddressGetPort(IPAddress *address); /** @brief Compares two IP addresses. @param a IP address of the first object. @param b IP address of the second object. @return 1 if both addresses are equal, 0 if they are not and -1 in case of error. */ int IPAddressIsEqual(IPAddress *a, IPAddress *b); /** @brief Checks if a given string is a properly formed IP Address. @param source Buffer containing the string. @param address Optional parameter. If given and not NULL then an IPAdress structure will be created from the string. @return Returns true if the string is a valid IP Address and false if not. The address parameter is populated accordingly. */ bool IPAddressIsIPAddress(Buffer *source, IPAddress **address); /** @brief Compares two IP addresses for sorting. @param a IP address of the first object. @param b IP address of the second object. @return 1 if a < b, and 0 otherwise. */ int IPAddressCompareLess(IPAddress *a, IPAddress *b); #endif // CFENGINE_IP_ADDRESS_H cfengine-3.6.2/libutils/set.h0000644000175100017510000001656312316547775015643 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SET_H #define CFENGINE_SET_H #include #include #include typedef Map Set; typedef MapIterator SetIterator; Set *SetNew(MapHashFn element_hash_fn, MapKeyEqualFn element_equal_fn, MapDestroyDataFn element_destroy_fn); void SetDestroy(Set *set); void SetAdd(Set *set, void *element); bool SetContains(const Set *set, const void *element); bool SetRemove(Set *set, const void *element); void SetClear(Set *set); size_t SetSize(const Set *set); bool SetIsEqual(const Set *set1, const Set *set2); SetIterator SetIteratorInit(Set *set); void *SetIteratorNext(SetIterator *i); #define TYPED_SET_DECLARE(Prefix, ElementType) \ typedef struct \ { \ Set *impl; \ } Prefix##Set; \ \ typedef SetIterator Prefix##SetIterator; \ \ Prefix##Set *Prefix##SetNew(void); \ void Prefix##SetAdd(const Prefix##Set *set, ElementType element); \ bool Prefix##SetContains(const Prefix##Set *Set, const ElementType element); \ bool Prefix##SetRemove(const Prefix##Set *Set, const ElementType element); \ void Prefix##SetClear(Prefix##Set *set); \ size_t Prefix##SetSize(const Prefix##Set *set); \ bool Prefix##SetIsEqual(const Prefix##Set *set1, const Prefix##Set *set2); \ void Prefix##SetDestroy(Prefix##Set *set); \ Prefix##SetIterator Prefix##SetIteratorInit(Prefix##Set *set); \ ElementType Prefix##SetIteratorNext(Prefix##SetIterator *iter); \ #define TYPED_SET_DEFINE(Prefix, ElementType, hash_fn, equal_fn, destroy_fn) \ \ Prefix##Set *Prefix##SetNew(void) \ { \ Prefix##Set *set = xcalloc(1, sizeof(Prefix##Set)); \ set->impl = SetNew(hash_fn, equal_fn, destroy_fn); \ return set; \ } \ \ void Prefix##SetAdd(const Prefix##Set *set, ElementType element) \ { \ SetAdd(set->impl, (void *)element); \ } \ \ bool Prefix##SetContains(const Prefix##Set *set, const ElementType element) \ { \ return SetContains(set->impl, element); \ } \ \ bool Prefix##SetRemove(const Prefix##Set *set, const ElementType element) \ { \ return SetRemove(set->impl, element); \ } \ \ void Prefix##SetClear(Prefix##Set *set) \ { \ SetClear(set->impl); \ } \ \ size_t Prefix##SetSize(const Prefix##Set *set) \ { \ return SetSize(set->impl); \ } \ \ bool Prefix##SetIsEqual(const Prefix##Set *set1, const Prefix##Set *set2) \ { \ return SetIsEqual(set1->impl, set2->impl); \ } \ \ void Prefix##SetDestroy(Prefix##Set *set) \ { \ if (set) \ { \ SetDestroy(set->impl); \ free(set); \ } \ } \ \ Prefix##SetIterator Prefix##SetIteratorInit(Prefix##Set *set) \ { \ return SetIteratorInit(set->impl); \ } \ \ ElementType Prefix##SetIteratorNext(Prefix##SetIterator *iter) \ { \ return SetIteratorNext(iter); \ } \ TYPED_SET_DECLARE(String, char *) void StringSetAddSplit(StringSet *set, const char *str, char delimiter); StringSet *StringSetFromString(const char *str, char delimiter); Buffer *StringSetToBuffer(StringSet *set, const char delimiter); JsonElement *StringSetToJson(const StringSet *set); #endif cfengine-3.6.2/libutils/json.c0000664000175100017510000016325112400110676015767 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include static const int SPACES_PER_INDENT = 2; static const int DEFAULT_CONTAINER_CAPACITY = 64; static const char *const JSON_TRUE = "true"; static const char *const JSON_FALSE = "false"; static const char *const JSON_NULL = "null"; struct JsonElement_ { JsonElementType type; char *propertyName; // to avoid having a struct JsonProperty union { struct JsonContainer { JsonContainerType type; Seq *children; } container; struct JsonPrimitive { JsonPrimitiveType type; const char *value; } primitive; }; }; // ******************************************************************************************* // JsonElement Functions // ******************************************************************************************* const char *JsonPrimitiveTypeToString(JsonPrimitiveType type) { switch (type) { case JSON_PRIMITIVE_TYPE_STRING: return "string"; case JSON_PRIMITIVE_TYPE_REAL: case JSON_PRIMITIVE_TYPE_INTEGER: return "number"; case JSON_PRIMITIVE_TYPE_BOOL: return "boolean"; default: assert(false && "Never reach"); return "(null)"; } } static void JsonElementSetPropertyName(JsonElement *element, const char *propertyName) { assert(element); if (element->propertyName) { free(element->propertyName); element->propertyName = NULL; } if (propertyName) { element->propertyName = xstrdup(propertyName); } } static JsonElement *JsonElementCreateContainer(JsonContainerType containerType, const char *propertyName, size_t initialCapacity) { JsonElement *element = xcalloc(1, sizeof(JsonElement)); element->type = JSON_ELEMENT_TYPE_CONTAINER; JsonElementSetPropertyName(element, propertyName); element->container.type = containerType; element->container.children = SeqNew(initialCapacity, JsonDestroy); return element; } static JsonElement *JsonElementCreatePrimitive(JsonPrimitiveType primitiveType, const char *value) { JsonElement *element = xcalloc(1, sizeof(JsonElement)); element->type = JSON_ELEMENT_TYPE_PRIMITIVE; element->primitive.type = primitiveType; element->primitive.value = value; return element; } static JsonElement *JsonArrayCopy(const JsonElement *array) { assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); JsonElement *copy = JsonArrayCreate(JsonLength(array)); JsonIterator iter = JsonIteratorInit(array); const JsonElement *child = NULL; while ((child = JsonIteratorNextValue(&iter))) { JsonArrayAppendElement(copy, JsonCopy(child)); } return copy; } static JsonElement *JsonObjectCopy(const JsonElement *object) { assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); JsonElement *copy = JsonObjectCreate(JsonLength(object)); JsonIterator iter = JsonIteratorInit(object); const JsonElement *child = NULL; while ((child = JsonIteratorNextValue(&iter))) { JsonObjectAppendElement(copy, JsonIteratorCurrentKey(&iter), JsonCopy(child)); } return copy; } static JsonElement *JsonContainerCopy(const JsonElement *container) { assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); switch (container->container.type) { case JSON_CONTAINER_TYPE_ARRAY: return JsonArrayCopy(container); case JSON_CONTAINER_TYPE_OBJECT: return JsonObjectCopy(container); } assert(false); return NULL; } static JsonElement *JsonPrimitiveCopy(const JsonElement *primitive) { assert(primitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); switch (primitive->primitive.type) { case JSON_PRIMITIVE_TYPE_BOOL: return JsonBoolCreate(JsonPrimitiveGetAsBool(primitive)); case JSON_PRIMITIVE_TYPE_INTEGER: return JsonIntegerCreate(JsonPrimitiveGetAsInteger(primitive)); case JSON_PRIMITIVE_TYPE_NULL: return JsonNullCreate(); case JSON_PRIMITIVE_TYPE_REAL: return JsonRealCreate(JsonPrimitiveGetAsReal(primitive)); case JSON_PRIMITIVE_TYPE_STRING: return JsonStringCreate(JsonPrimitiveGetAsString(primitive)); } assert(false); return NULL; } JsonElement *JsonCopy(const JsonElement *element) { switch (element->type) { case JSON_ELEMENT_TYPE_CONTAINER: return JsonContainerCopy(element); case JSON_ELEMENT_TYPE_PRIMITIVE: return JsonPrimitiveCopy(element); } assert(false); return NULL; } static int JsonArrayCompare(const JsonElement *a, const JsonElement *b) { assert(a->type == JSON_ELEMENT_TYPE_CONTAINER); assert(a->container.type == JSON_CONTAINER_TYPE_ARRAY); assert(b->type == JSON_ELEMENT_TYPE_CONTAINER); assert(b->container.type == JSON_CONTAINER_TYPE_ARRAY); int ret = JsonLength(a) - JsonLength(b); if (ret != 0) { return ret; } JsonIterator iter_a = JsonIteratorInit(a); JsonIterator iter_b = JsonIteratorInit(a); for (size_t i = 0; i < JsonLength(a); i++) { const JsonElement *child_a = JsonIteratorNextValue(&iter_a); const JsonElement *child_b = JsonIteratorNextValue(&iter_b); ret = JsonCompare(child_a, child_b); if (ret != 0) { return ret; } } return ret; } static int JsonObjectCompare(const JsonElement *a, const JsonElement *b) { assert(a->type == JSON_ELEMENT_TYPE_CONTAINER); assert(a->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(b->type == JSON_ELEMENT_TYPE_CONTAINER); assert(b->container.type == JSON_CONTAINER_TYPE_OBJECT); int ret = JsonLength(a) - JsonLength(b); if (ret != 0) { return ret; } JsonIterator iter_a = JsonIteratorInit(a); JsonIterator iter_b = JsonIteratorInit(a); for (size_t i = 0; i < JsonLength(a); i++) { const JsonElement *child_a = JsonIteratorNextValue(&iter_a); const JsonElement *child_b = JsonIteratorNextValue(&iter_b); ret = strcmp(JsonIteratorCurrentKey(&iter_a), JsonIteratorCurrentKey(&iter_b)); if (ret != 0) { return ret; } ret = JsonCompare(child_a, child_b); if (ret != 0) { return ret; } } return ret; } static int JsonContainerCompare(const JsonElement *a, const JsonElement *b) { assert(a->type == JSON_ELEMENT_TYPE_CONTAINER); assert(b->type == JSON_ELEMENT_TYPE_CONTAINER); if (a->container.type != b->container.type) { return a->container.type - b->container.type; } switch (a->container.type) { case JSON_CONTAINER_TYPE_ARRAY: return JsonArrayCompare(a, b); case JSON_CONTAINER_TYPE_OBJECT: return JsonObjectCompare(a, b); } assert(false); return -1; } int JsonCompare(const JsonElement *a, const JsonElement *b) { if (a->type != b->type) { return a->type - b->type; } switch (a->type) { case JSON_ELEMENT_TYPE_CONTAINER: return JsonContainerCompare(a, b); case JSON_ELEMENT_TYPE_PRIMITIVE: return strcmp(a->primitive.value, b->primitive.value); } assert(false); return -1; } void JsonDestroy(JsonElement *element) { if (element) { switch (element->type) { case JSON_ELEMENT_TYPE_CONTAINER: assert(element->container.children); SeqDestroy(element->container.children); element->container.children = NULL; break; case JSON_ELEMENT_TYPE_PRIMITIVE: assert(element->primitive.value); if (element->primitive.type != JSON_PRIMITIVE_TYPE_NULL && element->primitive.type != JSON_PRIMITIVE_TYPE_BOOL) { free((void *) element->primitive.value); } element->primitive.value = NULL; break; } if (element->propertyName) { free(element->propertyName); } free(element); } } JsonElement *JsonArrayMergeArray(const JsonElement *a, const JsonElement *b) { assert(JsonGetElementType(a) == JsonGetElementType(b)); assert(JsonGetElementType(a) == JSON_ELEMENT_TYPE_CONTAINER); assert(JsonGetContainerType(a) == JsonGetContainerType(b)); assert(JsonGetContainerType(a) == JSON_CONTAINER_TYPE_ARRAY); JsonElement *result = JsonArrayCreate(JsonLength(a) + JsonLength(b)); for (size_t i = 0; i < JsonLength(a); i++) { JsonArrayAppendElement(result, JsonCopy(JsonAt(a, i))); } for (size_t i = 0; i < JsonLength(b); i++) { JsonArrayAppendElement(result, JsonCopy(JsonAt(b, i))); } return result; } JsonElement *JsonObjectMergeArray(const JsonElement *a, const JsonElement *b) { assert(JsonGetElementType(a) == JsonGetElementType(b)); assert(JsonGetElementType(a) == JSON_ELEMENT_TYPE_CONTAINER); assert(JsonGetContainerType(a) == JSON_CONTAINER_TYPE_OBJECT); assert(JsonGetContainerType(b) == JSON_CONTAINER_TYPE_ARRAY); JsonElement *result = JsonObjectCopy(a); for (size_t i = 0; i < JsonLength(b); i++) { char *key = StringFromLong(i); JsonObjectAppendElement(result, key, JsonCopy(JsonAt(b, i))); free(key); } return result; } JsonElement *JsonObjectMergeObject(const JsonElement *a, const JsonElement *b) { assert(JsonGetElementType(a) == JsonGetElementType(b)); assert(JsonGetElementType(a) == JSON_ELEMENT_TYPE_CONTAINER); assert(JsonGetContainerType(a) == JSON_CONTAINER_TYPE_OBJECT); assert(JsonGetContainerType(b) == JSON_CONTAINER_TYPE_OBJECT); JsonElement *result = JsonObjectCopy(a); JsonIterator iter = JsonIteratorInit(b); const char *key; while ((key = JsonIteratorNextKey(&iter))) { JsonObjectAppendElement(result, key, JsonCopy(JsonIteratorCurrentValue(&iter))); } return result; } JsonElement *JsonMerge(const JsonElement *a, const JsonElement *b) { assert(JsonGetElementType(a) == JsonGetElementType(b)); assert(JsonGetElementType(a) == JSON_ELEMENT_TYPE_CONTAINER); switch (JsonGetContainerType(a)) { case JSON_CONTAINER_TYPE_ARRAY: switch (JsonGetContainerType(b)) { case JSON_CONTAINER_TYPE_ARRAY: return JsonArrayMergeArray(a, b); case JSON_CONTAINER_TYPE_OBJECT: return JsonObjectMergeArray(b, a); } assert(false && "never reach"); break; case JSON_CONTAINER_TYPE_OBJECT: switch (JsonGetContainerType(b)) { case JSON_CONTAINER_TYPE_OBJECT: return JsonObjectMergeObject(a, b); case JSON_CONTAINER_TYPE_ARRAY: return JsonObjectMergeArray(a, b); } assert(false && "never reach"); break; } assert(false && "never reach"); return NULL; } size_t JsonLength(const JsonElement *element) { assert(element); switch (element->type) { case JSON_ELEMENT_TYPE_CONTAINER: return element->container.children->length; case JSON_ELEMENT_TYPE_PRIMITIVE: return strlen(element->primitive.value); } return -1; // appease gcc } JsonIterator JsonIteratorInit(const JsonElement *container) { assert(container); assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); return (JsonIterator) { container, 0 }; } const char *JsonIteratorNextKey(JsonIterator *iter) { assert(iter); assert(iter->container->type == JSON_ELEMENT_TYPE_CONTAINER); assert(iter->container->container.type == JSON_CONTAINER_TYPE_OBJECT); const JsonElement *child = JsonIteratorNextValue(iter); return child ? child->propertyName : NULL; } const JsonElement *JsonIteratorNextValue(JsonIterator *iter) { assert(iter); assert(iter->container->type == JSON_ELEMENT_TYPE_CONTAINER); if (iter->index >= JsonLength(iter->container)) { return NULL; } return iter->container->container.children->data[iter->index++]; } const JsonElement *JsonIteratorNextValueByType(JsonIterator *iter, JsonElementType type, bool skip_null) { const JsonElement *e = NULL; while ((e = JsonIteratorNextValue(iter))) { if (skip_null && JsonGetElementType(e) == JSON_ELEMENT_TYPE_PRIMITIVE && JsonGetPrimitiveType(e) == JSON_PRIMITIVE_TYPE_NULL) { continue; } if (e->type == type) { return e; } } return NULL; } const JsonElement *JsonIteratorCurrentValue(const JsonIterator *iter) { assert(iter); assert(iter->container->type == JSON_ELEMENT_TYPE_CONTAINER); if (iter->index == 0 || iter->index > JsonLength(iter->container)) { return NULL; } return iter->container->container.children->data[(iter->index) - 1]; } const char *JsonIteratorCurrentKey(const JsonIterator *iter) { assert(iter); assert(iter->container->type == JSON_ELEMENT_TYPE_CONTAINER); assert(iter->container->container.type == JSON_CONTAINER_TYPE_OBJECT); const JsonElement *child = JsonIteratorCurrentValue(iter); return child ? child->propertyName : NULL; } JsonElementType JsonIteratorCurrentElementType(const JsonIterator *iter) { assert(iter); const JsonElement *child = JsonIteratorCurrentValue(iter); return child->type; } JsonContainerType JsonIteratorCurrentContainerType(const JsonIterator *iter) { assert(iter); const JsonElement *child = JsonIteratorCurrentValue(iter); assert(child->type == JSON_ELEMENT_TYPE_CONTAINER); return child->container.type; } JsonPrimitiveType JsonIteratorCurrentPrimitiveType(const JsonIterator *iter) { assert(iter); const JsonElement *child = JsonIteratorCurrentValue(iter); assert(child->type == JSON_ELEMENT_TYPE_PRIMITIVE); return child->primitive.type; } bool JsonIteratorHasMore(const JsonIterator *iter) { assert(iter); return iter->index < JsonLength(iter->container); } JsonElementType JsonGetElementType(const JsonElement *element) { assert(element); return element->type; } JsonContainerType JsonGetContainerType(const JsonElement *container) { assert(container); assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); return container->container.type; } JsonPrimitiveType JsonGetPrimitiveType(const JsonElement *primitive) { assert(primitive); assert(primitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); return primitive->primitive.type; } const char *JsonPrimitiveGetAsString(const JsonElement *primitive) { assert(primitive); assert(primitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); return primitive->primitive.value; } bool JsonPrimitiveGetAsBool(const JsonElement *primitive) { assert(primitive); assert(primitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); assert(primitive->primitive.type == JSON_PRIMITIVE_TYPE_BOOL); return StringSafeEqual(JSON_TRUE, primitive->primitive.value); } long JsonPrimitiveGetAsInteger(const JsonElement *primitive) { assert(primitive); assert(primitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); assert(primitive->primitive.type == JSON_PRIMITIVE_TYPE_INTEGER); return StringToLong(primitive->primitive.value); } double JsonPrimitiveGetAsReal(const JsonElement *primitive) { assert(primitive); assert(primitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); assert(primitive->primitive.type == JSON_PRIMITIVE_TYPE_REAL); return StringToDouble(primitive->primitive.value); } const char *JsonGetPropertyAsString(const JsonElement *element) { assert(element); return element->propertyName; } void JsonSort(JsonElement *container, JsonComparator *Compare, void *user_data) { assert(container); assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); SeqSort(container->container.children, (SeqItemComparator)Compare, user_data); } JsonElement *JsonAt(const JsonElement *container, size_t index) { assert(container); assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); assert(index < JsonLength(container)); return container->container.children->data[index]; } JsonElement *JsonSelect(JsonElement *element, size_t num_indices, char **indices) { if (num_indices == 0) { return element; } else { if (JsonGetElementType(element) != JSON_ELEMENT_TYPE_CONTAINER) { return NULL; } const char *index = indices[0]; switch (JsonGetContainerType(element)) { case JSON_CONTAINER_TYPE_OBJECT: { JsonElement *child = JsonObjectGet(element, index); if (child) { return JsonSelect(child, num_indices - 1, indices + 1); } } return NULL; case JSON_CONTAINER_TYPE_ARRAY: if (StringIsNumeric(index)) { size_t i = StringToLong(index); if (i < JsonLength(element)) { JsonElement *child = JsonArrayGet(element, i); if (child) { return JsonSelect(child, num_indices - 1, indices + 1); } } } return NULL; } } assert(false); return NULL; } // ******************************************************************************************* // JsonObject Functions // ******************************************************************************************* JsonElement *JsonObjectCreate(size_t initialCapacity) { return JsonElementCreateContainer(JSON_CONTAINER_TYPE_OBJECT, NULL, initialCapacity); } static char *JsonEncodeString(const char *unescaped_string) { assert(unescaped_string); Writer *writer = StringWriter(); for (const char *c = unescaped_string; *c != '\0'; c++) { switch (*c) { case '\"': case '\\': WriterWriteChar(writer, '\\'); WriterWriteChar(writer, *c); break; case '\b': WriterWriteChar(writer, '\\'); WriterWriteChar(writer, 'b'); break; case '\f': WriterWriteChar(writer, '\\'); WriterWriteChar(writer, 'f'); break; case '\n': WriterWriteChar(writer, '\\'); WriterWriteChar(writer, 'n'); break; case '\r': WriterWriteChar(writer, '\\'); WriterWriteChar(writer, 'r'); break; case '\t': WriterWriteChar(writer, '\\'); WriterWriteChar(writer, 't'); break; default: WriterWriteChar(writer, *c); } } return StringWriterClose(writer); } static char *JsonDecodeString(const char *encoded_string) { assert(encoded_string); Writer *w = StringWriter(); for (const char *c = encoded_string; *c != '\0'; c++) { switch (*c) { case '\\': switch (c[1]) { case '\"': case '\\': WriterWriteChar(w, c[1]); c++; break; case 'b': WriterWriteChar(w, '\b'); c++; break; case 'f': WriterWriteChar(w, '\f'); c++; break; case 'n': WriterWriteChar(w, '\n'); c++; break; case 'r': WriterWriteChar(w, '\r'); c++; break; case 't': WriterWriteChar(w, '\t'); c++; break; default: WriterWriteChar(w, *c); break; } break; default: WriterWriteChar(w, *c); break; } } return StringWriterClose(w); } void JsonObjectAppendString(JsonElement *object, const char *key, const char *value) { JsonElement *child = JsonStringCreate(value); JsonObjectAppendElement(object, key, child); } void JsonObjectAppendInteger(JsonElement *object, const char *key, int value) { JsonElement *child = JsonIntegerCreate(value); JsonObjectAppendElement(object, key, child); } void JsonObjectAppendBool(JsonElement *object, const char *key, _Bool value) { JsonElement *child = JsonBoolCreate(value); JsonObjectAppendElement(object, key, child); } void JsonObjectAppendReal(JsonElement *object, const char *key, double value) { JsonElement *child = JsonRealCreate(value); JsonObjectAppendElement(object, key, child); } void JsonObjectAppendNull(JsonElement *object, const char *key) { JsonElement *child = JsonNullCreate(); JsonObjectAppendElement(object, key, child); } void JsonObjectAppendArray(JsonElement *object, const char *key, JsonElement *array) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); JsonObjectAppendElement(object, key, array); } void JsonObjectAppendObject(JsonElement *object, const char *key, JsonElement *childObject) { assert(childObject); assert(childObject->type == JSON_ELEMENT_TYPE_CONTAINER); assert(childObject->container.type == JSON_CONTAINER_TYPE_OBJECT); JsonObjectAppendElement(object, key, childObject); } void JsonObjectAppendElement(JsonElement *object, const char *key, JsonElement *element) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); assert(element); JsonObjectRemoveKey(object, key); JsonElementSetPropertyName(element, key); SeqAppend(object->container.children, element); } static int JsonElementHasProperty(const void *propertyName, const void *jsonElement, ARG_UNUSED void *user_data) { assert(propertyName); const JsonElement *element = jsonElement; assert(element->propertyName); if (strcmp(propertyName, element->propertyName) == 0) { return 0; } return -1; } static int CompareKeyToPropertyName(const void *a, const void *b, ARG_UNUSED void *user_data) { return StringSafeCompare((char*)a, ((JsonElement*)b)->propertyName); } static ssize_t JsonElementIndexInParentObject(JsonElement *parent, const char* key) { assert(parent); assert(parent->type == JSON_ELEMENT_TYPE_CONTAINER); assert(parent->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); return SeqIndexOf(parent->container.children, key, CompareKeyToPropertyName); } bool JsonObjectRemoveKey(JsonElement *object, const char *key) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); ssize_t index = JsonElementIndexInParentObject(object, key); if (index != -1) { SeqRemove(object->container.children, index); return true; } return false; } JsonElement *JsonObjectDetachKey(JsonElement *object, const char *key) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); JsonElement *detached = NULL; ssize_t index = JsonElementIndexInParentObject(object, key); if (index != -1) { detached = SeqLookup(object->container.children, key, JsonElementHasProperty); SeqSoftRemove(object->container.children, index); } return detached; } const char *JsonObjectGetAsString(const JsonElement *object, const char *key) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); JsonElement *childPrimitive = SeqLookup(object->container.children, key, JsonElementHasProperty); if (childPrimitive) { assert(childPrimitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); assert(childPrimitive->primitive.type == JSON_PRIMITIVE_TYPE_STRING); return childPrimitive->primitive.value; } return NULL; } JsonElement *JsonObjectGetAsObject(JsonElement *object, const char *key) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); JsonElement *childPrimitive = SeqLookup(object->container.children, key, JsonElementHasProperty); if (childPrimitive) { assert(childPrimitive->type == JSON_ELEMENT_TYPE_CONTAINER); assert(childPrimitive->container.type == JSON_CONTAINER_TYPE_OBJECT); return childPrimitive; } return NULL; } JsonElement *JsonObjectGetAsArray(JsonElement *object, const char *key) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); JsonElement *childPrimitive = SeqLookup(object->container.children, key, JsonElementHasProperty); if (childPrimitive) { assert(childPrimitive->type == JSON_ELEMENT_TYPE_CONTAINER); assert(childPrimitive->container.type == JSON_CONTAINER_TYPE_ARRAY); return childPrimitive; } return NULL; } JsonElement *JsonObjectGet(const JsonElement *object, const char *key) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); assert(key); return SeqLookup(object->container.children, key, JsonElementHasProperty); } // ******************************************************************************************* // JsonArray Functions // ******************************************************************************************* JsonElement *JsonArrayCreate(size_t initialCapacity) { return JsonElementCreateContainer(JSON_CONTAINER_TYPE_ARRAY, NULL, initialCapacity); } void JsonArrayAppendString(JsonElement *array, const char *value) { JsonElement *child = JsonStringCreate(value); JsonArrayAppendElement(array, child); } void JsonArrayAppendBool(JsonElement *array, bool value) { JsonElement *child = JsonBoolCreate(value); JsonArrayAppendElement(array, child); } void JsonArrayAppendInteger(JsonElement *array, int value) { JsonElement *child = JsonIntegerCreate(value); JsonArrayAppendElement(array, child); } void JsonArrayAppendReal(JsonElement *array, double value) { JsonElement *child = JsonRealCreate(value); JsonArrayAppendElement(array, child); } void JsonArrayAppendNull(JsonElement *array) { JsonElement *child = JsonNullCreate(); JsonArrayAppendElement(array, child); } void JsonArrayAppendArray(JsonElement *array, JsonElement *childArray) { assert(childArray); assert(childArray->type == JSON_ELEMENT_TYPE_CONTAINER); assert(childArray->container.type == JSON_CONTAINER_TYPE_ARRAY); JsonArrayAppendElement(array, childArray); } void JsonArrayAppendObject(JsonElement *array, JsonElement *object) { assert(object); assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); JsonArrayAppendElement(array, object); } void JsonArrayAppendElement(JsonElement *array, JsonElement *element) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); assert(element); SeqAppend(array->container.children, element); } void JsonArrayRemoveRange(JsonElement *array, size_t start, size_t end) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); assert(end < array->container.children->length); assert(start <= end); SeqRemoveRange(array->container.children, start, end); } const char *JsonArrayGetAsString(JsonElement *array, size_t index) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); assert(index < array->container.children->length); JsonElement *childPrimitive = array->container.children->data[index]; if (childPrimitive) { assert(childPrimitive->type == JSON_ELEMENT_TYPE_PRIMITIVE); assert(childPrimitive->primitive.type == JSON_PRIMITIVE_TYPE_STRING); return childPrimitive->primitive.value; } return NULL; } JsonElement *JsonArrayGetAsObject(JsonElement *array, size_t index) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); assert(index < array->container.children->length); JsonElement *child = array->container.children->data[index]; if (child) { assert(child->type == JSON_ELEMENT_TYPE_CONTAINER); assert(child->container.type == JSON_CONTAINER_TYPE_OBJECT); return child; } return NULL; } JsonElement *JsonArrayGet(JsonElement *array, size_t index) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); return JsonAt(array, index); } void JsonContainerReverse(JsonElement *array) { assert(array); assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); SeqReverse(array->container.children); } // ******************************************************************************************* // Primitive Functions // ******************************************************************************************* JsonElement *JsonStringCreate(const char *value) { assert(value); return JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_STRING, xstrdup(value)); } JsonElement *JsonIntegerCreate(int value) { char *buffer; xasprintf(&buffer, "%d", value); return JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_INTEGER, buffer); } JsonElement *JsonRealCreate(double value) { if (isnan(value) || !isfinite(value)) { value = 0.0; } char *buffer = xcalloc(32, sizeof(char)); snprintf(buffer, 32, "%.4f", value); return JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_REAL, buffer); } JsonElement *JsonBoolCreate(bool value) { return JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_BOOL, value ? JSON_TRUE : JSON_FALSE); } JsonElement *JsonNullCreate() { return JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_NULL, JSON_NULL); } // ******************************************************************************************* // Printing // ******************************************************************************************* static void JsonContainerWrite(Writer *writer, const JsonElement *containerElement, size_t indent_level); static void JsonContainerWriteCompact(Writer *writer, const JsonElement *containerElement); static bool IsWhitespace(char ch) { return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; } static bool IsSeparator(char ch) { return IsWhitespace(ch) || ch == ',' || ch == ']' || ch == '}'; } static bool IsDigit(char ch) { // [1,9] return ch >= 49 && ch <= 57; } static void PrintIndent(Writer *writer, int num) { int i = 0; for (i = 0; i < num * SPACES_PER_INDENT; i++) { WriterWriteChar(writer, ' '); } } static void JsonPrimitiveWrite(Writer *writer, const JsonElement *primitiveElement, size_t indent_level) { assert(primitiveElement->type == JSON_ELEMENT_TYPE_PRIMITIVE); switch (primitiveElement->primitive.type) { case JSON_PRIMITIVE_TYPE_STRING: PrintIndent(writer, indent_level); { char *encoded = JsonEncodeString(primitiveElement->primitive.value); WriterWriteF(writer, "\"%s\"", encoded); free(encoded); } break; default: PrintIndent(writer, indent_level); WriterWrite(writer, primitiveElement->primitive.value); break; } } static void JsonArrayWrite(Writer *writer, const JsonElement *array, size_t indent_level) { assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); if (JsonLength(array) == 0) { WriterWrite(writer, "[]"); return; } WriterWrite(writer, "[\n"); for (size_t i = 0; i < array->container.children->length; i++) { JsonElement *child = array->container.children->data[i]; switch (child->type) { case JSON_ELEMENT_TYPE_PRIMITIVE: JsonPrimitiveWrite(writer, child, indent_level + 1); break; case JSON_ELEMENT_TYPE_CONTAINER: PrintIndent(writer, indent_level + 1); JsonContainerWrite(writer, child, indent_level + 1); break; } if (i < array->container.children->length - 1) { WriterWrite(writer, ",\n"); } else { WriterWrite(writer, "\n"); } } PrintIndent(writer, indent_level); WriterWriteChar(writer, ']'); } void JsonObjectWrite(Writer *writer, const JsonElement *object, size_t indent_level) { assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); WriterWrite(writer, "{\n"); for (size_t i = 0; i < object->container.children->length; i++) { JsonElement *child = object->container.children->data[i]; PrintIndent(writer, indent_level + 1); assert(child->propertyName); WriterWriteF(writer, "\"%s\": ", child->propertyName); switch (child->type) { case JSON_ELEMENT_TYPE_PRIMITIVE: JsonPrimitiveWrite(writer, child, 0); break; case JSON_ELEMENT_TYPE_CONTAINER: JsonContainerWrite(writer, child, indent_level + 1); break; } if (i < object->container.children->length - 1) { WriterWriteChar(writer, ','); } WriterWrite(writer, "\n"); } PrintIndent(writer, indent_level); WriterWriteChar(writer, '}'); } static void JsonContainerWrite(Writer *writer, const JsonElement *container, size_t indent_level) { assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); switch (container->container.type) { case JSON_CONTAINER_TYPE_OBJECT: JsonObjectWrite(writer, container, indent_level); break; case JSON_CONTAINER_TYPE_ARRAY: JsonArrayWrite(writer, container, indent_level); } } void JsonWrite(Writer *writer, const JsonElement *element, size_t indent_level) { assert(writer); assert(element); switch (element->type) { case JSON_ELEMENT_TYPE_CONTAINER: JsonContainerWrite(writer, element, indent_level); break; case JSON_ELEMENT_TYPE_PRIMITIVE: JsonPrimitiveWrite(writer, element, indent_level); break; } } static void JsonArrayWriteCompact(Writer *writer, const JsonElement *array) { assert(array->type == JSON_ELEMENT_TYPE_CONTAINER); assert(array->container.type == JSON_CONTAINER_TYPE_ARRAY); if (JsonLength(array) == 0) { WriterWrite(writer, "[]"); return; } WriterWrite(writer, "["); for (size_t i = 0; i < array->container.children->length; i++) { JsonElement *child = array->container.children->data[i]; switch (child->type) { case JSON_ELEMENT_TYPE_PRIMITIVE: JsonPrimitiveWrite(writer, child, 0); break; case JSON_ELEMENT_TYPE_CONTAINER: JsonContainerWriteCompact(writer, child); break; } if (i < array->container.children->length - 1) { WriterWrite(writer, ","); } } WriterWriteChar(writer, ']'); } void JsonObjectWriteCompact(Writer *writer, const JsonElement *object) { assert(object->type == JSON_ELEMENT_TYPE_CONTAINER); assert(object->container.type == JSON_CONTAINER_TYPE_OBJECT); WriterWrite(writer, "{"); for (size_t i = 0; i < object->container.children->length; i++) { JsonElement *child = object->container.children->data[i]; assert(child->propertyName); WriterWriteF(writer, "\"%s\":", child->propertyName); switch (child->type) { case JSON_ELEMENT_TYPE_PRIMITIVE: JsonPrimitiveWrite(writer, child, 0); break; case JSON_ELEMENT_TYPE_CONTAINER: JsonContainerWriteCompact(writer, child); break; } if (i < object->container.children->length - 1) { WriterWriteChar(writer, ','); } } WriterWriteChar(writer, '}'); } static void JsonContainerWriteCompact(Writer *writer, const JsonElement *container) { assert(container->type == JSON_ELEMENT_TYPE_CONTAINER); switch (container->container.type) { case JSON_CONTAINER_TYPE_OBJECT: JsonObjectWriteCompact(writer, container); break; case JSON_CONTAINER_TYPE_ARRAY: JsonArrayWriteCompact(writer, container); } } void JsonWriteCompact(Writer *w, const JsonElement *element) { assert(w); assert(element); switch (element->type) { case JSON_ELEMENT_TYPE_CONTAINER: JsonContainerWriteCompact(w, element); break; case JSON_ELEMENT_TYPE_PRIMITIVE: JsonPrimitiveWrite(w, element, 0); break; } } // ******************************************************************************************* // Parsing // ******************************************************************************************* static JsonParseError JsonParseAsObject(const char **data, JsonElement **json_out); static JsonElement *JsonParseAsBoolean(const char **data) { if (StringMatch("^true", *data, NULL, NULL)) { char next = *(*data + 4); if (IsSeparator(next) || next == '\0') { *data += 3; return JsonBoolCreate(true); } } else if (StringMatch("^false", *data, NULL, NULL)) { char next = *(*data + 5); if (IsSeparator(next) || next == '\0') { *data += 4; return JsonBoolCreate(false); } } return NULL; } static JsonElement *JsonParseAsNull(const char **data) { if (StringMatch("^null", *data, NULL, NULL)) { char next = *(*data + 4); if (IsSeparator(next) || next == '\0') { *data += 3; return JsonNullCreate(); } } return NULL; } const char* JsonParseErrorToString(JsonParseError error) { static const char *const parse_errors[JSON_PARSE_ERROR_MAX] = { [JSON_PARSE_OK] = "Success", [JSON_PARSE_ERROR_STRING_NO_DOUBLEQUOTE_START] = "Unable to parse json data as string, did not start with doublequote", [JSON_PARSE_ERROR_STRING_NO_DOUBLEQUOTE_END] = "Unable to parse json data as string, did not end with doublequote", [JSON_PARSE_ERROR_STRING_UNSUPPORTED_ESCAPE] = "Unsupported escape sequence", [JSON_PARSE_ERROR_NUMBER_EXPONENT_NEGATIVE] = "Unable to parse json data as number, - not at the start or not after exponent", [JSON_PARSE_ERROR_NUMBER_EXPONENT_POSITIVE] = "Unable to parse json data as number, + without preceding exponent", [JSON_PARSE_ERROR_NUMBER_DUPLICATE_ZERO] = "Unable to parse json data as number, started with 0 before dot or exponent, duplicate 0 seen", [JSON_PARSE_ERROR_NUMBER_NO_DIGIT] = "Unable to parse json data as number, dot not preceded by digit", [JSON_PARSE_ERROR_NUMBER_EXPONENT_DUPLICATE] = "Unable to parse json data as number, duplicate exponent", [JSON_PARSE_ERROR_NUMBER_EXPONENT_DIGIT] = "Unable to parse json data as number, exponent without preceding digit", [JSON_PARSE_ERROR_NUMBER_EXPONENT_FOLLOW_LEADING_ZERO] = "Unable to parse json data as number, dot or exponent must follow leading 0", [JSON_PARSE_ERROR_NUMBER_BAD_SYMBOL] = "Unable to parse json data as number, invalid symbol", [JSON_PARSE_ERROR_NUMBER_DIGIT_END] = "Unable to parse json data as string, did not end with digit", [JSON_PARSE_ERROR_ARRAY_START] = "Unable to parse json data as array, did not start with '['", [JSON_PARSE_ERROR_ARRAY_END] = "Unable to parse json data as array, did not end with ']'", [JSON_PARSE_ERROR_OBJECT_BAD_SYMBOL] = "Unable to parse json data as object, unrecognized token beginning entry", [JSON_PARSE_ERROR_OBJECT_START] = "Unable to parse json data as object, did not start with '{'", [JSON_PARSE_ERROR_OBJECT_END] = "Unable to parse json data as string, did not end with '}'", [JSON_PARSE_ERROR_OBJECT_COLON] = "Unable to parse json data as object, ':' seen without having specified an l-value", [JSON_PARSE_ERROR_OBJECT_COMMA] = "Unable to parse json data as object, ',' seen without having specified an r-value", [JSON_PARSE_ERROR_OBJECT_ARRAY_LVAL] = "Unable to parse json data as object, array not allowed as l-value", [JSON_PARSE_ERROR_OBJECT_OBJECT_LVAL] = "Unable to parse json data as object, object not allowed as l-value", [JSON_PARSE_ERROR_OBJECT_OPEN_LVAL] = "Unable to parse json data as object, tried to close object having opened an l-value", [JSON_PARSE_ERROR_INVALID_START] = "Unwilling to parse json data starting with invalid character", [JSON_PARSE_ERROR_NO_DATA] = "No data" }; assert(error < JSON_PARSE_ERROR_MAX); return parse_errors[error]; } static JsonParseError JsonParseAsString(const char **data, char **str_out) { if (**data != '"') { *str_out = NULL; return JSON_PARSE_ERROR_STRING_NO_DOUBLEQUOTE_START; } Writer *writer = StringWriter(); for (*data = *data + 1; **data != '\0'; *data = *data + 1) { switch (**data) { case '"': *str_out = StringWriterClose(writer); return JSON_PARSE_OK; case '\\': *data = *data + 1; switch (**data) { case '\\': case '"': case '/': WriterWriteChar(writer, **data); continue; case 'b': WriterWriteChar(writer, '\b'); continue; case 'f': WriterWriteChar(writer, '\f'); continue; case 'n': WriterWriteChar(writer, '\n'); continue; case 'r': WriterWriteChar(writer, '\r'); continue; case 't': WriterWriteChar(writer, '\t'); continue; default: WriterClose(writer); *str_out = NULL; return JSON_PARSE_ERROR_STRING_UNSUPPORTED_ESCAPE; } default: WriterWriteChar(writer, **data); continue; } } WriterClose(writer); *str_out = NULL; return JSON_PARSE_ERROR_STRING_NO_DOUBLEQUOTE_END; } static JsonParseError JsonParseAsNumber(const char **data, JsonElement **json_out) { Writer *writer = StringWriter(); bool zero_started = false; bool seen_dot = false; bool seen_exponent = false; char prev_char = 0; for (*data = *data; **data != '\0' && !IsSeparator(**data); prev_char = **data, *data = *data + 1) { switch (**data) { case '-': if (prev_char != 0 && prev_char != 'e' && prev_char != 'E') { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_EXPONENT_NEGATIVE; } break; case '+': if (prev_char != 'e' && prev_char != 'E') { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_EXPONENT_POSITIVE; } break; case '0': if (zero_started && !seen_dot && !seen_exponent) { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_DUPLICATE_ZERO; } if (prev_char == 0) { zero_started = true; } break; case '.': if (prev_char != '0' && !IsDigit(prev_char)) { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_NO_DIGIT; } seen_dot = true; break; case 'e': case 'E': if (seen_exponent) { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_EXPONENT_DUPLICATE; } else if (!IsDigit(prev_char) && prev_char != '0') { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_EXPONENT_DIGIT; } seen_exponent = true; break; default: if (zero_started && !seen_dot && !seen_exponent) { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_EXPONENT_FOLLOW_LEADING_ZERO; } if (!IsDigit(**data)) { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_BAD_SYMBOL; } break; } WriterWriteChar(writer, **data); } if (prev_char != '0' && !IsDigit(prev_char)) { *json_out = NULL; WriterClose(writer); return JSON_PARSE_ERROR_NUMBER_DIGIT_END; } // rewind 1 char so caller will see separator next *data = *data - 1; if (seen_dot) { *json_out = JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_REAL, StringWriterClose(writer)); return JSON_PARSE_OK; } else { *json_out = JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_INTEGER, StringWriterClose(writer)); return JSON_PARSE_OK; } } static JsonParseError JsonParseAsPrimitive(const char **data, JsonElement **json_out) { switch (**data) { case '"': { char *value = NULL; JsonParseError err = JsonParseAsString(data, &value); if (err != JSON_PARSE_OK) { return err; } *json_out = JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_STRING, JsonDecodeString(value)); free(value); } return JSON_PARSE_OK; default: if (**data == '-' || **data == '0' || IsDigit(**data)) { JsonParseError err = JsonParseAsNumber(data, json_out); if (err != JSON_PARSE_OK) { return err; } return JSON_PARSE_OK; } JsonElement *child_bool = JsonParseAsBoolean(data); if (child_bool) { *json_out = child_bool; return JSON_PARSE_OK; } JsonElement *child_null = JsonParseAsNull(data); if (child_null) { *json_out = child_null; return JSON_PARSE_OK; } *json_out = NULL; return JSON_PARSE_ERROR_OBJECT_BAD_SYMBOL; } } static JsonParseError JsonParseAsArray(const char **data, JsonElement **json_out) { if (**data != '[') { *json_out = NULL; return JSON_PARSE_ERROR_ARRAY_START; } JsonElement *array = JsonArrayCreate(DEFAULT_CONTAINER_CAPACITY); for (*data = *data + 1; **data != '\0'; *data = *data + 1) { if (IsWhitespace(**data)) { continue; } switch (**data) { case '"': { char *value = NULL; JsonParseError err = JsonParseAsString(data, &value); if (err != JSON_PARSE_OK) { return err; } JsonArrayAppendElement(array, JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_STRING, JsonDecodeString(value))); free(value); } break; case '[': { JsonElement *child_array = NULL; JsonParseError err = JsonParseAsArray(data, &child_array); if (err != JSON_PARSE_OK) { JsonDestroy(array); return err; } assert(child_array); JsonArrayAppendArray(array, child_array); } break; case '{': { JsonElement *child_object = NULL; JsonParseError err = JsonParseAsObject(data, &child_object); if (err != JSON_PARSE_OK) { JsonDestroy(array); return err; } assert(child_object); JsonArrayAppendObject(array, child_object); } break; case ',': break; case ']': *json_out = array; return JSON_PARSE_OK; default: if (**data == '-' || **data == '0' || IsDigit(**data)) { JsonElement *child = NULL; JsonParseError err = JsonParseAsNumber(data, &child); if (err != JSON_PARSE_OK) { JsonDestroy(array); return err; } assert(child); JsonArrayAppendElement(array, child); break; } JsonElement *child_bool = JsonParseAsBoolean(data); if (child_bool) { JsonArrayAppendElement(array, child_bool); break; } JsonElement *child_null = JsonParseAsNull(data); if (child_null) { JsonArrayAppendElement(array, child_null); break; } *json_out = NULL; JsonDestroy(array); return JSON_PARSE_ERROR_OBJECT_BAD_SYMBOL; } } *json_out = NULL; JsonDestroy(array); return JSON_PARSE_ERROR_ARRAY_END; } static JsonParseError JsonParseAsObject(const char **data, JsonElement **json_out) { if (**data != '{') { *json_out = NULL; return JSON_PARSE_ERROR_ARRAY_START; } JsonElement *object = JsonObjectCreate(DEFAULT_CONTAINER_CAPACITY); char *property_name = NULL; for (*data = *data + 1; **data != '\0'; *data = *data + 1) { if (IsWhitespace(**data)) { continue; } switch (**data) { case '"': if (property_name != NULL) { char *property_value = NULL; JsonParseError err = JsonParseAsString(data, &property_value); if (err != JSON_PARSE_OK) { free(property_name); JsonDestroy(object); return err; } assert(property_value); JsonObjectAppendElement(object, property_name, JsonElementCreatePrimitive(JSON_PRIMITIVE_TYPE_STRING, JsonDecodeString(property_value))); free(property_value); free(property_name); property_name = NULL; } else { property_name = NULL; JsonParseError err = JsonParseAsString(data, &property_name); if (err != JSON_PARSE_OK) { JsonDestroy(object); return err; } assert(property_name); } break; case ':': if (property_name == NULL) { json_out = NULL; free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_COLON; } break; case ',': if (property_name != NULL) { free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_COMMA; } break; case '[': if (property_name != NULL) { JsonElement *child_array = NULL; JsonParseError err = JsonParseAsArray(data, &child_array); if (err != JSON_PARSE_OK) { free(property_name); JsonDestroy(object); return err; } JsonObjectAppendArray(object, property_name, child_array); free(property_name); property_name = NULL; } else { free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_ARRAY_LVAL; } break; case '{': if (property_name != NULL) { JsonElement *child_object = NULL; JsonParseError err = JsonParseAsObject(data, &child_object); if (err != JSON_PARSE_OK) { free(property_name); JsonDestroy(object); return err; } JsonObjectAppendObject(object, property_name, child_object); free(property_name); property_name = NULL; } else { *json_out = NULL; free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_OBJECT_LVAL; } break; case '}': if (property_name != NULL) { *json_out = NULL; free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_OPEN_LVAL; } free(property_name); *json_out = object; return JSON_PARSE_OK; default: if (property_name) { if (**data == '-' || **data == '0' || IsDigit(**data)) { JsonElement *child = NULL; JsonParseError err = JsonParseAsNumber(data, &child); if (err != JSON_PARSE_OK) { free(property_name); JsonDestroy(object); return err; } JsonObjectAppendElement(object, property_name, child); free(property_name); property_name = NULL; break; } JsonElement *child_bool = JsonParseAsBoolean(data); if (child_bool) { JsonObjectAppendElement(object, property_name, child_bool); free(property_name); property_name = NULL; break; } JsonElement *child_null = JsonParseAsNull(data); if (child_null) { JsonObjectAppendElement(object, property_name, child_null); free(property_name); property_name = NULL; break; } } *json_out = NULL; free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_BAD_SYMBOL; } } *json_out = NULL; free(property_name); JsonDestroy(object); return JSON_PARSE_ERROR_OBJECT_END; } JsonParseError JsonParse(const char **data, JsonElement **json_out) { assert(data && *data); if (data == NULL || *data == NULL) { return JSON_PARSE_ERROR_NO_DATA; } while (**data) { if (**data == '{') { return JsonParseAsObject(data, json_out); } else if (**data == '[') { return JsonParseAsArray(data, json_out); } else if (IsWhitespace(**data)) { (*data)++; } else { return JsonParseAsPrimitive(data, json_out); } } return JSON_PARSE_ERROR_NO_DATA; } JsonParseError JsonParseFile(const char *path, size_t size_max, JsonElement **json_out) { Writer *contents = FileRead(path, size_max, NULL); if (!contents) { return JSON_PARSE_ERROR_NO_DATA; } JsonElement *json = NULL; const char *data = StringWriterData(contents); JsonParseError err = JsonParse(&data, &json); WriterClose(contents); *json_out = json; return err; } cfengine-3.6.2/libutils/deprecated.h0000664000175100017510000000324412406114255017121 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_DEPRECATED_H #define CFENGINE_DEPRECATED_H #include #include /* Mark specific functions as deprecated so that we don't use them. Since the * signature of the functions has to be exactly the same as in libc, we only * do that for Linux, where main development happens. */ #if defined(__linux__) && defined(__GLIBC__) int sprintf(char *str, const char *format, ...) \ FUNC_DEPRECATED("Try snprintf() or xsnprintf() or xasprintf()"); int setenv(const char *name, const char *value, int overwrite) \ FUNC_DEPRECATED("Always use putenv() in place of non-portable setenv()!"); #endif /* __linux__ && __GLIBC__ */ #endif /* CFENGINE_DEPRECATED_H */ cfengine-3.6.2/libutils/hashes.h0000664000175100017510000000224012400110676016264 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_HASHES_H #define CFENGINE_HASHES_H #include #include int FileChecksum(const char *filename, unsigned char digest[EVP_MAX_MD_SIZE + 1]); #endif cfengine-3.6.2/libutils/compiler.h0000664000175100017510000000364712400110676016637 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_COMPILER_H #define CFENGINE_COMPILER_H /* Compiler-specific options/defines */ #if defined(__GNUC__) && (__GNUC__ >= 3) # define FUNC_ATTR_NORETURN __attribute__((noreturn)) # define FUNC_ATTR_PRINTF(string_index, first_to_check) \ __attribute__((format(__printf__, string_index, first_to_check))) # define FUNC_UNUSED __attribute__((unused)) # define ARG_UNUSED __attribute__((unused)) # define FUNC_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) # if (__GNUC__ >= 4) && (__GNUC_MINOR__ >=5) # define FUNC_DEPRECATED(msg) __attribute__((deprecated(msg))) # else # define FUNC_DEPRECATED(msg) __attribute__((deprecated)) # endif #else /* not gcc >= 3.0 */ # define FUNC_ATTR_NORETURN # define FUNC_ATTR_PRINTF(string_index, first_to_check) # define FUNC_UNUSED # define ARG_UNUSED # define FUNC_WARN_UNUSED_RESULT # define FUNC_DEPRECATED(msg) #endif /* gcc >= 3.0 */ #endif /* CFENGINE_COMPILER_H */ cfengine-3.6.2/libutils/ip_address.c0000664000175100017510000010063112411001073017114 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include struct IPV4Address { uint8_t octets[4]; uint16_t port; }; struct IPV6Address { uint16_t sixteen[8]; uint16_t port; }; struct IPAddress { void *address; int type; }; #define Char2Dec(o, c) \ (o * 10) + c - '0' /* * Hexadecimal conversion is not as simple as decimal conversion, * so we implement it here. * We do not check for errors, we assume the caller has checked that * the characters are hexadecimal. */ static int Char2Hex(int beginning, char increment) { int number = beginning; number *= 16; if (('a' <= increment) && (increment <= 'f')) { number += (increment - 'a' + 0x0A); } else if (('A' <= increment) && (increment <= 'F')) { number += (increment - 'A' + 0x0A); } else { number += (increment - '0'); } return number; } /* * This function parses the source pointer and checks if it conforms to the * RFC 791. * * xxx.xxx.xxx.xxx[:ppppp] * * If address is not NULL and the address is IPV4, then the result is copied there. */ static int IPV4_parser(const char *source, struct IPV4Address *address) { char *p = NULL; int octet = 0; int port = 0; int period_counter = 0; int port_counter = 0; int char_counter = 0; bool is_period = false; bool is_digit = false; bool is_port = false; bool has_digit = false; /* * For simplicity sake we initialize address (if not NULL). */ if (address) { int i = 0; for (i = 0; i < 4; ++i) { address->octets[i] = 0; } address->port = 0; } /* * IPV4 parsing has 6 states, of which: * 2 are end states * 4 are parsing states * * States 0 to 3 are purely address parsing. State 5 * might never be reached if there is no port. * State 4 is the final state if everything went ok. * State 6 is reached in case of error. * * 0 1 2 3 * |d |d |d |d * | p | p | p | done * 0 -> 1 -> 2 -> 3 -> 4 * | | | | | * 7 <--+----+----+ | * error | ':' | * _5-----+ * d \| done */ int state = 0; bool state_change = false; for (p = (char *)source; *p != '\0'; ++p) { /* * Do some character recognition */ is_digit = isdigit(*p); is_period = (*p == '.') ? 1 : 0; is_port = (*p == ':') ? 1 : 0; /* * Update the corresponding flags. */ if (is_period) { period_counter++; } if (is_port) { port_counter++; } /* * Do the right operation depending on the state */ switch (state) { case 0: case 1: case 2: /* * The three first states are the same. * XXX.XXX.XXX.xxx[:nnnnn] */ if (is_digit) { octet = Char2Dec(octet, *p); has_digit = true; } else if (is_period) { if (address) { address->octets[state] = octet; } state++; state_change = true; } else { state = 7; state_change = true; } break; case 3: /* * This case is different from the previous ones. A period here means error. * xxx.xxx.xxx.XXX[:nnnnn] */ if (is_digit) { octet = Char2Dec(octet, *p); has_digit = true; } else if (is_port) { if (address) { address->octets[state] = octet; } state = 5; state_change = true; } else { state = 7; state_change = true; } break; case 4: break; case 5: if (is_digit) { port = Char2Dec(port, *p); } else { state = 7; state_change = true; } break; case 6: default: return -1; break; } /* * It is important to the filtering before counting the characters. * Otherwise the counter will need to start from -1. */ char_counter++; /* * Do some sanity checks, this should hold no matter * in which state of the state machine we are. */ if (octet > 255) { return -1; } if (port > 65535) { return -1; } if (period_counter > 1) { return -1; } if (port_counter > 1) { return -1; } if (state_change) { /* * Check that we have digits, otherwise the transition is wrong. */ if (!has_digit) { return -1; } /* * Reset all the variables. */ char_counter = 0; octet = 0; port = 0; period_counter = 0; port_counter = 0; is_period = false; is_digit = false; is_port = false; has_digit = false; state_change = false; } } /* * These states are not end state, which mean we exited the loop because of an error */ if ((state == 0) || (state == 1) || (state == 2)) { return -1; } /* * If state is 3 then we exited the loop without copying the last octet. * This is because we didn't get to state 4. * Notice that we need to check if we had characters, it might be possible that we * have the following situation 'xxx.xxx.xxx.' which will fit the state change but not * produce a valid IP. */ if (state == 3) { if (char_counter == 0) { return -1; } if (address) { address->octets[3] = octet; } } /* * If state is 5 then we exited the loop without copying the port. * This is because we hit a '\0'. * Notice that we need to check if we had characters, it might be possible that we * have the following situation 'xxx.xxx.xxx.xxx:' which will fit the state change but not * produce a valid IP. */ if (state == 5) { if (char_counter == 0) { return -1; } if (address) { address->port = port; } } /* * If state is 6 then there was an error. */ if (state == 6) { return -1; } return 0; } /* * This function parses the address and checks if it conforms to the * RFCs 2373, 2460 and 5952. * We do not support Microsoft UNC encoding, i.e. * hhhh-hhhh-hhhh-hhhh-hhhh-hhhh-hhhh-hhhh.ipv6-literal.net * Despite following RFC 5292 we do not signal errors derived from bad * zero compression although this might change on time, so please do not * trust that we will honor address with wrong zero compression. */ static int IPV6_parser(const char *source, struct IPV6Address *address) { /* * IPV6 parsing is more complex than IPV4 parsing. There are a few ground rules: * - Leading zeros can be omitted. * - Fields that are just zeros can be abreviated to one zero or completely omitted. * In the later case the following notation is used: '::'. * - Port number is specified in a special way: * [hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh]:ppppp * Notice that it is possible to have the '[' and ']' without specifying a port. * * Simplified state machine: * * _h _h _h _h _h _h _h _h _d * |/ ':' |/ ':' |/ ':' |/ ':' |/ ':' |/ ':' |/ ':' |/ ']' ':' |/ done * 0------>1------>2------>3------>4------>5------>6------>7------>8------>9------>11 * |\ | done | * -'[' 9<------+ * * This is a simplified state machine since I assume that we keep the square brackets inside * the same state as hexadecimal digits, which in practice is not true. */ char *p = NULL; int sixteen = 0; int unsorted_sixteen[6]; int unsorted_pointer = 0; int bracket_expected = 0; int port = 0; int char_counter = 0; bool is_start_bracket = 0; bool is_end_bracket = 0; bool is_colon = 0; bool is_hexdigit = 0; bool is_upper_hexdigit = 0; bool is_digit = 0; int zero_compression = 0; int already_compressed = 0; int state = 0; bool state_change = false; /* * Initialize our container for unknown numbers. */ for (unsorted_pointer = 0; unsorted_pointer < 6; ++unsorted_pointer) { unsorted_sixteen[unsorted_pointer] = 0; } unsorted_pointer = 0; /* * For simplicity sake we initialize address (if not NULL). */ if (address) { int i = 0; for (i = 0; i < 8; ++i) { address->sixteen[i] = 0; } address->port = 0; } for (p = (char *)source; *p != '\0'; ++p) { /* * Take a closer look at the character */ is_start_bracket = (*p == '[') ? 1 : 0; is_end_bracket = (*p == ']') ? 1 : 0; is_hexdigit = isxdigit(*p); is_digit = isdigit(*p); is_colon = (*p == ':') ? 1 : 0; if (is_hexdigit) { if (isalpha(*p)) { is_upper_hexdigit = isupper(*p); } } switch (state) { case 0: /* * This case is slightly different because of the possible presence of '['. * Notice that '[' is only valid as the first character, anything else is * an error! */ if (is_start_bracket) { if (char_counter == 0) { bracket_expected = 1; } else { state = 11; state_change = true; } } else if (is_hexdigit) { /* * RFC 5952 forbids upper case hex digits */ if (is_upper_hexdigit) { state = 11; state_change = true; } else { sixteen = Char2Hex(sixteen, *p); } } else if (is_colon) { if (address) { address->sixteen[0] = sixteen; } state = 1; state_change = true; } else { state = 11; state_change = true; } break; case 1: /* * This state is special since it cannot have a ']' as in the next * states. */ if (is_hexdigit) { /* * RFC 5952 forbids upper case hex digits */ if (is_upper_hexdigit) { state = 11; state_change = true; } else { sixteen = Char2Hex(sixteen, *p); } } else if (is_colon) { if (char_counter == 0) { /* * This means 'X::Y...' which means zero compression. * Flag it! */ zero_compression = 1; already_compressed = 1; } else { if (address) { address->sixteen[state] = sixteen; } } ++state; state_change = true; } else { state = 11; state_change = true; } break; case 2: case 3: case 4: case 5: case 6: if (is_hexdigit) { /* * RFC 5952 forbids upper case hex digits */ if (is_upper_hexdigit) { state = 11; state_change = true; } else { sixteen = Char2Hex(sixteen, *p); } } else if (is_colon) { if (char_counter == 0) { if (already_compressed) { /* * The '::' symbol can only occur once in a given address. */ state = 11; state_change = true; } else { /* * This means '...:X::Y...' which means zero compression. * Flag it! */ zero_compression = 1; already_compressed = 1; } } else { if (zero_compression) { /* * If zero compression is enabled, then we cannot trust the position * since we might compressed several fields. We store the value and * look at them afterwards. */ unsorted_sixteen[unsorted_pointer] = sixteen; ++unsorted_pointer; } else { /* * No zero compression, just assign the address and keep moving. */ if (address) { address->sixteen[state] = sixteen; } } ++state; state_change = true; } } else if (is_end_bracket) { if (bracket_expected && zero_compression) { bracket_expected = 0; /* * RFC 5952 says that we can end an address at any point after * the second position (consequence of the zero compression). * Therefore if we find a ']' we just jump to state 8. */ unsorted_sixteen[unsorted_pointer] = sixteen; ++unsorted_pointer; state = 8; state_change = true; } else { /* * Funny stuff, we got a ']' that we were not expecting. * Politely walk back and signal the error. */ state = 11; state_change = true; } } else { state = 11; state_change = true; } break; case 7: /* * This case is special. */ if (is_hexdigit) { /* * RFC 5952 forbids uppercase hex digits */ if (is_upper_hexdigit) { state = 11; state_change = true; } else { sixteen = Char2Hex(sixteen, *p); } } else if (is_end_bracket) { if (bracket_expected) { bracket_expected = 0; if (address) { address->sixteen[state] = sixteen; } /* * The last possible position for a sixteen is number 8. */ ++state; state_change = true; } else { /* * Funny stuff, we got a ']' that we were not expecting. * Politely walk back and signal the error. */ state = 11; state_change = true; } } else { state = 11; state_change = true; } break; case 8: if (is_colon) { ++state; state_change = true; } else { state = 11; state_change = true; } break; case 9: if (is_digit) { port = Char2Dec(port, *p); } else { state = 11; state_change = true; } break; case 10: break; case 11: default: return -1; break; } char_counter++; if (sixteen > 0xFFFF) { return -1; } if (port > 65535) { return -1; } if (state_change) { sixteen = 0; port = 0; char_counter = 0; is_start_bracket = false; is_end_bracket = false; is_colon = false; is_hexdigit = false; is_upper_hexdigit = false; is_digit = 0; state_change = false; } } /* * Look at the end state and return accordingly. */ if ((state == 0) || (state == 1)) { /* * These states are not final states, so if we exited is because something went wrong. */ return -1; } /* * Thanks to RFC5952 the final states can be intermediate states. This because of zero compression, * which means that the following address 1:0:0:0:0:0:0:1 can be written as * 1::1. Not to mention more exotic varieties such as 1:0:0:0:0:0:0:0 1:: or * 0:0:0:0:0:0:0:0 :: * The first intermediate state that can exit is 2, since even the smallest of all address('::') * will have at least two ':'. * Another exotic case is 'X:0:0:Y:0:0:0:Z' which becomes 'X::Y:0:0:0:Z' or X:0:0:Y::Z because the symbol '::' * can appear only once in a given address. */ if ((state == 2) || (state == 3) || (state == 4) || (state == 5) || (state == 6)) { /* * We check first for non-closed brackets. * Then we check if there is a number that has not been added to our array. * Finally we move to zero compression. */ if (bracket_expected) { return -1; } unsorted_sixteen[unsorted_pointer] = sixteen; ++unsorted_pointer; if (zero_compression) { /* * If there is no address, then we can just return :-) */ if (address) { /* * We need to find the rightful positions for those numbers. * We use a simple trick: * We know how many unsorted addresses we have from unsorted pointer, * and we know that once zero_compression is activated we do not fill * any more numbers to the address structure. Therefore the right way * to do this is to take the array of unsorted_sixteen and start assigning * numbers backwards. */ int i = 0; for (i = 0; i < unsorted_pointer; ++i) { address->sixteen[7 - i] = unsorted_sixteen[unsorted_pointer - i - 1]; } } } else { /* * We cannot end up here without zero compression, or an error. */ return -1; } } if (state == 7) { /* * This state corresponds to the final state of a simple ipv6 address, i.e. * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx * We exited because we ran out of characters. Let's check that we have something * before assigning things. */ if (char_counter == 0) { /* * The last field was empty, signal the error. */ return -1; } if (bracket_expected) { /* * We were expecting a bracket but it never came, so this is an error. */ return -1; } if (address) { address->sixteen[7] = sixteen; } } if (state == 8) { /* * This state corresponds to the final state if brackets were present. * We still need to check if zero compression was activated and copy * the values if so. */ if (zero_compression) { /* * If there is no address, then we can just return :-) */ if (address) { /* * We need to find the rightful positions for those numbers. * We use a simple trick: * We know how many unsorted addresses we have from unsorted pointer, * and we know that once zero_compression is activated we do not fill * any more numbers to the address structure. Therefore the right way * to do this is to take the array of unsorted_sixteen and start assigning * numbers backwards. */ int i = 0; for (i = 0; i < unsorted_pointer; ++i) { address->sixteen[7 - i] = unsorted_sixteen[i]; } } } } if (state == 9) { /* * This state corresponds to the final state if we had brackets around us. * This is usually used to append a port number to the address, so we check * if we have a port and then assign it. */ if (char_counter == 0) { /* * The last field was empty, signal the error. */ return -1; } if (address) { address->port = port; } } if (state == 11) { /* * Error state */ return -1; } return 0; } IPAddress *IPAddressNew(Buffer *source) { if (!source || !BufferData(source)) { return NULL; } IPAddress *address = NULL; const char *pad = BufferData(source); struct IPV4Address *ipv4 = NULL; struct IPV6Address *ipv6 = NULL; ipv4 = (struct IPV4Address *)xmalloc(sizeof(struct IPV4Address)); ipv6 = (struct IPV6Address *)xmalloc(sizeof(struct IPV6Address)); if (IPV4_parser(pad, ipv4) == 0) { free (ipv6); address = (IPAddress *)xmalloc(sizeof(IPAddress)); address->type = IP_ADDRESS_TYPE_IPV4; address->address = (void *)ipv4; } else if (IPV6_parser(pad, ipv6) == 0) { free (ipv4); address = (IPAddress *)xmalloc(sizeof(IPAddress)); address->type = IP_ADDRESS_TYPE_IPV6; address->address = (void *)ipv6; } else { /* * It was not a valid IP address. */ free (ipv4); free (ipv6); return NULL; } return address; } int IPAddressDestroy(IPAddress **address) { if (!address || !(*address)) { return 0; } if ((*address)->address) { free ((*address)->address); } free (*address); *address = NULL; return 0; } int IPAddressType(IPAddress *address) { if (!address) { return -1; } return address->type; } Buffer *IPAddressGetAddress(IPAddress *address) { if (!address) { return NULL; } Buffer *buffer = NULL; int result = 0; if (address->type == IP_ADDRESS_TYPE_IPV4) { struct IPV4Address *ipv4 = (struct IPV4Address *)address->address; buffer = BufferNew(); #if BIG_ENDIAN result = BufferPrintf(buffer, "%u.%u.%u.%u", ipv4->octets[0], ipv4->octets[1], ipv4->octets[2], ipv4->octets[3]); #elif LITTLE_ENDIAN result = BufferPrintf(buffer, "%u.%u.%u.%u", ipv4->octets[3], ipv4->octets[2], ipv4->octets[1], ipv4->octets[0]); #else #warning "Unrecognized endianness, assuming big endian" result = BufferPrintf(buffer, "%u.%u.%u.%u", ipv4->octets[0], ipv4->octets[1], ipv4->octets[2], ipv4->octets[3]); #endif } else if (address->type == IP_ADDRESS_TYPE_IPV6) { struct IPV6Address *ipv6 = (struct IPV6Address *)address->address; buffer = BufferNew(); #if BIG_ENDIAN result = BufferPrintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", ipv6->sixteen[0], ipv6->sixteen[1], ipv6->sixteen[2], ipv6->sixteen[3], ipv6->sixteen[4], ipv6->sixteen[5], ipv6->sixteen[6], ipv6->sixteen[7]); #elif LITTLE_ENDIAN result = BufferPrintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", ipv6->sixteen[7], ipv6->sixteen[6], ipv6->sixteen[5], ipv6->sixteen[4], ipv6->sixteen[3], ipv6->sixteen[2], ipv6->sixteen[1], ipv6->sixteen[0]); #else #warning "Unrecognized endianness, assuming big endian" result = BufferPrintf(buffer, "%x:%x:%x:%x:%x:%x:%x:%x", ipv6->sixteen[0], ipv6->sixteen[1], ipv6->sixteen[2], ipv6->sixteen[3], ipv6->sixteen[4], ipv6->sixteen[5], ipv6->sixteen[6], ipv6->sixteen[7]); #endif } else { buffer = NULL; } if (result < 0) { BufferDestroy(buffer); return NULL; } return buffer; } int IPAddressGetPort(IPAddress *address) { if (!address) { return -1; } int port = -1; if (address->type == IP_ADDRESS_TYPE_IPV4) { struct IPV4Address *ipv4 = (struct IPV4Address *)address->address; port = ipv4->port; } else if (address->type == IP_ADDRESS_TYPE_IPV6) { struct IPV6Address *ipv6 = (struct IPV6Address *)address->address; port = ipv6->port; } else { return -1; } return port; } /* * Comparison for IPV4 addresses */ static int IPV4Compare(struct IPV4Address *a, struct IPV4Address *b) { int i = 0; for (i = 0; i < 4; ++i) { if (a->octets[i] != b->octets[i]) { return 0; } } return 1; } /* * Comparison for IPV6 addresses */ static int IPV6Compare(struct IPV6Address *a, struct IPV6Address *b) { int i = 0; for (i = 0; i < 8; ++i) { if (a->sixteen[i] != b->sixteen[i]) { return 0; } } return 1; } int IPAddressIsEqual(IPAddress *a, IPAddress *b) { /* * We do not support IPV4 versus IPV6 comparisons. * This is trickier than what it seems, since even the IPV6 representation of an IPV6 address is not * clear yet. */ if (!a || !b) { return -1; } if (a->type != b->type) { return -1; } if (a->type == IP_ADDRESS_TYPE_IPV4) { return IPV4Compare((struct IPV4Address *)a->address, (struct IPV4Address *)b->address); } else if (a->type == IP_ADDRESS_TYPE_IPV6) { return IPV6Compare((struct IPV6Address *)a->address, (struct IPV6Address *)b->address); } return -1; } /* * Sorting comparison for IPV4 addresses */ static int IPV4CompareLess(struct IPV4Address *a, struct IPV4Address *b) { int i = 0; for (i = 0; i < 4; ++i) { if (a->octets[i] > b->octets[i]) { return 0; } else if (a->octets[i] < b->octets[i]) { return 1; } } return 0; } /* * Sorting comparison for IPV6 addresses */ static int IPV6CompareLess(struct IPV6Address *a, struct IPV6Address *b) { int i = 0; for (i = 0; i < 8; ++i) { if (a->sixteen[i] > b->sixteen[i]) { return 0; } else if (a->sixteen[i] < b->sixteen[i]) { return 1; } } return 0; } int IPAddressCompareLess(IPAddress *a, IPAddress *b) { /* * We do not support IPV4 versus IPV6 comparisons. * This is trickier than what it seems, since even the IPV6 representation of an IPV6 address is not * clear yet. */ if (!a || !b) { return 1; } // Sort IPv4 BEFORE any other types if (a->type == IP_ADDRESS_TYPE_IPV4 && a->type != b->type) { return 1; } if (b->type == IP_ADDRESS_TYPE_IPV4 && a->type != b->type) { return 0; } if (a->type == IP_ADDRESS_TYPE_IPV4 && b->type == IP_ADDRESS_TYPE_IPV4) { return IPV4CompareLess((struct IPV4Address *)a->address, (struct IPV4Address *)b->address); } if (a->type == IP_ADDRESS_TYPE_IPV6 && b->type == IP_ADDRESS_TYPE_IPV6) { return IPV6CompareLess((struct IPV6Address *)a->address, (struct IPV6Address *)b->address); } return -1; } bool IPAddressIsIPAddress(Buffer *source, IPAddress **address) { if (!source || !BufferData(source)) { return false; } bool create_object = false; if (address) { create_object = true; } const char *pad = BufferData(source); struct IPV4Address *ipv4 = NULL; struct IPV6Address *ipv6 = NULL; ipv4 = (struct IPV4Address *)xmalloc(sizeof(struct IPV4Address)); ipv6 = (struct IPV6Address *)xmalloc(sizeof(struct IPV6Address)); if (IPV4_parser(pad, ipv4) == 0) { free (ipv6); if (create_object) { *address = (IPAddress *)xmalloc(sizeof(IPAddress)); (*address)->type = IP_ADDRESS_TYPE_IPV4; (*address)->address = (void *)ipv4; } else { /* * We know it is a valid IPV4 address and we know we don't need the * IPV4 structure. */ free (ipv4); } } else if (IPV6_parser(pad, ipv6) == 0) { free (ipv4); if (create_object) { *address = (IPAddress *)xmalloc(sizeof(IPAddress)); (*address)->type = IP_ADDRESS_TYPE_IPV6; (*address)->address = (void *)ipv6; } else { /* * We know it is a valid IPV6 address and we know we don't need the * IPV6 structure. */ free (ipv6); } } else { /* * It was not a valid IP address. */ free (ipv4); free (ipv6); return false; } return true; } cfengine-3.6.2/libutils/regex.c0000664000175100017510000001105012400110676016115 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #define STRING_MATCH_OVECCOUNT 30 #define NULL_OR_EMPTY(str) ((str == NULL) || (str[0] == '\0')) pcre *CompileRegex(const char *regex) { const char *errorstr; int erroffset; pcre *rx = pcre_compile(regex, PCRE_MULTILINE | PCRE_DOTALL, &errorstr, &erroffset, NULL); if (!rx) { Log(LOG_LEVEL_ERR, "Regular expression error: pcre_compile() '%s' in expression '%s' (offset: %d)", errorstr, regex, erroffset); } return rx; } bool StringMatchWithPrecompiledRegex(pcre *regex, const char *str, int *start, int *end) { assert(regex); assert(str); int ovector[STRING_MATCH_OVECCOUNT] = { 0 }; int result = pcre_exec(regex, NULL, str, strlen(str), 0, 0, ovector, STRING_MATCH_OVECCOUNT); if (result) { if (start) { *start = ovector[0]; } if (end) { *end = ovector[1]; } } else { if (start) { *start = 0; } if (end) { *end = 0; } } return result >= 0; } bool StringMatch(const char *regex, const char *str, int *start, int *end) { pcre *pattern = CompileRegex(regex); if (pattern == NULL) { return false; } bool ret = StringMatchWithPrecompiledRegex(pattern, str, start, end); pcre_free(pattern); return ret; } bool StringMatchFull(const char *regex, const char *str) { pcre *pattern = CompileRegex(regex); if (pattern == NULL) { return false; } bool ret = StringMatchFullWithPrecompiledRegex(pattern, str); pcre_free(pattern); return ret; } bool StringMatchFullWithPrecompiledRegex(pcre *pattern, const char *str) { int start = 0, end = 0; if (StringMatchWithPrecompiledRegex(pattern, str, &start, &end)) { return (start == 0) && (end == strlen(str)); } else { return false; } } Seq *StringMatchCaptures(const char *regex, const char *str) { assert(regex); assert(str); pcre *pattern = NULL; { const char *errorstr; int erroffset; pattern = pcre_compile(regex, PCRE_MULTILINE | PCRE_DOTALL, &errorstr, &erroffset, NULL); } assert(pattern); if (pattern == NULL) { return NULL; } int captures; int res = pcre_fullinfo(pattern, NULL, PCRE_INFO_CAPTURECOUNT, &captures); if (res != 0) { pcre_free(pattern); return NULL; } int *ovector = xmalloc(sizeof(int) * (captures + 1) * 3); int result = pcre_exec(pattern, NULL, str, strlen(str), 0, 0, ovector, (captures + 1) * 3); if (result <= 0) { free(ovector); pcre_free(pattern); return NULL; } Seq *ret = SeqNew(captures + 1, free); for (int i = 0; i <= captures; ++i) { SeqAppend(ret, xstrndup(str + ovector[2*i], ovector[2*i + 1] - ovector[2 * i])); } free(ovector); pcre_free(pattern); return ret; } bool CompareStringOrRegex(const char *value, const char *compareTo, bool regex) { if (regex) { if (!NULL_OR_EMPTY(compareTo) && !StringMatchFull(compareTo, value)) { return false; } } else { if (!NULL_OR_EMPTY(compareTo) && strcmp(compareTo, value) != 0) { return false; } } return true; } cfengine-3.6.2/libutils/set.c0000644000175100017510000000752112316547775015630 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include TYPED_SET_DEFINE(String, char *, (MapHashFn)&StringHash, (MapKeyEqualFn)&StringSafeEqual, &free) Set *SetNew(MapHashFn element_hash_fn, MapKeyEqualFn element_equal_fn, MapDestroyDataFn element_destroy_fn) { return MapNew(element_hash_fn, element_equal_fn, element_destroy_fn, NULL); } void SetDestroy(Set *set) { MapDestroy(set); } void SetAdd(Set *set, void *element) { MapInsert(set, element, element); } bool SetContains(const Set *set, const void *element) { return MapHasKey(set, element); } bool SetRemove(Set *set, const void *element) { return MapRemove(set, element); } void SetClear(Set *set) { MapClear(set); } size_t SetSize(const Set *set) { return MapSize(set); } bool SetIsEqual(const Set *set1, const Set *set2) { return MapContainsSameKeys(set1, set2); } SetIterator SetIteratorInit(Set *set) { return MapIteratorInit(set); } void *SetIteratorNext(SetIterator *i) { MapKeyValue *kv = MapIteratorNext(i); return kv ? kv->key : NULL; } Buffer *StringSetToBuffer(StringSet *set, const char delimiter) { Buffer *buf = BufferNew(); StringSetIterator it = StringSetIteratorInit(set); const char *element = NULL; int pos = 0; int size = StringSetSize(set); char minibuf[2]; minibuf[0] = delimiter; minibuf[1] = '\0'; while ((element = StringSetIteratorNext(&it))) { BufferAppend(buf, element, strlen(element)); if (pos < size-1) { BufferAppend(buf, minibuf, sizeof(char)); } pos++; } return buf; } void StringSetAddSplit(StringSet *set, const char *str, char delimiter) { if (str) // TODO: remove this inconsistency, add assert(str) { const char *prev = str; const char *cur = str; while (*cur != '\0') { if (*cur == delimiter) { size_t len = cur - prev; if (len > 0) { StringSetAdd(set, xstrndup(prev, len)); } else { StringSetAdd(set, xstrdup("")); } prev = cur + 1; } cur++; } if (cur > prev) { StringSetAdd(set, xstrndup(prev, cur - prev)); } } } StringSet *StringSetFromString(const char *str, char delimiter) { StringSet *set = StringSetNew(); StringSetAddSplit(set, str, delimiter); return set; } JsonElement *StringSetToJson(const StringSet *set) { JsonElement *arr = JsonArrayCreate(StringSetSize(set)); StringSetIterator it = StringSetIteratorInit((StringSet *)set); const char *el = NULL; while ((el = StringSetIteratorNext(&it))) { JsonArrayAppendString(arr, el); } return arr; } cfengine-3.6.2/libutils/misc_lib.c0000664000175100017510000000710012400110676016565 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include unsigned long UnsignedModulus(long dividend, long divisor) { return ((dividend % divisor) + divisor) % divisor; } size_t UpperPowerOfTwo(size_t v) { // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } void __ProgrammingError(const char *file, int lineno, const char *format, ...) { va_list ap; char *fmt = NULL; va_start(ap, format); xasprintf(&fmt, "%s:%d: Programming Error: %s\n", file, lineno, format); vfprintf(stdout, fmt, ap); va_end(ap); free(fmt); #ifdef NDEBUG exit(255); #else abort(); #endif } /** @brief Log unexpected runtime error to stderr, do not exit program. */ void __UnexpectedError(const char *file, int lineno, const char *format, ...) { va_list ap; char *fmt = NULL; va_start(ap, format); xasprintf(&fmt, "%s:%d: Unexpected Error - this is a BUG, please report it: %s\n", file, lineno, format); vfprintf(stderr, fmt, ap); va_end(ap); free(fmt); } void xclock_gettime(clockid_t clk_id, struct timespec *ts) { int ret = clock_gettime(clk_id, ts); if (ret != 0) { Log(LOG_LEVEL_VERBOSE, "clock_gettime() failed (%s), falling back to time()", GetErrorStr()); *ts = (struct timespec) { .tv_sec = time(NULL) }; } } /** * Unchecked version of snprintf(). For when you're *sure* the result fits in * the buffer, and you don't want to check it. In other words, NO PART OF THE * OUTPUT SHOULD BE DEPENDENT ON USER DATA! * * Only exception is usage in the unit tests, where we use it all over the * place in order to flag stupid programming mistakes. */ void xsnprintf(char *str, size_t str_size, const char *format, ...) { va_list ap; va_start(ap, format); int ret = vsnprintf(str, str_size, format, ap); va_end(ap); if (ret < 0) /* error */ { *str = '\0'; Log(LOG_LEVEL_WARNING, "Unexpected failure from snprint(\"%s\"): %s", format, GetErrorStr()); } else if (ret >= str_size) /* output truncated */ { #ifdef NDEBUG UnexpectedError("Result of snprintf(\"%s\") truncated at %zu chars", format, str_size); #else ProgrammingError("Result of snprintf(\"%s\") truncated at %zu chars", format, str_size); #endif } } cfengine-3.6.2/libutils/map.c0000664000175100017510000001603012400110676015563 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include /* * This associative array implementation uses array with linear search up to * TINY_LIMIT elements, and then converts into full-fledged hash table with open * addressing. * * There is a lot of small hash tables, both iterating and deleting them as a * hashtable takes a lot of time, especially given associative hash tables are * created and destroyed for each scope entered and left. */ struct Map_ { MapHashFn hash_fn; union { ArrayMap *arraymap; HashMap *hashmap; }; }; static unsigned IdentityHashFn(const void *ptr, ARG_UNUSED unsigned int seed, ARG_UNUSED unsigned int max) { return (unsigned)(uintptr_t)ptr; } static bool IdentityEqualFn(const void *p1, const void *p2) { return p1 == p2; } static void NopDestroyFn(ARG_UNUSED void *p1) { } /* * hash_fn is used as a flag "this map uses ArrayMap still". We could have a * separate boolean flag for that, but given we have to store hash_fn somewhere * anyway, let's reuse it this way. Saves us 4-8 bytes for each map. */ static bool IsArrayMap(const Map *map) { return map->hash_fn != NULL; } Map *MapNew(MapHashFn hash_fn, MapKeyEqualFn equal_fn, MapDestroyDataFn destroy_key_fn, MapDestroyDataFn destroy_value_fn) { if (hash_fn == NULL) { hash_fn = &IdentityHashFn; } if (equal_fn == NULL) { equal_fn = &IdentityEqualFn; } if (destroy_key_fn == NULL) { destroy_key_fn = &NopDestroyFn; } if (destroy_value_fn == NULL) { destroy_value_fn = &NopDestroyFn; } Map *map = xcalloc(1, sizeof(Map)); map->arraymap = ArrayMapNew(equal_fn, destroy_key_fn, destroy_value_fn); map->hash_fn = hash_fn; return map; } size_t MapSize(const Map *map) { if (IsArrayMap(map)) { return map->arraymap->size; } else { MapIterator i = MapIteratorInit((Map*)map); size_t size = 0; while (MapIteratorNext(&i)) { size++; } return size; } } static void ConvertToHashMap(Map *map) { HashMap *hashmap = HashMapNew(map->hash_fn, map->arraymap->equal_fn, map->arraymap->destroy_key_fn, map->arraymap->destroy_value_fn); /* We have to use internals of ArrayMap here, as we don't want to destroy the values in ArrayMapDestroy */ for (int i = 0; i < map->arraymap->size; ++i) { HashMapInsert(hashmap, map->arraymap->values[i].key, map->arraymap->values[i].value); } free(map->arraymap->values); free(map->arraymap); map->hashmap = hashmap; map->hash_fn = NULL; } void MapInsert(Map *map, void *key, void *value) { if (IsArrayMap(map)) { if (ArrayMapInsert(map->arraymap, key, value)) { return; } else { ConvertToHashMap(map); } } HashMapInsert(map->hashmap, key, value); } /* * The best we can get out of C type system. Caller should make sure that if * argument is const, it does not modify the result. */ static MapKeyValue *MapGetRaw(const Map *map, const void *key) { if (IsArrayMap(map)) { return ArrayMapGet((ArrayMap *)map->arraymap, key); } else { return HashMapGet((HashMap *)map->hashmap, key); } } bool MapHasKey(const Map *map, const void *key) { return MapGetRaw(map, key) != NULL; } void *MapGet(Map *map, const void *key) { MapKeyValue *kv = MapGetRaw(map, key); return kv ? kv->value : NULL; } bool MapRemove(Map *map, const void *key) { if (IsArrayMap(map)) { return ArrayMapRemove(map->arraymap, key); } else { return HashMapRemove(map->hashmap, key); } } void MapClear(Map *map) { if (IsArrayMap(map)) { ArrayMapClear(map->arraymap); } else { HashMapClear(map->hashmap); } } void MapSoftDestroy(Map *map) { if (map) { if (IsArrayMap(map)) { ArrayMapSoftDestroy(map->arraymap); } else { HashMapSoftDestroy(map->hashmap); } free(map); } } void MapDestroy(Map *map) { if (map) { if (IsArrayMap(map)) { ArrayMapDestroy(map->arraymap); } else { HashMapDestroy(map->hashmap); } free(map); } } bool MapContainsSameKeys(const Map *map1, const Map *map2) { MapIterator i = MapIteratorInit((Map *)map1); MapKeyValue *item; size_t count = 0; while ((item = MapIteratorNext(&i))) { count++; if (!MapHasKey(map2, item->key)) { return false; } } return (count == MapSize(map2)); } void MapPrintStats(const Map *map, FILE *f) { fprintf(f, "================ Map statistics ================\n"); if (IsArrayMap(map)) { fprintf(f, "Map is too small, fits in a small array.\n"); } else { HashMapPrintStats(map->hashmap, f); } fprintf(f, "================================================\n"); } /******************************************************************************/ MapIterator MapIteratorInit(Map *map) { MapIterator i; if (IsArrayMap(map)) { i.is_array = true; i.arraymap_iter = ArrayMapIteratorInit(map->arraymap); } else { i.is_array = false; i.hashmap_iter = HashMapIteratorInit(map->hashmap); } return i; } MapKeyValue *MapIteratorNext(MapIterator *i) { if (i->is_array) { return ArrayMapIteratorNext(&i->arraymap_iter); } else { return HashMapIteratorNext(&i->hashmap_iter); } } TYPED_MAP_DEFINE(String, char *, char *, (MapHashFn)&StringHash, (MapKeyEqualFn)&StringSafeEqual, &free, &free) cfengine-3.6.2/libutils/Makefile.am0000664000175100017510000000323612411001073016672 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libutils.la # TODO remove the openssl dependency! It's only there for base64 encoding. AM_CFLAGS = $(PCRE_CFLAGS) $(OPENSSL_CFLAGS) AM_CPPFLAGS = $(PCRE_CPPFLAGS) $(OPENSSL_CPPFLAGS) AM_LDFLAGS = $(PCRE_LDFLAGS) $(OPENSSL_LDFLAGS) libutils_la_LIBADD = ../libcompat/libcompat.la libutils_la_LIBS = $(PCRE_LIBS) $(OPENSSL_LIBS) libutils_la_SOURCES = \ alloc.c alloc.h \ atexit.c atexit.h \ compiler.h \ deprecated.h \ dir.h dir_priv.h \ hashes.c hashes.h hash_method.h \ sequence.c sequence.h \ set.c set.h \ statistics.c statistics.h \ string_lib.c string_lib.h \ pcre_include.h \ platform.h \ proc_keyvalue.c proc_keyvalue.h \ bool.h \ json.c json.h \ refcount.c refcount.h \ list.c list.h \ logging.c logging.h logging_priv.h \ buffer.c buffer.h \ ip_address.c ip_address.h \ map.c map.h map_common.h \ array_map.c array_map_priv.h \ hash_map.c hash_map_priv.h \ misc_lib.c misc_lib.h \ writer.c writer.h \ csv_writer.c csv_writer.h \ csv_parser.c csv_parser.h \ xml_writer.c xml_writer.h \ file_lib.c file_lib.h \ man.c man.h \ rb-tree.c rb-tree.h \ mustache.c mustache.h \ cfversion.c cfversion.h \ unicode.c unicode.h \ hash.c hash.h \ queue.c queue.h \ ring_buffer.c ring_buffer.h \ regex.c regex.h \ encode.c encode.h \ printsize.h if !NT libutils_la_SOURCES += unix_dir.c endif if CYGWIN libutils_la_SOURCES += unix_dir.c endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = config.h.in cfengine-3.6.2/libutils/array_map.c0000644000175100017510000000724212316547775017010 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* FIXME: make configurable and move to map.c */ #define TINY_LIMIT 14 ArrayMap *ArrayMapNew(MapKeyEqualFn equal_fn, MapDestroyDataFn destroy_key_fn, MapDestroyDataFn destroy_value_fn) { ArrayMap *map = xcalloc(1, sizeof(ArrayMap)); map->equal_fn = equal_fn; map->destroy_key_fn = destroy_key_fn; map->destroy_value_fn = destroy_value_fn; map->values = xcalloc(1, sizeof(MapKeyValue) * TINY_LIMIT); return map; } bool ArrayMapInsert(ArrayMap *map, void *key, void *value) { if (map->size == TINY_LIMIT) { return false; } for (int i = 0; i < map->size; ++i) { if (map->equal_fn(map->values[i].key, key)) { map->destroy_key_fn(key); map->destroy_value_fn(map->values[i].value); map->values[i].value = value; return true; } } map->values[map->size++] = (MapKeyValue) { key, value }; return true; } bool ArrayMapRemove(ArrayMap *map, const void *key) { for (int i = 0; i < map->size; ++i) { if (map->equal_fn(map->values[i].key, key)) { map->destroy_key_fn(map->values[i].key); map->destroy_value_fn(map->values[i].value); memmove(map->values + i, map->values + i + 1, sizeof(MapKeyValue) * (map->size - i - 1)); map->size--; return true; } } return false; } MapKeyValue *ArrayMapGet(const ArrayMap *map, const void *key) { for (int i = 0; i < map->size; ++i) { if (map->equal_fn(map->values[i].key, key)) { return map->values + i; } } return NULL; } void ArrayMapClear(ArrayMap *map) { for (int i = 0; i < map->size; ++i) { map->destroy_key_fn(map->values[i].key); map->destroy_value_fn(map->values[i].value); } map->size = 0; } void ArrayMapSoftDestroy(ArrayMap *map) { if (map) { for (int i = 0; i < map->size; ++i) { map->destroy_key_fn(map->values[i].key); } map->size = 0; free(map->values); free(map); } } void ArrayMapDestroy(ArrayMap *map) { if (map) { ArrayMapClear(map); free(map->values); free(map); } } /******************************************************************************/ ArrayMapIterator ArrayMapIteratorInit(ArrayMap *map) { return (ArrayMapIterator) { map, 0 }; } MapKeyValue *ArrayMapIteratorNext(ArrayMapIterator *i) { if (i->pos >= i->map->size) { return NULL; } else { return &i->map->values[i->pos++]; } } cfengine-3.6.2/libutils/csv_parser.c0000644000175100017510000002426612352022221017157 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include typedef enum { CSV_ST_NEW_LINE, CSV_ST_PRE_START_SPACE, CSV_ST_NO_QUOTE_MODE, CSV_ST_SEPARATOR, CSV_ST_LEADING_QUOTE, CSV_ST_INTERNAL_QUOTE, CSV_ST_WITH_QUOTE_MODE, CSV_ST_SPACE_AFTER_QUOTE, CSV_ST_ERROR, CSV_ST_CLOSED } csv_state; #define CSVCL_BLANK(x) (((x)==' ')||((x)=='\t')||((x)=='\n')||((x)=='\r')) #define CSVCL_QUOTE(x) (((x)=='"')) #define CSVCL_SEP(x) (((x)==',')) #define CSVCL_EOL(x) (((x)=='\0')) #define CSVCL_ANY1(x) ((!CSVCL_BLANK(x))&&(!CSVCL_QUOTE(x))&&(!CSVCL_SEP(x))) #define CSVCL_ANY2(x) ((!CSVCL_BLANK(x))&&(!CSVCL_QUOTE(x))&&(!CSVCL_SEP(x))) #define CSVCL_ANY3(x) ((!CSVCL_QUOTE(x))&&(!CSVCL_SEP(x))) #define CSVCL_ANY4(x) ((!CSVCL_BLANK(x))&&(!CSVCL_QUOTE(x))&&(!CSVCL_SEP(x))) #define CSVCL_ANY5(x) ((!CSVCL_QUOTE(x))) #define CSVCL_ANY6(x) ((!CSVCL_BLANK(x))&&(!CSVCL_QUOTE(x))&&(!CSVCL_SEP(x))) #define CSVCL_ANY7(x) ((!CSVCL_QUOTE(x))) #define CSVCL_ANY8(x) ((!CSVCL_BLANK(x))&&(!CSVCL_SEP(x))) typedef enum { CSV_ERR_OK, CVS_ERR_MALFORMED, CSV_ERR_UNKNOWN_STATE, CSV_ERR_UNEXPECTED_END, CSV_ERR_INVALID_INPUT } csv_parser_error; /** @brief parse CSV-formatted line and put its content in a list @param[in] str: is the CSV string to parse @param[out] newlist: list of elements found @retval 0: successful, <>0: failed */ static csv_parser_error LaunchCsvAutomata(const char *str, Seq **newlist) { assert(str); if (str == NULL || strlen(str) >= CSV_MAX_LLENGTH) { return CSV_ERR_INVALID_INPUT; } const char *s = str; csv_state current_state = CSV_ST_NEW_LINE; csv_parser_error ret; char snatched[CSV_MAX_LLENGTH]; snatched[0] = '\0'; char *sn = snatched ; *sn = '\0'; while (*s) { switch(current_state) { case CSV_ST_ERROR: ret = CVS_ERR_MALFORMED; goto clean; case CSV_ST_NEW_LINE: if (CSVCL_SEP(*s)) { *sn = '\0'; sn = NULL; SeqAppend(*newlist, (void *)xstrdup("")); current_state = CSV_ST_SEPARATOR; } else if (CSVCL_BLANK(*s)) { *sn = *s; sn++; current_state = CSV_ST_PRE_START_SPACE; } else if (CSVCL_QUOTE(*s)) { snatched[0] = '\0'; sn = NULL; current_state = CSV_ST_LEADING_QUOTE; } else if (CSVCL_ANY1(*s)) { *sn = *s; sn++; current_state = CSV_ST_NO_QUOTE_MODE; } s++; break; case CSV_ST_PRE_START_SPACE: if (CSVCL_SEP(*s)) { *sn = '\0'; sn = NULL; SeqAppend(*newlist, (void *)xstrdup(snatched)); snatched[0] = '\0'; current_state = CSV_ST_SEPARATOR; } else if (CSVCL_BLANK(*s)) { *sn = *s; sn++; current_state = CSV_ST_PRE_START_SPACE; } else if (CSVCL_QUOTE(*s)) { snatched[0] = '\0'; sn = NULL; current_state = CSV_ST_LEADING_QUOTE; } else if (CSVCL_ANY2(*s)) { *sn = *s; sn++; current_state = CSV_ST_NO_QUOTE_MODE; } s++; break; case CSV_ST_NO_QUOTE_MODE: if (CSVCL_SEP(*s)) { *sn = '\0'; sn = NULL; SeqAppend(*newlist, (void *)xstrdup(snatched)); snatched[0] = '\0'; current_state = CSV_ST_SEPARATOR; } else if (CSVCL_QUOTE(*s)) { snatched[0] = '\0'; sn = NULL; current_state = CSV_ST_ERROR; } else if (CSVCL_ANY3(*s)) { *sn = *s; sn++; current_state = CSV_ST_NO_QUOTE_MODE; } s++; break; case CSV_ST_SEPARATOR: if (CSVCL_SEP(*s)) { snatched[0] = '\0'; sn = NULL; SeqAppend(*newlist, (void *)xstrdup(snatched)); current_state = CSV_ST_SEPARATOR; } else if (CSVCL_BLANK(*s)) { sn = snatched; *sn = *s; sn++; current_state = CSV_ST_PRE_START_SPACE; } else if (CSVCL_QUOTE(*s)) { snatched[0] = '\0'; sn = NULL; current_state = CSV_ST_LEADING_QUOTE; } else if (CSVCL_ANY4(*s)) { sn = snatched; *sn = *s; sn++; current_state = CSV_ST_NO_QUOTE_MODE; } s++; break; case CSV_ST_LEADING_QUOTE: if (CSVCL_QUOTE(*s)) { sn = snatched; current_state = CSV_ST_INTERNAL_QUOTE; } else if (CSVCL_ANY5(*s)) { sn = snatched; *sn = *s; sn++; current_state = CSV_ST_WITH_QUOTE_MODE; } s++; break; case CSV_ST_INTERNAL_QUOTE: if (CSVCL_SEP(*s)) { *sn = '\0'; sn = NULL; SeqAppend(*newlist, (void *)xstrdup(snatched)); current_state = CSV_ST_SEPARATOR; } else if (CSVCL_BLANK(*s)) { current_state = CSV_ST_SPACE_AFTER_QUOTE; } else if (CSVCL_QUOTE(*s)) { *sn = *s; sn++; current_state = CSV_ST_WITH_QUOTE_MODE; } else if (CSVCL_ANY6(*s)) { snatched[0] = '\0'; sn++; current_state = CSV_ST_ERROR; } s++; break; case CSV_ST_WITH_QUOTE_MODE: if (CSVCL_QUOTE(*s)) { current_state = CSV_ST_INTERNAL_QUOTE; } else if (CSVCL_ANY7(*s)) { *sn = *s; sn++; current_state = CSV_ST_WITH_QUOTE_MODE; } s++; break; case CSV_ST_SPACE_AFTER_QUOTE: if (CSVCL_SEP(*s)) { sn = NULL; SeqAppend(*newlist, (void *)xstrdup(snatched)); current_state = CSV_ST_SEPARATOR; } else if (CSVCL_BLANK(*s)) { if (sn != NULL) { *sn = '\0'; } sn = NULL; current_state = CSV_ST_SPACE_AFTER_QUOTE; } else if (CSVCL_ANY8(*s)) { snatched[0] = '\0'; sn = NULL; current_state = CSV_ST_ERROR; } s++; break; default: ret = CSV_ERR_UNKNOWN_STATE; goto clean; break; } } if (current_state != CSV_ST_LEADING_QUOTE && current_state != CSV_ST_WITH_QUOTE_MODE ) { if (sn != NULL) { *sn = *s; sn++; *sn = '\0'; sn = NULL; } if(current_state == CSV_ST_NO_QUOTE_MODE || current_state == CSV_ST_PRE_START_SPACE) { int len = strlen(snatched); if (len > 1 && snatched[len - 2] == '\r' && snatched[len - 1] == '\n') { snatched[len - 2] = '\0'; } } SeqAppend(*newlist, (void *)xstrdup(snatched)); snatched[0] = '\0'; } else { ret = CSV_ERR_UNEXPECTED_END; goto clean; } return CSV_ERR_OK; clean: if (newlist) { SeqDestroy(*newlist); } return ret; } Seq *SeqParseCsvString(const char *string) { Seq *newlist = SeqNew(16, free); if (LaunchCsvAutomata(string, &newlist) != CSV_ERR_OK) { return NULL; } return newlist; } char *GetCsvLineNext(FILE *fp) { if (!fp) { return NULL; } Writer *buffer = StringWriter(); char prev = 0; for (;;) { int current = fgetc(fp); if (current == EOF || feof(fp)) { break; } WriterWriteChar(buffer, current); if ((current == '\n') && (prev == '\r')) { break; } prev = current; } if (StringWriterLength(buffer) <= 0) { WriterClose(buffer); return NULL; } return StringWriterClose(buffer); } cfengine-3.6.2/libutils/atexit.c0000664000175100017510000000372212243421446016315 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #if defined(__MINGW32__) typedef struct AtExitList { AtExitFn fn; struct AtExitList *next; } AtExitList; static pthread_mutex_t atexit_functions_mutex = PTHREAD_MUTEX_INITIALIZER; static AtExitList *atexit_functions; /* To be called externally only by Windows service implementation */ void CallAtExitFunctions(void) { pthread_mutex_lock(&atexit_functions_mutex); AtExitList *p = atexit_functions; while (p) { AtExitList *cur = p; (cur->fn)(); p = cur->next; free(cur); } atexit_functions = NULL; pthread_mutex_unlock(&atexit_functions_mutex); } #endif void RegisterAtExitFunction(AtExitFn fn) { #if defined(__MINGW32__) pthread_mutex_lock(&atexit_functions_mutex); AtExitList *p = xmalloc(sizeof(AtExitList)); p->fn = fn; p->next = atexit_functions; atexit_functions = p; pthread_mutex_unlock(&atexit_functions_mutex); #endif atexit(fn); } cfengine-3.6.2/libutils/string_lib.c0000664000175100017510000004371612404565361017166 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* BUF_MEM */ #include /* BIO_* */ #include /* BIO_f_base64 */ #include #include #include #include char *StringVFormat(const char *fmt, va_list ap) { char *value; int ret = xvasprintf(&value, fmt, ap); if (ret < 0) { return NULL; } else { return value; } } char *StringFormat(const char *fmt, ...) { va_list ap; va_start(ap, fmt); char *res = StringVFormat(fmt, ap); va_end(ap); return res; } unsigned int StringHash(const char *str, unsigned int seed, unsigned int max) { unsigned const char *p = str; unsigned int h = seed; size_t len = strlen(str); for (size_t i = 0; i < len; i++) { h += p[i]; h += (h << 10); h ^= (h >> 6); } h += (h << 3); h ^= (h >> 11); h += (h << 15); return (h & (max - 1)); } char ToLower(char ch) { if (isupper((unsigned char) ch)) { return (ch - 'A' + 'a'); } else { return (ch); } } /*********************************************************************/ char ToUpper(char ch) { if ((isdigit((unsigned char) ch)) || (ispunct((unsigned char) ch))) { return (ch); } if (isupper((unsigned char) ch)) { return (ch); } else { return (ch - 'a' + 'A'); } } /*********************************************************************/ void ToUpperStrInplace(char *str) { for (; *str != '\0'; str++) { *str = ToUpper(*str); } } /*********************************************************************/ void ToLowerStrInplace(char *str) { for (; *str != '\0'; str++) { *str = ToLower(*str); } } /*********************************************************************/ char *SafeStringDuplicate(const char *str) { if (str == NULL) { return NULL; } return xstrdup(str); } /*********************************************************************/ int SafeStringLength(const char *str) { if (str == NULL) { return 0; } return strlen(str); } int StringSafeCompare(const char *a, const char *b) { if (a == b) { return 0; } if (a && b) { return strcmp(a, b); } if (a == NULL) { return -1; } assert(b == NULL); return +1; } bool StringSafeEqual(const char *a, const char *b) { if (a == b) { return true; } if ((a == NULL) || (b == NULL)) { return false; } return strcmp(a, b) == 0; } /*********************************************************************/ char *SearchAndReplace(const char *source, const char *search, const char *replace) { const char *source_ptr = source; if ((source == NULL) || (search == NULL) || (replace == NULL)) { ProgrammingError("Programming error: NULL argument is passed to SearchAndReplace"); } if (strcmp(search, "") == 0) { return xstrdup(source); } Writer *w = StringWriter(); for (;;) { const char *found_ptr = strstr(source_ptr, search); if (found_ptr == NULL) { WriterWrite(w, source_ptr); return StringWriterClose(w); } WriterWriteLen(w, source_ptr, found_ptr - source_ptr); WriterWrite(w, replace); source_ptr += found_ptr - source_ptr + strlen(search); } } /*********************************************************************/ char *StringConcatenate(size_t count, const char *first, ...) { if (count < 1) { return NULL; } size_t total_length = first ? strlen(first) : 0; va_list args; va_start(args, first); for (size_t i = 1; i < count; i++) { const char *arg = va_arg(args, const char*); if (arg) { total_length += strlen(arg); } } va_end(args); char *result = xcalloc(total_length + 1, sizeof(char)); if (first) { strcat(result, first); } va_start(args, first); for (size_t i = 1; i < count; i++) { const char *arg = va_arg(args, const char *); if (arg) { strcat(result, arg); } } va_end(args); return result; } /*********************************************************************/ char *StringSubstring(const char *source, size_t source_len, int start, int len) { size_t end = -1; if (len == 0) { return SafeStringDuplicate(""); } else if (len < 0) { end = source_len + len - 1; } else { end = start + len - 1; } end = MIN(end, source_len - 1); if (start < 0) { start = source_len + start; } if (start >= end) { return NULL; } char *result = xcalloc(end - start + 2, sizeof(char)); memcpy(result, source + start, end - start + 1); return result; } /*********************************************************************/ bool StringIsNumeric(const char *s) { for (; *s; s++) { if (!isdigit((unsigned char)*s)) { return false; } } return true; } bool StringIsPrintable(const char *s) { for (; *s; s++) { if (!isprint((unsigned char)*s)) { return false; } } return true; } bool EmptyString(const char *s) { const char *sp; for (sp = s; *sp != '\0'; sp++) { if (!isspace((unsigned char)*sp)) { return false; } } return true; } /*********************************************************************/ long StringToLong(const char *str) { assert(str); char *end; long result = strtol(str, &end, 10); assert(!*end && "Failed to convert string to long"); return result; } char *StringFromLong(long number) { char *str = xcalloc(32, sizeof(char)); snprintf(str, 32, "%ld", number); return str; } /*********************************************************************/ double StringToDouble(const char *str) { assert(str); char *end; double result = strtod(str, &end); assert(!*end && "Failed to convert string to double"); return result; } char *StringFromDouble(double number) { return StringFormat("%.2f", number); } /*********************************************************************/ char *NULLStringToEmpty(char *str) { if(!str) { return ""; } return str; } /** * @NOTE this function always '\0'-terminates the destination string #dst. * @return length of written string #dst. */ size_t StringBytesToHex(char *dst, size_t dst_size, const unsigned char *src_bytes, size_t src_len) { static const char *const hex_chars = "0123456789abcdef"; size_t i = 0; while ((i < src_len) && (i*2 + 2 < dst_size)) /* room for 2 more hex chars */ { dst[2*i] = hex_chars[(src_bytes[i] >> 4) & 0xf]; dst[2*i + 1] = hex_chars[src_bytes[i] & 0xf]; i++; } assert(2*i < dst_size); dst[2*i] = '\0'; return 2*i; } bool IsStrIn(const char *str, const char *const strs[]) { int i; for (i = 0; strs[i]; ++i) { if (strcmp(str, strs[i]) == 0) { return true; } } return false; } bool IsStrCaseIn(const char *str, const char *const strs[]) { int i; for (i = 0; strs[i]; ++i) { if (strcasecmp(str, strs[i]) == 0) { return true; } } return false; } int CountChar(const char *string, char sep) { int count = 0; if (string == NULL) { return 0; } if (string && (strlen(string) == 0)) { return 0; } for (const char *sp = string; *sp != '\0'; sp++) { if ((*sp == '\\') && (*(sp + 1) == sep)) { ++sp; } else if (*sp == sep) { count++; } } return count; } void ReplaceChar(char *in, char *out, int outSz, char from, char to) /* Replaces all occurences of 'from' to 'to' in preallocated * string 'out'. */ { int len; int i; memset(out, 0, outSz); len = strlen(in); for (i = 0; (i < len) && (i < outSz - 1); i++) { if (in[i] == from) { out[i] = to; } else { out[i] = in[i]; } } } /* TODO replace with StringReplace. This one is pretty slow, calls strncmp * O(n) times even if string matches nowhere. */ bool ReplaceStr(const char *in, char *out, int outSz, const char *from, const char *to) /* Replaces all occurences of strings 'from' to 'to' in preallocated * string 'out'. Returns true on success, false otherwise. */ { int inSz; int outCount; int inCount; int fromSz, toSz; memset(out, 0, outSz); inSz = strlen(in); fromSz = strlen(from); toSz = strlen(to); inCount = 0; outCount = 0; while ((inCount < inSz) && (outCount < outSz)) { if (strncmp(in + inCount, from, fromSz) == 0) { if (outCount + toSz >= outSz) { return false; } strcat(out, to); inCount += fromSz; outCount += toSz; } else { out[outCount] = in[inCount]; inCount++; outCount++; } } return true; } void ReplaceTrailingChar(char *str, char from, char to) /* Replaces any unwanted last char in str. */ { int strLen; strLen = SafeStringLength(str); if (strLen == 0) { return; } if (str[strLen - 1] == from) { str[strLen - 1] = to; } } static StringRef StringRefNull(void) { return (StringRef) { .data = NULL, .len = 0 }; } size_t StringCountTokens(const char *str, size_t len, const char *seps) { size_t num_tokens = 0; bool in_token = false; for (size_t i = 0; i < len; i++) { if (strchr(seps, str[i])) { in_token = false; } else { if (!in_token) { num_tokens++; } in_token = true; } } return num_tokens; } static StringRef StringNextToken(const char *str, size_t len, const char *seps) { size_t start = 0; bool found = false; for (size_t i = 0; i < len; i++) { if (strchr(seps, str[i])) { if (found) { assert(i > 0); return (StringRef) { .data = str + start, .len = i - start }; } } else { if (!found) { found = true; start = i; } } } if (found) { return (StringRef) { .data = str + start, .len = len - start }; } else { return StringRefNull(); } } StringRef StringGetToken(const char *str, size_t len, size_t index, const char *seps) { StringRef ref = StringNextToken(str, len, seps); for (size_t i = 0; i < index; i++) { if (!ref.data) { return ref; } len = len - (ref.data - str + ref.len); str = ref.data + ref.len; ref = StringNextToken(str, len, seps); } return ref; } char **String2StringArray(const char *str, char separator) /** * Parse CSVs into char **. * MEMORY NOTE: Caller must free return value with FreeStringArray(). **/ { int i = 0, len; if (str == NULL) { return NULL; } for (const char *sp = str; *sp != '\0'; sp++) { if (*sp == separator) { i++; } } char **arr = (char **) xcalloc(i + 2, sizeof(char *)); const char *sp = str; i = 0; while (sp) { const char *esp = strchr(sp, separator); if (esp) { len = esp - sp; esp++; } else { len = strlen(sp); } arr[i] = xcalloc(len + 1, sizeof(char)); memcpy(arr[i], sp, len); sp = esp; i++; } return arr; } void FreeStringArray(char **strs) { int i; if (strs == NULL) { return; } for (i = 0; strs[i] != NULL; i++) { free(strs[i]); strs[i] = NULL; } free(strs); } char *EscapeCharCopy(const char *str, char to_escape, char escape_with) /* * Escapes the 'to_escape'-chars found in str, by prefixing them with 'escape_with'. * Returns newly allocated string. */ { assert(str); int in_size = strlen(str); int out_size = in_size + CountChar(str, to_escape) + 1; char *out = xcalloc(1, out_size); const char *in_pos = str; char *out_pos = out; for(; *in_pos != '\0'; in_pos++, out_pos++) { if(*in_pos == to_escape) { *out_pos = escape_with; out_pos++; } *out_pos = *in_pos; } return out; } int StringInArray(char **array, char *string) { for (int i = 0; array[i] != NULL; i++) { if (strcmp(string, array[i]) == 0) { return true; } } return false; } char *ScanPastChars(char *scanpast, char *input) { char *pos = input; while ((*pos != '\0') && (strchr(scanpast, *pos))) { pos++; } return pos; } int StripTrailingNewline(char *str, size_t max_length) { if (str) { size_t i = strnlen(str, max_length + 1); if (i > max_length) /* See off-by-one comment below */ { return -1; } while (i > 0 && str[i - 1] == '\n') { i--; } assert(str[i] == '\0' || str[i] == '\n'); str[i] = '\0'; } return 0; } /* Off-by-one quirk in max_length. * * Both StripTrailngNewline() and Chop() have long allowed callers to * pass (effectively) the strlen(str) rather than the size of memory * (which is at least strlen() + 1) in the buffer. The present * incarnation thus reads max_length as max-strlen(), not as size of * the buffer. It may be sensible to review all callers and change so * that max_length is the buffer size instead. * * TODO: assess practicality of that change in behaviour. */ int Chop(char *str, size_t max_length) { if (str) { size_t i = strnlen(str, max_length + 1); if (i > max_length) /* See off-by-one comment above */ { return -1; } while (i > 0 && isspace((unsigned char)str[i-1])) { i--; } assert(str[i] == '\0' || isspace((unsigned char)str[i])); str[i] = '\0'; } return 0; } bool StringEndsWith(const char *str, const char *suffix) { size_t str_len = strlen(str); size_t suffix_len = strlen(suffix); if (suffix_len > str_len) { return false; } for (size_t i = 0; i < suffix_len; i++) { if (str[str_len - i - 1] != suffix[suffix_len - i - 1]) { return false; } } return true; } bool StringStartsWith(const char *str, const char *prefix) { int str_len = strlen(str); int prefix_len = strlen(prefix); if (prefix_len > str_len) { return false; } for (int i = 0; i < prefix_len; i++) { if (str[i] != prefix[i]) { return false; } } return true; } void *MemSpan(const void *mem, char c, size_t n) { const char *end = mem + n; for (; (char*)mem < end; ++mem) { if (*((char *)mem) != c) { return (char *)mem; } } return (char *)mem; } void *MemSpanInverse(const void *mem, char c, size_t n) { const char *end = mem + n; for (; (char*)mem < end; ++mem) { if (*((char*)mem) == c) { return (char *)mem; } } return (char *)mem; } /* * @brief extract info from input string given two types of constraints: * - length of the extracted string is bounded * - extracted string should stop at first element of an exclude list * * @param[in] isp : the string to scan * @param[in] limit : size limit on the output string (including '\0') * @param[in] exclude : characters to be excluded from output buffer * @param[out] obuf : the output buffer * @retval true if string was capped, false if not */ bool StringNotMatchingSetCapped(const char *isp, int limit, const char *exclude, char *obuf) { size_t l = strcspn(isp, exclude); if (l < limit-1) { memcpy(obuf, isp, l); obuf[l]='\0'; return false; } else { memcpy(obuf, isp, limit-1); obuf[limit-1]='\0'; return true; } } bool StringAppend(char *dst, const char *src, size_t n) { int i, j; n--; for (i = 0; i < n && dst[i]; i++) { } for (j = 0; i < n && src[j]; i++, j++) { dst[i] = src[j]; } dst[i] = '\0'; return (i < n || !src[j]); } cfengine-3.6.2/libutils/logging_priv.h0000664000175100017510000000346312411001073017477 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_LOGGING_PRIV_H #define CFENGINE_LOGGING_PRIV_H #include /* * This interface is private and intended only for use by logging extensions (such as one defined in libpromises). */ typedef struct LoggingPrivContext LoggingPrivContext; typedef char *(*LoggingPrivLogHook)(LoggingPrivContext *context, LogLevel level, const char *message); struct LoggingPrivContext { LoggingPrivLogHook log_hook; void *param; }; /** * @brief Attaches context to logging for current thread */ void LoggingPrivSetContext(LoggingPrivContext *context); /** * @brief Retrieves logging context for current thread */ LoggingPrivContext *LoggingPrivGetContext(void); /** * @brief Set logging (syslog) and reporting (stdout) level for current thread */ void LoggingPrivSetLevels(LogLevel log_level, LogLevel report_level); #endif cfengine-3.6.2/libutils/refcount.h0000644000175100017510000000700712316547775016666 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_REFCOUNT_H #define CFENGINE_REFCOUNT_H #include /** @brief Simple reference count implementation. Reference counting helps to keep track of elements and avoid unnecessary duplication. In C we need to manually keep track of the users, while in C++ this is implicitly done by the "this" pointer. If we don't do that and we just count how many users we have, we risk multiples attach or detach. We need one way to find out who is connected to the refcount so we can act properly. */ struct RefCountNode { struct RefCountNode *next; struct RefCountNode *previous; void *user; }; typedef struct RefCountNode RefCountNode; struct RefCount { // Normally one unless we are shared. unsigned int user_count; RefCountNode *users; RefCountNode *last; }; typedef struct RefCount RefCount; /** @brief Initializes a refcount structure. @param ref RefCount structure to be initialized. */ void RefCountNew(RefCount **ref); /** @brief Destroys a refcount structure. @param ref RefCount structure to be destroyed. */ void RefCountDestroy(RefCount **ref); /** @brief Attaches a data structure to a given RefCount structure. Attaching refers to the fact that the container is using a data structure that might be shared by others. This should be called before using the data structure so everybody is aware of the new holder. @param ref RefCountr structure @param owner Data structure to be attached. */ void RefCountAttach(RefCount *ref, void *owner); /** @brief Detaches a data structure from a given RefCount structure. Detaching should be called after the container has copied the data structure. As long as the container is still using the data structure it should not detach from the reference counting. Otherwise this might lead to undesired side effects. @param ref RefCountr structure @param owner Data structure to be detached. */ void RefCountDetach(RefCount *ref, void *owner); /** @brief Simple check to see if a given data structure is shared. @param ref RefCount structure. @return True if shared, false otherwise. */ bool RefCountIsShared(RefCount *ref); /** @brief Compares two RefCount structures. @param a @param b @return True if a and b point to the same object, false otherwise. @remarks This function is needed in order to speed up comparisons of complex data structures. If the RefCount objects of the two structures are the same, then most likely the structures are the same. */ bool RefCountIsEqual(RefCount *a, RefCount *b); #endif // CFENGINE_REFCOUNT_H cfengine-3.6.2/libutils/mustache.h0000664000175100017510000000026612411001073016620 0ustar00a10038a1003800000000000000#ifndef CFENGINE_MUSTACHE_H #define CFENGINE_MUSTACHE_H #include #include bool MustacheRender(Buffer *out, const char *input, const JsonElement *hash); #endif cfengine-3.6.2/libutils/map_common.h0000664000175100017510000000240112243421446017142 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_MAP_COMMON_H #define CFENGINE_MAP_COMMON_H #include /* * Key/Value pair. */ typedef struct { void* key; void *value; } MapKeyValue; typedef bool (*MapKeyEqualFn)(const void *key1, const void *key2); typedef void (*MapDestroyDataFn)(void *key); #endif cfengine-3.6.2/libutils/rb-tree.c0000664000175100017510000003641712411001073016351 0ustar00a10038a1003800000000000000#include #include #include typedef struct RBNode_ RBNode; struct RBNode_ { void *key; void *value; bool red; RBNode *parent; RBNode *left; RBNode *right; }; struct RBTree_ { void *(*KeyCopy)(const void *key); int (*KeyCompare)(const void *a, const void *b); void (*KeyDestroy)(void *key); void *(*ValueCopy)(const void *key); int (*ValueCompare)(const void *a, const void *b); void (*ValueDestroy)(void *key); struct RBNode_ *root; struct RBNode_ *nil; size_t size; }; struct RBTreeIterator_ { const RBTree *tree; RBNode *curr; }; static void PutFix_(RBTree *tree, RBNode *z); static RBNode *Next_(const RBTree *tree, const RBNode *node); static void VerifyTree_(RBTree *tree); static int PointerCompare_(const void *a, const void *b) { return a - b; } static void NoopDestroy_(ARG_UNUSED void *a) { return; } static void *NoopCopy_(const void *a) { return (void *)a; } static RBNode *NodeNew_(RBTree *tree, RBNode *parent, bool red, const void *key, const void *value) { RBNode *node = xmalloc(sizeof(RBNode)); node->parent = parent; node->red = red; node->key = tree->KeyCopy(key); node->value = tree->ValueCopy(value); node->left = tree->nil; node->right = tree->nil; return node; } static void NodeDestroy_(RBTree *tree, RBNode *node) { if (node) { tree->KeyDestroy(node->key); tree->ValueDestroy(node->value); free(node); } } static void Reset_(RBTree *tree) { tree->nil->key = tree->nil->value = NULL; tree->nil->red = false; tree->nil->parent = tree->nil->left = tree->nil->right = tree->nil; tree->root->key = tree->root->value = NULL; tree->root->red = false; tree->root->parent = tree->root->left = tree->root->right = tree->nil; tree->size = 0; } RBTree *RBTreeNew(void *(*KeyCopy)(const void *key), int (*KeyCompare)(const void *a, const void *b), void (*KeyDestroy)(void *key), void *(*ValueCopy)(const void *key), int (*ValueCompare)(const void *a, const void *b), void (*ValueDestroy)(void *key)) { assert(!(KeyCopy && KeyDestroy) || (KeyCopy && KeyDestroy)); assert(!(ValueCopy && ValueDestroy) || (ValueCopy && ValueDestroy)); RBTree *t = xmalloc(sizeof(RBTree)); t->KeyCopy = KeyCopy ? KeyCopy : NoopCopy_; t->KeyCompare = KeyCompare ? KeyCompare : PointerCompare_; t->KeyDestroy = KeyDestroy ? KeyDestroy : NoopDestroy_; t->ValueCopy = ValueCopy ? ValueCopy : NoopCopy_; t->ValueCompare = ValueCompare ? ValueCompare : PointerCompare_; t->ValueDestroy = ValueDestroy ? ValueDestroy : NoopDestroy_; t->nil = xcalloc(1, sizeof(RBNode)); t->root = xcalloc(1, sizeof(RBNode)); Reset_(t); return t; } static void TreeDestroy_(RBTree *tree, RBNode *x) { if (x != tree->nil) { TreeDestroy_(tree, x->left); TreeDestroy_(tree, x->right); NodeDestroy_(tree, x); } } RBTree *RBTreeCopy(const RBTree *tree, RBTreePredicate *filter, void *user_data) { RBNode **nodes = xmalloc(tree->size * sizeof(RBNode *)); size_t node_count = 0; { RBTreeIterator *iter = NULL; for (iter = RBTreeIteratorNew(tree); iter->curr != iter->tree->nil; iter->curr = Next_(iter->tree, iter->curr)) { if (!filter || filter(iter->curr->key, iter->curr->value, user_data)) { nodes[node_count] = iter->curr; node_count++; } } RBTreeIteratorDestroy(iter); } RBTree *copy = RBTreeNew(tree->KeyCopy, tree->KeyCompare, tree->KeyDestroy, tree->ValueCopy, tree->ValueCompare, tree->ValueDestroy); RBNode *node = NULL; // [0, 1, 2, 3, 4] if ((node_count % 2) != 0) { node = nodes[node_count / 2]; RBTreePut(copy, node->key, node->value); node_count--; } else { node = copy->root; } assert((node_count % 2) == 0); // [0, 1, 2, 3] for (size_t i = 0; i < (node_count / 2); i += 1) { node = nodes[(node_count / 2) + i]; RBTreePut(copy, node->key, node->value); node = nodes[(node_count / 2) - i - 1]; RBTreePut(copy, node->key, node->value); } free(nodes); VerifyTree_(copy); return copy; } bool RBTreeEqual(const void *_a, const void *_b) { const RBTree *a = _a, *b = _b; if (a == b) { return true; } if (a == NULL || b == NULL) { return false; } if (a->KeyCompare != b->KeyCompare || a->ValueCompare != b->ValueCompare) { return false; } if (RBTreeSize(a) != RBTreeSize(b)) { return false; } RBTreeIterator *it_a = RBTreeIteratorNew(a); RBTreeIterator *it_b = RBTreeIteratorNew(b); void *a_key, *a_val, *b_key, *b_val; while (RBTreeIteratorNext(it_a, &a_key, &a_val) && RBTreeIteratorNext(it_b, &b_key, &b_val)) { if (a->KeyCompare(a_key, b_key) != 0 || b->ValueCompare(a_val, b_val)) { RBTreeIteratorDestroy(it_a); RBTreeIteratorDestroy(it_b); return false; } } RBTreeIteratorDestroy(it_a); RBTreeIteratorDestroy(it_b); return true; } void RBTreeDestroy(void *rb_tree) { RBTree *tree = rb_tree; if (tree) { TreeDestroy_(tree, tree->root->left); free(tree->root); free(tree->nil); free(tree); } } static void RotateLeft_(RBTree *tree, RBNode *x) { assert(!tree->nil->red); RBNode *y = x->right; x->right = y->left; if (y->left != tree->nil) { y->left->parent = x; } y->parent = x->parent; if (x == x->parent->left) { x->parent->left = y; } else { x->parent->right = y; } y->left = x; x->parent = y; assert(!tree->nil->red); } static void RotateRight_(RBTree *tree, RBNode *y) { assert(!tree->nil->red); RBNode *x = y->left; y->left = x->right; if (x->right != tree->nil) { x->right->parent = y; } x->parent = y->parent; if (y == y->parent->left) { y->parent->left = x; } else { y->parent->right = x; } x->right = y; y->parent = x; assert(!tree->nil->red); } typedef struct { bool replaced; RBNode *node; } InsertResult_; static void PutFix_(RBTree *tree, RBNode *z) { while (z->parent->red) { if (z->parent == z->parent->parent->left) { RBNode *y = z->parent->parent->right; if (y->red) { // case 1 z->parent->red = false; y->red = false; z->parent->parent->red = true; z = z->parent->parent; } else { if (z == z->parent->right) { // case 2 z = z->parent; RotateLeft_(tree, z); } // case 3 z->parent->red = false; z->parent->parent->red = true; RotateRight_(tree, z->parent->parent); } } else { RBNode *y = z->parent->parent->left; if (y->red) { // case 1 z->parent->red = false; y->red = false; z->parent->parent->red = true; z = z->parent->parent; } else { if (z == z->parent->left) { // case 2 z = z->parent; RotateRight_(tree, z); } // case 3 z->parent->red = false; z->parent->parent->red = true; RotateLeft_(tree, z->parent->parent); } } } tree->root->left->red = false; assert(!tree->nil->red); assert(!tree->root->red); } bool RBTreePut(RBTree *tree, const void *key, const void *value) { RBNode *y = tree->root; RBNode *x = tree->root->left; while (x != tree->nil) { y = x; int cmp = tree->KeyCompare(key, x->key); if (cmp == 0) { tree->ValueDestroy(x->value); x->value = tree->ValueCopy(value); return true; } x = (cmp < 0) ? x->left : x->right; } RBNode *z = NodeNew_(tree, y, true, key, value); if (y == tree->root || tree->KeyCompare(z->key, y->key) < 0) { y->left = z; } else { y->right = z; } PutFix_(tree, z); tree->size++; return false; } static RBNode *Next_(const RBTree *tree, const RBNode *node) { if (node->right != tree->nil) { RBNode *curr; for (curr = node->right; curr->left != tree->nil; curr = curr->left); return curr; } else { RBNode *curr; for (curr = node->parent; node == curr->right; node = curr, curr = curr->parent); return (curr != tree->root) ? curr : tree->nil; } } static RBNode *Get_(const RBTree *tree, const void *key) { assert(!tree->nil->red); RBNode *curr = tree->root->left; while (curr != tree->nil) { int cmp = tree->KeyCompare(key, curr->key); if (cmp == 0) { return curr; } else if (cmp < 0) { curr = curr->left; } else { curr = curr->right; } } assert(!tree->nil->red); return curr; } void *RBTreeGet(const RBTree *tree, const void *key) { RBNode *node = Get_(tree, key); return node != tree->nil ? node->value : NULL; } void RemoveFix_(RBTree *tree, RBNode *x) { assert(!tree->nil->red); RBNode *root = tree->root->left; RBNode *w; while (x != root && !x->red) { if (x == x->parent->left) { w = x->parent->right; if (w->red) { w->red = false; x->parent->red = true; RotateLeft_(tree, x->parent); w = x->parent->right; } if (!w->left->red && !w->right->red) { w->red = true; x = x->parent; } else { if (!w->right->red) { w->left->red = false; w->red = true; RotateRight_(tree, w); w = x->parent->right; } w->red = x->parent->red; x->parent->red = false; w->right->red = false; RotateLeft_(tree, x->parent); x = root; } } else { w = x->parent->left; if (w->red) { w->red = false; x->parent->red = true; RotateRight_(tree, x->parent); w = x->parent->left; } if (!w->left->red && !w->right->red) { w->red = true; x = x->parent; } else { if (!w->left->red) { w->right->red = false; w->red = true; RotateLeft_(tree, w); w = x->parent->left; } w->red = x->parent->red; x->parent->red = false; w->left->red = false; RotateRight_(tree, x->parent); x = root; } } } x->red = false; assert(!tree->nil->red); } bool RBTreeRemove(RBTree *tree, const void *key) { assert(!tree->nil->red); RBNode *z = Get_(tree, key); if (z == tree->nil) { return false; } RBNode *y = ((z->left == tree->nil) || (z->right == tree->nil)) ? z : Next_(tree, z); RBNode *x = (y->left == tree->nil) ? y->right : y->left; x->parent = y->parent; if (tree->root == x->parent) { tree->root->left = x; } else { if (y == y->parent->left) { y->parent->left = x; } else { y->parent->right = x; } } if (z != y) { assert(y != tree->nil); assert(!tree->nil->red); if (!y->red) { RemoveFix_(tree, x); } y->left = z->left; y->right = z->right; y->parent = z->parent; y->red = z->red; z->left->parent = y; z->right->parent = y; if (z == z->parent->left) { z->parent->left = y; } else { z->parent->right = y; } NodeDestroy_(tree, z); } else { if (!y->red) { RemoveFix_(tree, x); } NodeDestroy_(tree, y); } assert(!tree->nil->red); tree->size--; return true; } void ClearRecursive_(RBTree *tree, RBNode *node) { if (node == tree->nil) { return; } ClearRecursive_(tree, node->left); ClearRecursive_(tree, node->right); NodeDestroy_(tree, node); } void RBTreeClear(RBTree *tree) { assert(tree); ClearRecursive_(tree, tree->root); tree->root = xcalloc(1, sizeof(RBNode)); Reset_(tree); } size_t RBTreeSize(const RBTree *tree) { return tree->size; } RBTreeIterator *RBTreeIteratorNew(const RBTree *tree) { RBTreeIterator *iter = xmalloc(sizeof(RBTreeIterator)); iter->tree = tree; for (iter->curr = iter->tree->root; iter->curr->left != tree->nil; iter->curr = iter->curr->left); return iter; } bool Peek_(RBTreeIterator *iter, void **key, void **value) { if (iter->tree->size == 0) { return false; } if (iter->curr == iter->tree->nil) { return false; } if (key) { *key = iter->curr->key; } if (value) { *value = iter->curr->value; } return true; } bool RBTreeIteratorNext(RBTreeIterator *iter, void **key, void **value) { if (Peek_(iter, key, value)) { iter->curr = Next_(iter->tree, iter->curr); return true; } else { return false; } } void RBTreeIteratorDestroy(void *_rb_iter) { free(_rb_iter); } static void VerifyNode_(RBTree *tree, RBNode *node, int black_count, int *path_black_count) { if (node->red) { assert(!node->left->red); assert(!node->right->red); } else { black_count++; } if (node == tree->nil) { assert(!node->red); if ((*path_black_count) == -1) { *path_black_count = black_count; } else { assert(black_count == *path_black_count); } } else { VerifyNode_(tree, node->left, black_count, path_black_count); VerifyNode_(tree, node->right, black_count, path_black_count); } } static void VerifyTree_(RBTree *tree) { assert(!tree->root->red); assert(!tree->root->key); assert(!tree->root->value); assert(!tree->nil->red); assert(!tree->nil->key); assert(!tree->nil->value); int path_black_count = -1; VerifyNode_(tree, tree->root->left, 0, &path_black_count); } cfengine-3.6.2/libutils/alloc.c0000644000175100017510000000437512316547775016133 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #define ALLOC_IMPL #include #include static void *CheckResult(void *ptr, const char *fn, bool check_result) { if ((ptr == NULL) && (check_result)) { fputs(fn, stderr); fputs("CRITICAL: Unable to allocate memory\n", stderr); exit(255); } return ptr; } void *xmalloc(size_t size) { return CheckResult(malloc(size), "xmalloc", size != 0); } void *xcalloc(size_t nmemb, size_t size) { return CheckResult(calloc(nmemb, size), "xcalloc", (nmemb != 0) && (size != 0)); } void *xrealloc(void *ptr, size_t size) { return CheckResult(realloc(ptr, size), "xrealloc", size != 0); } char *xstrdup(const char *str) { return CheckResult(strdup(str), "xstrdup", true); } char *xstrndup(const char *str, size_t n) { return CheckResult(strndup(str, n), "xstrndup", true); } void *xmemdup(const void *data, size_t size) { return CheckResult(memdup(data, size), "xmemdup", size != 0); } int xasprintf(char **strp, const char *fmt, ...) { va_list ap; va_start(ap, fmt); int res = xvasprintf(strp, fmt, ap); va_end(ap); return res; } int xvasprintf(char **strp, const char *fmt, va_list ap) { int res = vasprintf(strp, fmt, ap); CheckResult(res == -1 ? NULL : *strp, "xvasprintf", true); return res; } cfengine-3.6.2/libutils/unix_dir.c0000644000175100017510000001241112352557236016641 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include struct Dir_ { DIR *dirh; struct dirent *entrybuf; }; static size_t GetNameMax(DIR *dirp); static size_t GetDirentBufferSize(size_t path_len); Dir *DirOpen(const char *dirname) { Dir *ret = xcalloc(1, sizeof(Dir)); int safe_fd; safe_fd = safe_open(dirname, O_RDONLY); if (safe_fd < 0) { free(ret); return NULL; } ret->dirh = opendir(dirname); if (ret->dirh == NULL) { close(safe_fd); free(ret); return NULL; } struct stat safe_stat, dir_stat; bool stat_failed = fstat(safe_fd, &safe_stat) < 0 || fstat(dirfd(ret->dirh), &dir_stat) < 0; close(safe_fd); if (stat_failed) { closedir(ret->dirh); free(ret); return NULL; } // Make sure we opened the same file descriptor as safe_open did. if (safe_stat.st_dev != dir_stat.st_dev || safe_stat.st_ino != dir_stat.st_ino) { closedir(ret->dirh); free(ret); errno = EACCES; return NULL; } size_t dirent_buf_size = GetDirentBufferSize(GetNameMax(ret->dirh)); ret->entrybuf = xcalloc(1, dirent_buf_size); return ret; } /* * Returns NULL on EOF or error. * * Sets errno to 0 for EOF and non-0 for error. */ const struct dirent *DirRead(Dir *dir) { errno = 0; struct dirent *ret; int err = readdir_r((DIR *) dir->dirh, dir->entrybuf, &ret); if (err != 0) { errno = err; return NULL; } if (ret == NULL) { return NULL; } return ret; } void DirClose(Dir *dir) { closedir((DIR *) dir->dirh); free(dir->entrybuf); free(dir); } /* * Taken from http://womble.decadent.org.uk/readdir_r-advisory.html * * Issued by Ben Hutchings , 2005-11-02. * * Licence * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following condition: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * Calculate the required buffer size (in bytes) for directory entries read from * the given directory handle. Return -1 if this this cannot be done. * * This code does not trust values of NAME_MAX that are less than 255, since * some systems (including at least HP-UX) incorrectly define it to be a smaller * value. * * If you use autoconf, include fpathconf and dirfd in your AC_CHECK_FUNCS list. * Otherwise use some other method to detect and use them where available. */ #if defined(HAVE_FPATHCONF) && defined(_PC_NAME_MAX) static size_t GetNameMax(DIR *dirp) { long name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); if (name_max != -1) { return name_max; } # if defined(NAME_MAX) return (NAME_MAX > 255) ? NAME_MAX : 255; # else return (size_t) (-1); # endif } #else /* FPATHCONF && _PC_NAME_MAX */ # if defined(NAME_MAX) static size_t GetNameMax(DIR *dirp) { return (NAME_MAX > 255) ? NAME_MAX : 255; } # else # error "buffer size for readdir_r cannot be determined" # endif #endif /* FPATHCONF && _PC_NAME_MAX */ /* * Returns size of memory enough to hold path name_len bytes long. */ static size_t GetDirentBufferSize(size_t name_len) { size_t name_end = (size_t) offsetof(struct dirent, d_name) + name_len + 1; return (name_end > sizeof(struct dirent) ? name_end : sizeof(struct dirent)); } struct dirent *AllocateDirentForFilename(const char *filename) { struct dirent *entry = xcalloc(1, GetDirentBufferSize(strlen(filename))); strcpy(entry->d_name, filename); return entry; } cfengine-3.6.2/libutils/hash_method.h0000664000175100017510000000142512411001073017270 0ustar00a10038a1003800000000000000/* * HashMethod (unfortunately) needs to be defined in cf3.defs.h. By putting it * separate here we avoid cf3.defs.h pulling the whole OpenSSL includes that * hash.h has. */ #ifndef CFENGINE_HASH_METHOD_H #define CFENGINE_HASH_METHOD_H typedef enum { HASH_METHOD_MD5, HASH_METHOD_SHA224, HASH_METHOD_SHA256, HASH_METHOD_SHA384, HASH_METHOD_SHA512, HASH_METHOD_SHA1, HASH_METHOD_SHA, HASH_METHOD_BEST, HASH_METHOD_CRYPT, HASH_METHOD_NONE } HashMethod; typedef enum { CF_MD5_LEN = 16, CF_SHA224_LEN = 28, CF_SHA256_LEN = 32, CF_SHA384_LEN = 48, CF_SHA512_LEN = 64, CF_SHA1_LEN = 20, CF_SHA_LEN = 20, CF_BEST_LEN = 0, CF_CRYPT_LEN = 64, CF_NO_HASH = 0 } HashSize; #endif /* CFENGINE_HASH_METHOD_H */ cfengine-3.6.2/libutils/hash.h0000664000175100017510000000767312400110676015753 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_HASH_H #define CFENGINE_HASH_H /** @brief Hash implementations */ #include #include /* HashMethod, HashSize */ typedef struct Hash Hash; /** @brief Creates a new structure of type Hash. @param data String to hash. @param length Length of the string to hash. @param method Hash method. @return A structure of type Hash or NULL in case of error. */ Hash *HashNew(const char *data, const unsigned int length, HashMethod method); /** @brief Creates a new structure of type Hash. @param descriptor Either file descriptor or socket descriptor. @param method Hash method. @return A structure of type Hash or NULL in case of error. */ Hash *HashNewFromDescriptor(const int descriptor, HashMethod method); /** @brief Creates a new structure of type Hash. @param rsa RSA key to be hashed. @param method Hash method. @return A structure of type Hash or NULL in case of error. */ Hash *HashNewFromKey(const RSA *rsa, HashMethod method); /** @brief Destroys a structure of type Hash. @param hash The structure to be destroyed. */ void HashDestroy(Hash **hash); /** @brief Copy a hash @param origin Hash to be copied. @param destination Hash to be copied to. @return 0 if successful, -1 in any other case. */ int HashCopy(Hash *origin, Hash **destination); /** @brief Checks if two hashes are equal. @param a 1st hash to be compared. @param b 2nd hash to be compared. @return True if both hashes are equal and false in any other case. */ int HashEqual(const Hash *a, const Hash *b); /** @brief Pointer to the raw digest data. @note Notice that this is a binary representation and not '\0' terminated. @param hash Hash structure. @param length Pointer to an unsigned int to hold the length of the data. @return A pointer to the raw digest data. */ const unsigned char *HashData(const Hash *hash, unsigned int *length); /** @brief Printable hash representation. @param hash Hash structure. @return A pointer to the printable digest representation. */ const char *HashPrintable(const Hash *hash); /** @brief Hash type. @param hash Hash structure @return The hash method used by this hash structure. */ HashMethod HashType(const Hash *hash); /** @brief Hash length in bytes. @param hash Hash structure @return The hash length in bytes. */ HashSize HashLength(const Hash *hash); /** @brief Returns the ID of the hash based on the name @param hash_name Name of the hash. @return Returns the ID of the hash from the name. */ HashMethod HashIdFromName(const char *hash_name); /** @brief Returns the name of the hash based on the ID. @param hash_id Id of the hash. @return Returns the name of the hash. */ const char *HashNameFromId(HashMethod hash_id); /** @brief Size of the hash @param method Hash method @return Returns the size of the hash or 0 in case of error. */ HashSize HashSizeFromId(HashMethod hash_id); #endif // CFENGINE_HASH_H cfengine-3.6.2/libutils/platform.h0000664000175100017510000005244112411001073016635 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_PLATFORM_H #define CFENGINE_PLATFORM_H /* * Platform-specific definitions and declarations. * * INCLUDE THIS HEADER ALWAYS FIRST in order to define apropriate macros for * including system headers (such as _FILE_OFFSET_BITS). */ #ifdef HAVE_CONFIG_H # include #endif #define _GNU_SOURCE 1 #ifdef _WIN32 # define MAX_FILENAME 227 # define WINVER 0x501 #if defined(__CYGWIN__) # undef FD_SETSIZE #endif /* Increase select(2) FD limit from 64. It's documented and valid to do it * like that provided that we define it *before* including winsock2.h. */ # define FD_SETSIZE 4096 #else # define MAX_FILENAME 254 #endif #ifdef __MINGW32__ # include # include # include # include # include # include # include # include # include # include # include // for disphelper #endif /* Standard C. */ #include #include #include #include #include #include /* offsetof, size_t */ /* POSIX but available in all platforms. */ #include #include #include #include /* We now require a pthreads implementation. */ #include #ifndef _GETOPT_H # include <../libcompat/getopt.h> #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_UNAME # include #else # define _SYS_NMLN 257 struct utsname { char sysname[_SYS_NMLN]; char nodename[_SYS_NMLN]; char release[_SYS_NMLN]; char version[_SYS_NMLN]; char machine[_SYS_NMLN]; }; #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_SYS_SYSTEMINFO_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_SYS_MOUNT_H # include #endif #ifdef HAVE_SYS_WAIT_H # include #endif #ifndef WEXITSTATUS # define WEXITSTATUS(s) ((unsigned)(s) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(s) (((s) & 255) == 0) #endif #ifndef WIFSIGNALED # define WIFSIGNALED(s) ((s) & 0) /* Can't use for BSD */ #endif #ifndef WTERMSIG # define WTERMSIG(s) ((s) & 0) #endif #include #include #ifdef HAVE_DIRENT_H # include #else # define dirent direct # if HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif #endif #ifndef PATH_MAX # ifdef _MAX_PATH # define PATH_MAX _MAX_PATH # else # define PATH_MAX 4096 # endif #endif #include #ifdef __MINGW32__ # define LOG_LOCAL0 (16<<3) # define LOG_LOCAL1 (17<<3) # define LOG_LOCAL2 (18<<3) # define LOG_LOCAL3 (19<<3) # define LOG_LOCAL4 (20<<3) # define LOG_LOCAL5 (21<<3) # define LOG_LOCAL6 (22<<3) # define LOG_LOCAL7 (23<<3) # define LOG_USER (1<<3) # define LOG_DAEMON (3<<3) /* MinGW added this flag only in latest version. */ # ifndef IPV6_V6ONLY # define IPV6_V6ONLY 27 # endif // Not available in MinGW headers unless you raise WINVER and _WIN32_WINNT, but // that is very badly supported in MinGW ATM. ULONGLONG WINAPI GetTickCount64(void); #else /* !__MINGW32__ */ # include #endif #ifdef _AIX # ifndef ps2 # include # endif # include #endif #ifdef __sun # include # undef nfstype #include #ifndef timersub # define timersub(a, b, result) \ do \ { \ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ if ((result)->tv_usec < 0) \ { \ --(result)->tv_sec; \ (result)->tv_usec += 1000000; \ } \ } while (0) #endif #endif #if !HAVE_DECL_DIRFD int dirfd(DIR *dirp); #endif /* strndup is defined as a macro on many systems */ #if !HAVE_DECL_STRNDUP # ifndef strndup char *strndup(const char *s, size_t n); # endif #endif #if !HAVE_DECL_STRNLEN size_t strnlen(const char *str, size_t maxlen); #endif #ifdef HAVE_UNISTD_H # include #endif #if !HAVE_DECL_STRLCPY size_t strlcpy(char *destination, const char *source, size_t size); #endif #if !HAVE_DECL_STRLCAT size_t strlcat(char *destination, const char *source, size_t size); #endif #if !HAVE_DECL_STRSEP char *strsep(char **stringp, const char *delim); #endif #if !HAVE_DECL_SOCKETPAIR int socketpair(int domain, int type, int protocol, int sv[2]); #endif #if !HAVE_DECL_FSYNC int fsync(int fd); #endif #if !HAVE_DECL_GLOB #define GLOB_NOSPACE 1 #define GLOB_ABORTED 2 #define GLOB_NOMATCH 3 typedef struct { size_t gl_pathc; /* Count of paths matched so far */ char **gl_pathv; /* List of matched pathnames. */ size_t gl_offs; } glob_t; int glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob); void globfree(glob_t *pglob); #endif #ifdef __APPLE__ # include # include #endif #ifdef HAVE_SYS_MALLOC_H # ifdef __APPLE__ # include # include # endif #else # ifdef HAVE_MALLOC_H # ifndef __OpenBSD__ # ifdef __FreeBSD__ # include # else # include # endif # endif # endif #endif #include #ifdef HAVE_VFS_H # include #endif #ifdef __hpux # include #endif #ifdef HAVE_UTIME_H # include /* use utime not utimes for portability */ #elif TIME_WITH_SYS_TIME # include # include #elif HAVE_SYS_TIME_H # include #elif ! defined(AOS) # include #endif #ifdef HAVE_TIME_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #ifndef __MINGW32__ # include # include #endif #ifdef HAVE_SYS_SOCKIO_H # include #endif #ifndef __MINGW32__ # include # include # include # include # include # include # include # include # include # if !defined __linux__ && !defined _WIN32 # include # undef sgi # include # endif #endif #ifdef __linux__ # if defined(__GLIBC__) || defined(__BIONIC__) # include # include # include # else # include # include # include # endif #endif #ifndef CLOCK_REALTIME # define CLOCK_REALTIME 1 #endif #ifndef HAVE_CLOCKID_T typedef int clockid_t; #endif #ifndef HAVE_SOCKLEN_T typedef int socklen_t; #endif # ifndef _SC_THREAD_STACK_MIN # define _SC_THREAD_STACK_MIN PTHREAD_STACK_MIN #endif #ifndef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP # define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER #endif #if !HAVE_DECL_GETLOADAVG int getloadavg (double loadavg[], int nelem); #endif #ifdef HAVE_ENDIAN_H # include #endif #if !HAVE_DECL_LE32TOH static inline uint32_t ByteSwap32(uint32_t le32uint) { uint32_t be32uint; unsigned char *le_ptr = (unsigned char *)&le32uint; unsigned char *be_ptr = (unsigned char *)&be32uint; be_ptr[0] = le_ptr[3]; be_ptr[1] = le_ptr[2]; be_ptr[2] = le_ptr[1]; be_ptr[3] = le_ptr[0]; return be32uint; } # ifdef WORDS_BIGENDIAN # define le32toh(x) ByteSwap32(x) # define htole32(x) ByteSwap32(x) # else # define le32toh(x) (x) # define htole32(x) (x) # endif #endif // !HAVE_DECL_LE32TOH #if !HAVE_DECL_PTHREAD_ATTR_SETSTACKSIZE int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); #endif #ifdef HAVE_SCHED_H # include #endif #ifdef HAVE_ATTR_XATTR_H # include #elif defined(HAVE_SYS_XATTR_H) # include #endif #ifndef MIN # define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX # define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef INADDR_NONE # define INADDR_NONE ((unsigned long int) 0xffffffff) #endif #ifndef HAVE_SETEGID int setegid(gid_t gid); #endif #if !HAVE_DECL_UNAME int uname(struct utsname *buf); #endif #if !HAVE_DECL_GETUID uid_t getuid(void); #endif #if !HAVE_DECL_GETGID gid_t getgid(void); #endif #if !HAVE_DECL_FGETGRENT struct group *fgetgrent(FILE *stream); #endif #if !HAVE_DECL_DRAND48 double drand48(void); #endif #if !HAVE_DECL_SRAND48 void srand48(long seed); #endif #if !HAVE_DECL_CLOCK_GETTIME int clock_gettime(clockid_t clock_id, struct timespec *tp); #endif #if !HAVE_DECL_REALPATH /** * WARNING realpath() has varying behaviour among platforms. * - Do not use it to convert relative paths to absolute * (Solaris under certain conditions will return relative path). * - Do not use it to check existence of file * (on *BSD the last component of the path may not exist). * Use it only to resolve all symlinks and canonicalise filename, * i.e. remove double '/' and "/./" and "/../". * * @TODO what we need is a resolvepath(2) cross-platform implementation. */ # if defined (__MINGW32__) # define realpath(N,R) _fullpath((R), (N), PATH_MAX) # endif #endif #if !HAVE_DECL_LSTAT int lstat(const char *file_name, struct stat *buf); #endif #if !HAVE_DECL_SLEEP unsigned int sleep(unsigned int seconds); #endif #if !HAVE_DECL_NANOSLEEP int nanosleep(const struct timespec *req, struct timespec *rem); #endif #if !HAVE_DECL_CHOWN int chown(const char *path, uid_t owner, gid_t group); #endif #if !HAVE_DECL_FCHMOD int fchmod(int fd, mode_t mode); #endif #if !HAVE_DECL_GETNETGRENT int getnetgrent(char **host, char **user, char **domain); #endif #if !HAVE_DECL_SETNETGRENT #if SETNETGRENT_RETURNS_INT int #else void #endif setnetgrent(const char *netgroup); #endif #if !HAVE_DECL_ENDNETGRENT #if ENDNETGRENT_RETURNS_INT int #else void #endif endnetgrent(void); #endif #if !HAVE_DECL_STRSTR char *strstr(const char *haystack, const char *needle); #endif #if !HAVE_DECL_STRCASESTR char *strcasestr(const char *haystack, const char *needle); #endif #if !HAVE_DECL_STRCASECMP int strcasecmp(const char *s1, const char *s2); #endif #if !HAVE_DECL_STRNCASECMP int strncasecmp(const char *s1, const char *s2, size_t n); #endif #if !HAVE_DECL_STRSIGNAL char *strsignal(int sig); #endif #if !HAVE_DECL_STRDUP char *strdup(const char *str); #endif #if !HAVE_DECL_MEMRCHR void *memrchr(const void *s, int c, size_t n); #endif #if !HAVE_DECL_MEMDUP void *memdup(const void *mem, size_t size); #endif #if !HAVE_DECL_MEMMEM void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen); #endif #if !HAVE_DECL_STRERROR char *strerror(int err); #endif #if !HAVE_DECL_UNSETENV int unsetenv(const char *name); #endif #ifndef HAVE_SETEUID int seteuid(uid_t euid); #endif #ifndef HAVE_SETEUID int setegid(gid_t egid); #endif #if !HAVE_DECL_SETLINEBUF void setlinebuf(FILE *stream); #endif #if HAVE_STDARG_H # include # if !HAVE_VSNPRINTF int rpl_vsnprintf(char *, size_t, const char *, va_list); /* If [v]snprintf() does not exist or is not C99 compatible, then we assume * that [v]printf() and [v]fprintf() need to be provided as well. */ int rpl_vprintf(const char *format, va_list ap); int rpl_vfprintf(FILE *stream, const char *format, va_list ap); # endif # if !HAVE_SNPRINTF int rpl_snprintf(char *, size_t, const char *, ...); int rpl_printf(const char *format, ...); int rpl_fprintf(FILE *stream, const char *format, ...); # endif # if !HAVE_VASPRINTF int rpl_vasprintf(char **, const char *, va_list); # endif # if !HAVE_ASPRINTF int rpl_asprintf(char **, const char *, ...); # endif #endif /* HAVE_STDARG_H */ /* For example Solaris, does not have isfinite() in . */ #if !HAVE_DECL_ISFINITE && defined(HAVE_IEEEFP_H) # include # define isfinite(x) finite(x) #endif #if !HAVE_DECL_GETLINE ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif #if !HAVE_DECL_GMTIME_R struct tm *gmtime_r(const time_t *timep, struct tm *result); #endif #if !HAVE_DECL_LOCALTIME_R struct tm *localtime_r(const time_t *timep, struct tm *result); #endif #if !HAVE_DECL_CHMOD int chmod(const char *path, mode_t mode); #endif #if !HAVE_DECL_ALARM unsigned int alarm(unsigned int seconds); #endif #if !HAVE_DECL_MKDTEMP char *mkdtemp(char *template); #endif #if !HAVE_DECL_STRRSTR char *strrstr(const char *haystack, const char *needle); #endif #if !HAVE_DECL_INET_NTOP const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); #endif #if !HAVE_DECL_INET_PTON int inet_pton(int af, const char *src, void *dst); #endif #if !HAVE_DECL_GETADDRINFO int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); void freeaddrinfo(struct addrinfo *res); int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags); const char *gai_strerror(int errcode); #endif #if !HAVE_STRUCT_SOCKADDR_STORAGE #ifdef AF_INET6 #define sockaddr_storage sockaddr_in6 #else #define sockaddr_storage sockaddr #endif #endif #ifndef AF_INET6 /* if the platform doesn't have it, it's useless, but define it as -1 * since we need it in our code... */ #define AF_INET6 -1 #endif #ifndef AI_NUMERICSERV /* Not portable to MinGW so don't use it. */ #define AI_NUMERICSERV -1 #endif #if !defined(HAVE_MKDIR_PROPER) int rpl_mkdir(const char *pathname, mode_t mode); #endif #if !defined(HAVE_STAT_PROPER) int rpl_stat(const char *path, struct stat *buf); #define _stat64(name, st) rpl_stat(name, st) #endif #if !defined(HAVE_RENAME_PROPER) int rpl_rename(const char *oldpath, const char *newpath); #endif #if !defined(HAVE_CTIME_PROPER) char *rpl_ctime(const time_t *t); #endif #ifndef NGROUPS # define NGROUPS 20 #endif #if !HAVE_DECL_OPENAT int openat(int dirfd, const char *pathname, int flags, ...); int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags); int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags); #ifndef AT_SYMLINK_NOFOLLOW #define AT_SYMLINK_NOFOLLOW 0x1000 #endif #ifndef AT_FDCWD #define AT_FDCWD (-2) #endif #endif #if !HAVE_DECL_LOG2 double log2(double x); #endif /*******************************************************************/ /* Windows */ /*******************************************************************/ #ifdef __MINGW32__ # define MAXHOSTNAMELEN 256 // always adequate: http://msdn.microsoft.com/en-us/library/ms738527(VS.85).aspx // as seen in in_addr struct in winsock.h typedef u_long in_addr_t; // shold be in winnt.h, but is not in current MinGW version # ifndef VER_SUITE_WH_SERVER # define VER_SUITE_WH_SERVER 0x00008000 # endif /* Dummy signals, can be set to anything below 23 but * 2, 4, 8, 11, 15, 21, 22 which are taken. * Calling signal() with anything from below causes SIG_ERR * to be returned. */ # define SIGALRM 1 # define SIGHUP 3 # define SIGTRAP 5 # define SIGKILL 6 # define SIGPIPE 7 # define SIGCONT 9 # define SIGSTOP 10 # define SIGQUIT 12 # define SIGCHLD 13 # define SIGUSR1 14 # define SIGUSR2 16 # define SIGBUS 17 # if !defined( _TIMESPEC_DEFINED) && !defined(HAVE_STRUCT_TIMESPEC) # define HAVE_STRUCT_TIMESPEC 1 struct timespec { long tv_sec; long tv_nsec; }; # endif/* NOT _TIMESPEC_DEFINED */ #endif /* __MINGW32__ */ #ifndef ERESTARTSYS # define ERESTARTSYS EINTR #endif #ifndef EOPNOTSUPP # define EOPNOTSUPP EINVAL #endif #ifndef ENOTSUPP # define ENOTSUPP EINVAL #endif /*******************************************************************/ /* Copy file defines */ /*******************************************************************/ /* Based heavily on cp.c in GNU-fileutils */ #ifndef DEV_BSIZE # ifdef BSIZE # define DEV_BSIZE BSIZE # else/* !BSIZE */ # define DEV_BSIZE 4096 # endif/* !BSIZE */ #endif /* !DEV_BSIZE */ /* Extract or fake data from a `struct stat'. ST_BLKSIZE: Optimal I/O blocksize for the file, in bytes. ST_NBLOCKS: Number of 512-byte blocks in the file (including indirect blocks). */ #define SMALL_BLOCK_BUF_SIZE 512 #ifndef HAVE_ST_BLOCKS # define ST_BLKSIZE(statbuf) DEV_BSIZE # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */ # define ST_NBLOCKS(statbuf) (((statbuf).st_size + 512 - 1) / 512) # else/* !_POSIX_SOURCE && BSIZE */ # define ST_NBLOCKS(statbuf) (st_blocks ((statbuf).st_size)) # endif/* !_POSIX_SOURCE && BSIZE */ #else /* HAVE_ST_BLOCKS */ /* Some systems, like Sequents, return st_blksize of 0 on pipes. */ # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \ ? (statbuf).st_blksize : DEV_BSIZE) # if defined(__hpux) /* HP-UX counts st_blocks in 1024-byte units. This loses when mixing HP-UX and BSD filesystems with NFS. */ # define ST_NBLOCKS(statbuf) ((statbuf).st_blocks * 2) # else/* !hpux */ # if defined(_AIX) && defined(_I386) /* AIX PS/2 counts st_blocks in 4K units. */ # define ST_NBLOCKS(statbuf) ((statbuf).st_blocks * 8) # else /* not AIX PS/2 */ # define ST_NBLOCKS(statbuf) ((statbuf).st_blocks) # endif /* not AIX PS/2 */ # endif/* !hpux */ #endif /* HAVE_ST_BLOCKS */ #ifndef SEEK_CUR # define SEEK_CUR 1 #endif /*******************************************************************/ /* Ultrix/BSD don't have all these from sys/stat.h */ /*******************************************************************/ #ifndef S_IFBLK # define S_IFBLK 0060000 #endif #ifndef S_IFCHR # define S_IFCHR 0020000 #endif #ifndef S_IFDIR # define S_IFDIR 0040000 #endif #ifndef S_IFIFO # define S_IFIFO 0010000 #endif #ifndef S_IFREG # define S_IFREG 0100000 #endif #ifndef S_IFLNK # define S_IFLNK 0120000 #endif #ifndef S_IFSOCK # define S_IFSOCK 0140000 #endif #ifndef S_IFMT # define S_IFMT 00170000 #endif #ifndef S_ISREG # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif #ifndef S_ISFIFO # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #endif #ifndef S_ISCHR # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif #ifndef S_ISBLK # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #endif #ifndef S_ISSOCK # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #endif #ifndef S_IRUSR # define S_IRWXU 00700 # define S_IRUSR 00400 # define S_IWUSR 00200 # define S_IXUSR 00100 #endif #ifndef S_IRGRP # define S_IRWXG 00070 # define S_IRGRP 00040 # define S_IWGRP 00020 # define S_IXGRP 00010 #endif #ifndef S_IROTH # define S_IRWXO 00007 # define S_IROTH 00004 # define S_IWOTH 00002 # define S_IXOTH 00001 #endif /* Too bad we don't have FD_CLOEXEC -- but we can fake it */ #ifndef FD_CLOEXEC # define FD_CLOEXEC 0 #endif /* kill(2) on OS X returns ETIMEDOUT instead of ESRCH */ #ifndef ETIMEDOUT # define ETIMEDOUT ESRCH #endif /********************************************************************/ /* *BSD chflags stuff - */ /********************************************************************/ #if !defined UF_NODUMP # define UF_NODUMP 0 #endif #if !defined UF_IMMUTABLE # define UF_IMMUTABLE 0 #endif #if !defined UF_APPEND # define UF_APPEND 0 #endif #if !defined UF_OPAQUE # define UF_OPAQUE 0 #endif #if !defined UF_NOUNLINK # define UF_NOUNLINK 0 #endif #if !defined SF_ARCHIVED # define SF_ARCHIVED 0 #endif #if !defined SF_IMMUTABLE # define SF_IMMUTABLE 0 #endif #if !defined SF_APPEND # define SF_APPEND 0 #endif #if !defined SF_NOUNLINK # define SF_NOUNLINK 0 #endif #define CHFLAGS_MASK ( UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE | UF_NOUNLINK | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK ) /* For cygwin32 */ #if !defined O_BINARY # define O_BINARY 0 #endif #if !defined O_TEXT # define O_TEXT 0 #endif #if defined(__MINGW32__) /* _mkdir(3) */ # include #endif /* Must be always the last one! */ #include #include #endif /* CFENGINE_PLATFORM_H */ cfengine-3.6.2/libutils/ring_buffer.h0000664000175100017510000000144512411001073017277 0ustar00a10038a1003800000000000000#ifndef CFENGINE_RING_BUFFER_H #define CFENGINE_RING_BUFFER_H #include typedef struct RingBuffer_ RingBuffer; typedef struct RingBufferIterator_ RingBufferIterator; RingBuffer *RingBufferNew(size_t capacity, void *(*copy)(const void *), void (*destroy)(void *)); void RingBufferDestroy(RingBuffer *buf); void RingBufferAppend(RingBuffer *buf, void *item); void RingBufferClear(RingBuffer *buf); size_t RingBufferLength(const RingBuffer *buf); bool RingBufferIsFull(const RingBuffer *buf); const void *RingBufferHead(const RingBuffer *buf); const void *RingBufferTail(const RingBuffer *buf); RingBufferIterator *RingBufferIteratorNew(const RingBuffer *buf); void RingBufferIteratorDestroy(RingBufferIterator *iter); const void *RingBufferIteratorNext(RingBufferIterator *iter); #endif cfengine-3.6.2/libutils/atexit.h0000664000175100017510000000214612243421446016321 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_ATEXIT_H #define CFENGINE_ATEXIT_H typedef void (*AtExitFn)(void); void RegisterAtExitFunction(AtExitFn fn); #endif cfengine-3.6.2/libutils/proc_keyvalue.c0000644000175100017510000000420712352557236017674 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include typedef struct { void *orig_param; KeyNumericValueCallback orig_callback; } KeyNumericParserInfo; bool KeyNumericParserCallback(const char *field, const char *value, void *param) { KeyNumericParserInfo *info = param; long long numeric_value; if (sscanf(value, #if defined(__MINGW32__) "%I64d", #else "%lli", #endif &numeric_value) != 1) { /* Malformed file */ return false; } return (*info->orig_callback) (field, numeric_value, info->orig_param); } bool ParseKeyNumericValue(FILE *fd, KeyNumericValueCallback callback, void *param) { KeyNumericParserInfo info = { param, callback }; return ParseKeyValue(fd, KeyNumericParserCallback, &info); } bool ParseKeyValue(FILE *fd, KeyValueCallback callback, void *param) { char buf[1024]; while (fgets(buf, sizeof(buf), fd)) { char *s = strchr(buf, ':'); if (!s) { /* Malformed file */ return false; } *s = 0; if (!(*callback) (buf, s + 1, param)) { return false; } } return !ferror(fd); } cfengine-3.6.2/libutils/sequence.h0000644000175100017510000001663212352557236016646 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SEQUENCE_H #define CFENGINE_SEQUENCE_H #include /** @brief Sequence data-structure. This is an array-list loosely modeled on GSequence. It is a managed array of void pointers and can be used to store arbitrary data. The array list will auto-expand by a factor of EXPAND_FACTOR (e.g. 2) when necessary, but not contract. Because sequence is content agnostic, it does not support the usual copy semantics found in other CFEngine structures, such as RList. Thus, appending an item to a Sequence may imply a transfer of ownership. Clients that require copy semantics should therefore make sure that elements are copied before they are appended. Some Sequence operations may remove some or all of the elements held. In order to do so safely, it's incumbent upon the client to supply the necessary item destructor to the Sequence constructor. If the item destructor argument is NULL, Sequence will not attempt to free the item memory held. */ typedef struct { void **data; size_t length; size_t capacity; void (*ItemDestroy) (void *item); } Seq; #define SeqAt(seq, i) seq->data[i] /** @brief Length of the sequence. @note On NULL sequence return size 0. @param seq [in] sequence. @return Sequence length. */ size_t SeqLength(const Seq *seq); /** @brief Create a new Sequence @param [in] initial_capacity Size of initial buffer to allocate for item pointers. @param [in] ItemDestroy Optional item destructor to clean up memory when needed. @return A pointer to the created Sequence */ Seq *SeqNew(size_t initial_capacity, void (*ItemDestroy) ()); /** @brief Destroy an existing Sequence @param [in] seq The Sequence to destroy. */ void SeqDestroy(Seq *seq); /** @brief Destroy an existing Sequence without destroying its items. @param [in] seq The Sequence to destroy. */ void SeqSoftDestroy(Seq *seq); /** @brief Function to compare two items in a Sequence. @retval -1 if the first argument is smaller than the second @retval 0 if the arguments are equal @retval 1 if the first argument is bigger than the second */ typedef int (*SeqItemComparator) (const void *, const void *, void *user_data); void SeqSet(Seq *set, size_t index, void *item); /** @brief Append a new item to the Sequence @param seq [in] The Sequence to append to. @param item [in] The item to append. Note that this item may be passed to the item destructor specified in the constructor. */ void SeqAppend(Seq *seq, void *item); /** * @brief Append a sequence to this sequence. Only copies pointers. * @param seq Sequence to append to * @param items Sequence to copy pointers from. */ void SeqAppendSeq(Seq *seq, const Seq *items); /** @brief Linearly searches through the sequence and return the first item considered equal to the specified key. @param seq [in] The Sequence to search. @param key [in] The item to compare against. @param compare [in] Comparator function to use. An item matches if the function returns 0. @returns A pointer to the found item, or NULL if not found. */ void *SeqLookup(Seq *seq, const void *key, SeqItemComparator Compare); /** * @brief Performs a binary search looking for the item matching the given key. * It is the programmer's responsibility to make sure that the sequence is already sorted. * @param seq [in] The Sequence to search. * @param key [in] The item to compare against. * @param compare [in] Comparator function to use (return value has strcmp semantics). * @returns A pointer to the found item, or NULL if not found. */ void *SeqBinaryLookup(Seq *seq, const void *key, SeqItemComparator Compare); /** @brief Linearly searches through the sequence and returns the index of the first matching object, or -1 if it doesn't exist. */ ssize_t SeqIndexOf(Seq *seq, const void *key, SeqItemComparator Compare); /** * @brief Performs a binary search looking for the item matching the given key. * It is the programmer's responsibility to make sure that the sequence is already sorted. * @param seq [in] The Sequence to search. * @param key [in] The item to compare against. * @param compare [in] Comparator function to use (return value has strcmp semantics). * @returns The index of the item, or -1 if it is not found. */ ssize_t SeqBinaryIndexOf(Seq *seq, const void *key, SeqItemComparator Compare); /** @brief Remove an inclusive range of items in the Sequence. A single item may be removed by specifiying start = end. @param seq [in] The Sequence to remove from. @param start [in] Index of the first element to remove @param end [in] Index of the last element to remove. */ void SeqRemoveRange(Seq *seq, size_t start, size_t end); /** @brief Remove a single item in the sequence */ void SeqRemove(Seq *seq, size_t index); /** @brief Sort a Sequence according to the given item comparator function @param compare [in] The comparator function used for sorting. @param user_data [in] Pointer passed to the comparator function */ void SeqSort(Seq *seq, SeqItemComparator compare, void *user_data); /** @brief Returns a soft copy of the sequence sorted according to the given item comparator function. @param compare [in] The comparator function used for sorting. @param user_data [in] Pointer passed to the comparator function */ Seq *SeqSoftSort(const Seq *seq, SeqItemComparator compare, void *user_data); /** @brief Remove an inclusive range of item handles in the Sequence. A single item may be removed by specifiying start = end. @param seq [in] The Sequence to remove from. @param start [in] Index of the first element to remove @param end [in] Index of the last element to remove. */ void SeqSoftRemoveRange(Seq *seq, size_t start, size_t end); /** @brief Remove a single item handle from the sequence */ void SeqSoftRemove(Seq *seq, size_t index); /** @brief Reverses the order of the sequence */ void SeqReverse(Seq *seq); /** * @brief Shuffle the sequence by randomly switching positions of the pointers * @param seq * @param seed Seed value for the PRNG */ void SeqShuffle(Seq *seq, unsigned int seed); /** * @brief Remove all elements in sequence * @param seq */ void SeqClear(Seq *seq); /** @brief Get soft copy of sequence according to specified range @param [in] seq Sequence select from @param [in] start Start index of sub sequence. @param [in] end End index which will be included into. @return A pointer to sub sequence, NULL on error. */ Seq *SeqGetRange(const Seq *seq, size_t start, size_t end); #endif cfengine-3.6.2/libutils/config.post.h.in0000664000175100017510000000030112411001073017633 0ustar00a10038a1003800000000000000/* * Macros which cannot be declared before inclusion of system headers from config.h * (say, #define mkdir rpl_mkdir) due to conflicts arising from it, are declared here. */ @post_macros@ cfengine-3.6.2/libutils/cfversion.h0000664000175100017510000000567512243421446017033 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFVERSION_H #define CFVERSION_H #include /** @brief Version is a data structure to handle versions of software. */ typedef struct Version Version; /** @brief Creates a new empty version. Use set version to initialize it. @return An empty Version structure or NULL in case of error. */ Version *VersionNew(); /** @brief Creates a new version based on the given char pointer. @param version Char pointer containing the version string. @param size Length of the version string. @return A fully initialized Version structure or NULL in case of error. */ Version *VersionNewFromCharP(const char *version, unsigned int size); /** @brief Creates a new version based on the Buffer structure. @param buffer Buffer containing the version string. @return A fully initialized Version structure or NULL in case of error. */ Version *VersionNewFrom(Buffer *buffer); /** @brief Destroys a Version structure. @param version Version structure. */ void VersionDestroy(Version **version); /** @brief Compares two versions. @param a version a @param b version b @return <0 if a < b, 0 if a == b, >0 if a > b @remarks The extra field is never included in the comparison. */ int VersionCompare(Version *a, Version *b); /** @param version Version to operate on. @return Returns the major version or -1 in case of error. */ int VersionMajor(Version *version); /** @param version Version to operate on. @return Returns the minor version or -1 in case of error. */ int VersionMinor(Version *version); /** @param version Version to operate on. @return Returns the patch version or -1 in case of error. */ int VersionPatch(Version *version); /** @param version Version to operate on. @return Returns the extra version or -1 in case of error. */ int VersionExtra(Version *version); /** @param version Version to operate on. @return Returns the build version or -1 in case of error. */ int VersionBuild(Version *version); #endif // CFVERSION_H cfengine-3.6.2/libutils/ring_buffer.c0000664000175100017510000000507612411001073017276 0ustar00a10038a1003800000000000000#include #include #include struct RingBuffer_ { void *(*copy)(const void *data); void (*destroy)(void *data); void **data; size_t capacity; size_t end; size_t len; }; struct RingBufferIterator_ { const RingBuffer *buf; size_t num_read; }; RingBuffer *RingBufferNew(size_t capacity, void *(*copy)(const void *), void (*destroy)(void *)) { assert(capacity > 0); RingBuffer *buf = xmalloc(sizeof(RingBuffer)); buf->copy = copy; buf->destroy = destroy; buf->data = xcalloc(capacity, sizeof(void *)); buf->capacity = MAX(capacity, 1); buf->len = 0; buf->end = 0; return buf; } void RingBufferAppend(RingBuffer *buf, void *item) { if (buf->data[buf->end] && buf->destroy) { buf->destroy(buf->data[buf->end]); } buf->data[buf->end] = buf->copy ? buf->copy(item) : item; buf->end = (buf->end + 1) % buf->capacity; if (buf->len < buf->capacity) { buf->len++; } } void RingBufferClear(RingBuffer *buf) { if (buf->destroy) { for (size_t i = 0; i < buf->capacity; i++) { if (buf->data[i]) { buf->destroy(buf->data[i]); buf->data[i] = NULL; } } } buf->end = 0; buf->len = 0; } size_t RingBufferLength(const RingBuffer *buf) { return buf->len; } bool RingBufferIsFull(const RingBuffer *buf) { return buf->len == buf->capacity; } const void *RingBufferHead(const RingBuffer *buf) { if (RingBufferLength(buf) == 0) { return NULL; } if (buf->end == 0) { return buf->data[buf->capacity - 1]; } else { return buf->data[buf->end - 1]; } } RingBufferIterator *RingBufferIteratorNew(const RingBuffer *buf) { RingBufferIterator *iter = xmalloc(sizeof(RingBufferIterator)); iter->buf = buf; iter->num_read = 0; return iter; } void RingBufferDestroy(RingBuffer *buf) { if (buf) { RingBufferClear(buf); free(buf->data); free(buf); } } void RingBufferIteratorDestroy(RingBufferIterator *iter) { if (iter) { free(iter); } } const void *RingBufferIteratorNext(RingBufferIterator *iter) { if ((iter->buf->len - iter->num_read) == 0) { return NULL; } size_t offset = iter->num_read; if (RingBufferIsFull(iter->buf)) { offset = (iter->buf->end + iter->num_read) % iter->buf->capacity; } const void *data = iter->buf->data[offset]; iter->num_read++; return data; } cfengine-3.6.2/libutils/csv_parser.h0000644000175100017510000000224512316547775017207 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CSV_PARSER_H #define CFENGINE_CSV_PARSER_H #define CSV_MAX_LLENGTH (4096) #include Seq *SeqParseCsvString(const char *string); char *GetCsvLineNext(FILE *fp); #endif cfengine-3.6.2/libutils/unicode.h0000644000175100017510000000404312352022221016432 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef UNICODE_H #define UNICODE_H #include #include /** * Dumb conversion from 8-bit strings to 16-bit. * * Does not take locales or any special characters into account. * @param dst The destination string. * @param src The source string. * @param size The size of dst, in wchars. */ void ConvertFromCharToWChar(int16_t *dst, const char *src, size_t size); /** * Dumb conversion from 16-bit strings to 8-bit. * * Does not take locales or any special characters into account. Since * it's possible to lose information this way, this function returns a * value indicating whether the conversion was "clean" or whether information * was lost. * @param dst The destination string. * @param src The source string. * @param size The size of dst, in bytes. * @return Returns true if conversion was successful. Returns false if the * 16-bit string could not be converted cleanly to 8-bit. Note that dst * will always contain a valid string. */ bool ConvertFromWCharToChar(char *dst, const int16_t *src, size_t size); #endif // !UNICODE_H cfengine-3.6.2/libutils/logging.c0000664000175100017510000001665512411001073016441 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include char VPREFIX[1024] = ""; /* GLOBAL_C */ bool LEGACY_OUTPUT = false; /* GLOBAL_A */ typedef struct { LogLevel log_level; LogLevel report_level; bool color; LoggingPrivContext *pctx; } LoggingContext; static LogLevel global_level = LOG_LEVEL_NOTICE; /* GLOBAL_X */ static pthread_once_t log_context_init_once = PTHREAD_ONCE_INIT; /* GLOBAL_T */ static pthread_key_t log_context_key; /* GLOBAL_T, initialized by pthread_key_create */ static void LoggingInitializeOnce(void) { if (pthread_key_create(&log_context_key, &free) != 0) { /* There is no way to signal error out of pthread_once callback. * However if pthread_key_create fails we are pretty much guaranteed * that nothing else will work. */ fprintf(stderr, "Unable to initialize logging subsystem\n"); exit(255); } } static LoggingContext *GetCurrentThreadContext(void) { pthread_once(&log_context_init_once, &LoggingInitializeOnce); LoggingContext *lctx = pthread_getspecific(log_context_key); if (lctx == NULL) { lctx = xcalloc(1, sizeof(LoggingContext)); lctx->log_level = global_level; lctx->report_level = global_level; pthread_setspecific(log_context_key, lctx); } return lctx; } void LoggingPrivSetContext(LoggingPrivContext *pctx) { LoggingContext *lctx = GetCurrentThreadContext(); lctx->pctx = pctx; } LoggingPrivContext *LoggingPrivGetContext(void) { LoggingContext *lctx = GetCurrentThreadContext(); return lctx->pctx; } void LoggingPrivSetLevels(LogLevel log_level, LogLevel report_level) { LoggingContext *lctx = GetCurrentThreadContext(); lctx->log_level = log_level; lctx->report_level = report_level; } const char *LogLevelToString(LogLevel level) { switch (level) { case LOG_LEVEL_CRIT: return "critical"; case LOG_LEVEL_ERR: return "error"; case LOG_LEVEL_WARNING: return "warning"; case LOG_LEVEL_NOTICE: return "notice"; case LOG_LEVEL_INFO: return "info"; case LOG_LEVEL_VERBOSE: return "verbose"; case LOG_LEVEL_DEBUG: return "debug"; default: ProgrammingError("LogLevelToString: Unexpected log level %d", level); } } static const char *LogLevelToColor(LogLevel level) { switch (level) { case LOG_LEVEL_CRIT: case LOG_LEVEL_ERR: return "\x1b[31m"; // red case LOG_LEVEL_WARNING: return "\x1b[33m"; // yellow case LOG_LEVEL_NOTICE: case LOG_LEVEL_INFO: return "\x1b[32m"; // green case LOG_LEVEL_VERBOSE: case LOG_LEVEL_DEBUG: return "\x1b[34m"; // blue default: ProgrammingError("LogLevelToColor: Unexpected log level %d", level); } } bool LoggingFormatTimestamp(char dest[64], size_t n, struct tm *timestamp) { if (strftime(dest, n, "%Y-%m-%dT%H:%M:%S%z", timestamp) == 0) { strlcpy(dest, "", n); return false; } return true; } static void LogToConsole(const char *msg, LogLevel level, bool color) { FILE *output_file = (level <= LOG_LEVEL_WARNING) ? stderr : stdout; if (LEGACY_OUTPUT) { if (level >= LOG_LEVEL_VERBOSE) { fprintf(stdout, "%s> %s\n", VPREFIX, msg); } else { fprintf(stdout, "%s\n", msg); } } else { struct tm now; time_t now_seconds = time(NULL); localtime_r(&now_seconds, &now); char formatted_timestamp[64]; LoggingFormatTimestamp(formatted_timestamp, 64, &now); const char *string_level = LogLevelToString(level); if (color) { fprintf(output_file, "%s%s %8s: %s\x1b[0m\n", LogLevelToColor(level), formatted_timestamp, string_level, msg); } else { fprintf(output_file, "%s %8s: %s\n", formatted_timestamp, string_level, msg); } } } #if !defined(__MINGW32__) static int LogLevelToSyslogPriority(LogLevel level) { switch (level) { case LOG_LEVEL_CRIT: return LOG_CRIT; case LOG_LEVEL_ERR: return LOG_ERR; case LOG_LEVEL_WARNING: return LOG_WARNING; case LOG_LEVEL_NOTICE: return LOG_NOTICE; case LOG_LEVEL_INFO: return LOG_INFO; case LOG_LEVEL_VERBOSE: return LOG_DEBUG; /* FIXME: Do we really want to conflate those levels? */ case LOG_LEVEL_DEBUG: return LOG_DEBUG; default: ProgrammingError("LogLevelToSyslogPriority: Unexpected log level %d", level); } } void LogToSystemLog(const char *msg, LogLevel level) { syslog(LogLevelToSyslogPriority(level), "%s", msg); } const char *GetErrorStrFromCode(int error_code) { return strerror(error_code); } const char *GetErrorStr(void) { return strerror(errno); } #endif void VLog(LogLevel level, const char *fmt, va_list ap) { LoggingContext *lctx = GetCurrentThreadContext(); char *msg = StringVFormat(fmt, ap); char *hooked_msg = NULL; if (lctx->pctx && lctx->pctx->log_hook) { hooked_msg = lctx->pctx->log_hook(lctx->pctx, level, msg); } else { hooked_msg = xstrdup(msg); } if (level <= lctx->report_level) { LogToConsole(hooked_msg, level, lctx->color); } if (level <= lctx->log_level) { LogToSystemLog(hooked_msg, level); } free(msg); free(hooked_msg); } /** * @brief Logs binary data in #buf, with each byte translated to '.' if not * printable. Message is prefixed with #prefix. */ void LogRaw(LogLevel level, const char *prefix, const void *buf, size_t buflen) { /* Translate non printable characters to printable ones. */ const unsigned char *src = (const unsigned char *) buf; unsigned char dst[buflen+1]; size_t i; for (i = 0; i < buflen; i++) { dst[i] = isprint(src[i]) ? src[i] : '.'; } dst[i] = '\0'; /* And Log the translated buffer, which is now a valid string. */ Log(level, "%s%s", prefix, dst); } void Log(LogLevel level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); VLog(level, fmt, ap); va_end(ap); } void LogSetGlobalLevel(LogLevel level) { global_level = level; LoggingPrivSetLevels(level, level); } LogLevel LogGetGlobalLevel(void) { return global_level; } void LoggingSetColor(bool enabled) { LoggingContext *lctx = GetCurrentThreadContext(); lctx->color = enabled; } cfengine-3.6.2/libutils/list.c0000644000175100017510000005103312316547775016005 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include struct ListNode { void *payload; struct ListNode *next; struct ListNode *previous; }; typedef struct ListNode ListNode; struct ListMutableIterator { int valid; ListNode *current; List *origin; }; struct List { // Number of nodes int node_count; // Incremental number that keeps track of the state of the list, only used for light iterators unsigned int state; // Nodes ListNode *list; // Link to the first element ListNode *first; // Link to the last element ListNode *last; // This function is used to compare two elements int (*compare)(const void *a, const void *b); // This function is used whenever there is need to perform a deep copy void (*copy)(const void *source, void **destination); // This function can be used to destroy the elements at destruction time void (*destroy)(void *element); // Reference counting RefCount *ref_count; // Mutable iterator. ListMutableIterator *iterator; }; struct ListIterator { ListNode *current; List *origin; unsigned int state; }; #define IsIteratorValid(iterator) \ iterator->state != iterator->origin->state #define IsMutableIteratorValid(iterator) \ iterator->valid == 0 #define ChangeListState(list) \ list->state++ /* * Helper method to detach lists. */ static void ListDetach(List *list) { int shared = RefCountIsShared(list->ref_count); if (shared) { /* * 1. Perform a deep copy (expensive!) * 2. Detach */ ListNode *p = NULL, *q = NULL, *newList = NULL, *first = NULL, *last = NULL; for (p = list->list; p; p = p->next) { if (newList) { q->next = (ListNode *)xmalloc(sizeof(ListNode)); q->next->previous = q; q->next->next = NULL; q = q->next; last = q; if (p->payload) { if (list->copy) { list->copy(p->payload, &q->payload); } else { q->payload = p->payload; } } } else { // First element newList = (ListNode *)xmalloc(sizeof(ListNode)); newList->next = NULL; newList->previous = NULL; first = newList; last = newList; if (p->payload) { if (list->copy) { list->copy(p->payload, &newList->payload); } else { newList->payload = p->payload; } } q = newList; } } list->list = newList; list->first = first; list->last = last; // Ok, we have our own copy of the list. Now we detach. RefCountDetach(list->ref_count, list); list->ref_count = NULL; RefCountNew(&list->ref_count); RefCountAttach(list->ref_count, list); } } List *ListNew(int (*compare)(const void *, const void *), void (*copy)(const void *, void **), void (*destroy)(void *)) { List *list = NULL; list = (List *)xmalloc(sizeof(List)); list->list = NULL; list->first = NULL; list->last = NULL; list->node_count = 0; list->iterator = NULL; list->state = 0; list->compare = compare; list->destroy = destroy; list->copy = copy; RefCountNew(&list->ref_count); RefCountAttach(list->ref_count, list); return list; } int ListDestroy(List **list) { if (!list || !(*list)) { return 0; } int shared = RefCountIsShared((*list)->ref_count); if (shared) { /* * We just detach from the list. */ RefCountDetach((*list)->ref_count, (*list)); } else { // We are the only ones using the list, we can delete it. ListNode *node = NULL; ListNode *p = NULL; for (node = (*list)->first; node; node = p) { if ((*list)->destroy) (*list)->destroy(node->payload); p = node->next; free(node); } RefCountDestroy(&(*list)->ref_count); } free((*list)); *list = NULL; return 0; } int ListCopy(List *origin, List **destination) { if (!origin || !destination) return -1; /* * The first thing we check is the presence of a copy function. * Without that function we need to abort the operation. */ if (!origin->copy) { return -1; } *destination = (List *)xmalloc(sizeof(List)); (*destination)->list = origin->list; (*destination)->first = origin->first; (*destination)->last = origin->last; (*destination)->node_count = origin->node_count; (*destination)->state = origin->state; (*destination)->destroy = origin->destroy; (*destination)->copy = origin->copy; (*destination)->compare = origin->compare; /* * We do not copy iterators. */ (*destination)->iterator = NULL; /* We have a copy function, we can perform a shallow copy. */ RefCountAttach(origin->ref_count, (*destination)); (*destination)->ref_count = origin->ref_count; return 0; } int ListPrepend(List *list, void *payload) { ListNode *node = NULL; if (!list) { return -1; } ListDetach(list); node = (ListNode *)xmalloc(sizeof(ListNode)); node->payload = payload; node->previous = NULL; if (list->list) { // We have elements node->next = list->list; list->list->previous = node; } else { // First element node->next = NULL; list->last = node; } list->list = node; list->first = node; list->node_count++; return 0; } int ListAppend(List *list, void *payload) { ListNode *node = NULL; if (!list) { return -1; } ListDetach(list); node = (ListNode *)xmalloc(sizeof(ListNode)); node->next = NULL; node->payload = payload; if (list->last) { // We have elements node->previous = list->last; list->last->next = node; } else { // First element node->previous = NULL; list->list = node; list->first = node; } list->last = node; list->node_count++; return 0; } /* * We split the code into several helper functions. * These functions are not exported to the outside world * since it does not make sense for them to be used in other * places. */ static int ListFindNode(List *list, void *payload) { if (!list) { return -1; } ListNode *node = NULL; int found = 0; for (node = list->list; node; node = node->next) { if (!node->payload) continue; if (list->compare) { if (!list->compare(node->payload, payload)) { found = 1; break; } } else { if (node->payload == payload) { found = 1; break; } } } return found; } static void ListUpdateListState(List *list) { list->node_count--; ChangeListState(list); } int ListRemove(List *list, void *payload) { if (!list || !payload) return -1; ListNode *node = NULL; /* * This is a complicated matter. We could detach the list before * we know that we have a new node, but that will mean that we * might have copied the whole list without real reasons. On the * other hand, it saves us a whole traversal of the list if we * just do it. */ int found = ListFindNode(list, payload); if (!found) return -1; found = 0; ListDetach(list); node = NULL; /* * We need to find the node again since we have a new list. * In theory we don't have to worry about the existence of the node, * since the list has not changed, it might have been copied but * it is still the same as before. */ for (node = list->list; node; node = node->next) { if (list->compare) { if (!list->compare(node->payload, payload)) { found = 1; break; } } else { if (node->payload == payload) { found = 1; break; } } } /* * This is nearly impossible, so we will only assert it. */ assert(node); assert(found == 1); /* * Before deleting the node we have to update the mutable iterator. * We might need to advance it! */ if (list->iterator) { if (list->iterator->current == node) { /* * So lucky, it is the same node! * Move the iterator so it is not dangling. * Rules for moving: * 1. Move forward. * 2. if not possible, move backward. * 3. If not possible, then invalidate the iterator. */ if (list->iterator->current->next) { list->iterator->current = list->iterator->current->next; } else if (list->iterator->current->previous) { list->iterator->current = list->iterator->current->previous; } else { list->iterator->valid = 0; } } } /* * Now, remove the node from the list and delete it. */ if (node->next && node->previous) { // Middle of the list node->next->previous = node->previous; node->previous->next = node->next; } else if (node->next) { // First element of the list list->list = node->next; list->first = node->next; node->next->previous = NULL; } else if (node->previous) { // Last element node->previous->next = NULL; list->last = node->previous; } else { // Single element list->list = NULL; list->first = NULL; list->last = NULL; } if (list->destroy && node->payload) { list->destroy(node->payload); } else { free (node->payload); } free(node); ListUpdateListState(list); return 0; } // Number of elements on the list int ListCount(const List *list) { return list ? list->node_count : -1; } /* * Functions for iterators */ ListIterator *ListIteratorGet(const List *list) { if (!list) { return NULL; } // You cannot get an iterator for an empty list. if (!list->first) { return NULL; } ListIterator *iterator = NULL; iterator = (ListIterator *)xmalloc(sizeof(ListIterator)); iterator->current = list->list; // Remaining only works in one direction, we need two variables for this. iterator->origin = (List *)list; iterator->state = list->state; return iterator; } int ListIteratorDestroy(ListIterator **iterator) { if (!iterator || !(*iterator)) { return 0; } (*iterator)->current = NULL; free((*iterator)); *iterator = NULL; return 0; } int ListIteratorFirst(ListIterator *iterator) { if (!iterator) { return -1; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return -1; } iterator->current = iterator->origin->first; return 0; } int ListIteratorLast(ListIterator *iterator) { if (!iterator) { return -1; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return -1; } iterator->current = iterator->origin->last; return 0; } int ListIteratorNext(ListIterator *iterator) { if (!iterator) { return -1; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return -1; } // Ok, check if we are at the end if (iterator->current && iterator->current->next) { iterator->current = iterator->current->next; } else { return -1; } return 0; } int ListIteratorPrevious(ListIterator *iterator) { if (!iterator) { return -1; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return -1; } // Ok, check if we are at the end if (iterator->current && iterator->current->previous) { iterator->current = iterator->current->previous; } else { return -1; } return 0; } void *ListIteratorData(const ListIterator *iterator) { if (!iterator) { return NULL; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return NULL; } return iterator->current->payload; } bool ListIteratorHasNext(const ListIterator *iterator) { if (!iterator) { return false; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return false; } if (iterator->current->next) { return true; } return false; } bool ListIteratorHasPrevious(const ListIterator *iterator) { if (!iterator) { return false; } if (IsIteratorValid(iterator)) { // The list has moved forward, the iterator is invalid now return false; } if (iterator->current->previous) { return true; } return false; } /* * Mutable iterator operations */ ListMutableIterator *ListMutableIteratorGet(List *list) { if (!list) { return NULL; } if (list->iterator) { // Only one iterator at a time return NULL; } // You cannot get an iterator for an empty list. if (!list->first) { return NULL; } ListMutableIterator *iterator = NULL; iterator = (ListMutableIterator *)xmalloc(sizeof(ListMutableIterator)); iterator->current = list->first; iterator->origin = list; iterator->valid = 1; list->iterator = iterator; return iterator; } int ListMutableIteratorRelease(ListMutableIterator **iterator) { if (iterator && *iterator) { (*iterator)->origin->iterator = NULL; free (*iterator); *iterator = NULL; } return 0; } int ListMutableIteratorFirst(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; iterator->current = iterator->origin->first; return 0; } int ListMutableIteratorLast(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; iterator->current = iterator->origin->last; return 0; } int ListMutableIteratorNext(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; if (!iterator->current->next) return -1; iterator->current = iterator->current->next; return 0; } int ListMutableIteratorPrevious(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; if (!iterator->current->previous) return -1; iterator->current = iterator->current->previous; return 0; } void *ListMutableIteratorData(const ListMutableIterator *iterator) { if (!iterator) return NULL; if (IsMutableIteratorValid(iterator)) return NULL; return (void *)iterator->current->payload; } int ListMutableIteratorRemove(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListDetach(iterator->origin); /* * Removing an element is not as simple as it sounds. We need to inform the list * and make sure we move out of the way. */ ListNode *node = NULL; if (iterator->current->next) { /* * We are not the last element, therefore we proceed as normal. */ node = iterator->current->next; } else { /* * We might be the last element or the only element on the list. * If we are the only element we do not destroy the element otherwise the iterator * would become invalid. */ if (iterator->current->previous) { /* * last element */ node = iterator->current->previous; } else return -1; } /* * Now, remove the node from the list and delete it. */ if (iterator->current->next && iterator->current->previous) { // Middle of the list iterator->current->next->previous = iterator->current->previous; iterator->current->previous->next = iterator->current->next; } else if (iterator->current->next) { // First element of the list iterator->origin->list = iterator->current->next; iterator->origin->first = iterator->current->next; iterator->current->next->previous = NULL; } else if (iterator->current->previous) { // Last element iterator->current->previous->next = NULL; iterator->origin->last = iterator->current->previous; } if (iterator->origin->destroy && iterator->current->payload) { iterator->origin->destroy(iterator->current->payload); } else { free (iterator->current->payload); } free(iterator->current); iterator->current = node; ListUpdateListState(iterator->origin); return 0; } int ListMutableIteratorPrepend(ListMutableIterator *iterator, void *payload) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListNode *node = NULL; node = (ListNode *)xmalloc(sizeof(ListNode)); ListDetach(iterator->origin); node->payload = payload; if (iterator->current->previous) { node->previous = iterator->current->previous; node->next = iterator->current; iterator->current->previous->next = node; iterator->current->previous = node; } else { // First element node->previous = NULL; node->next = iterator->current; iterator->current->previous = node; iterator->origin->first = node; iterator->origin->list = node; } iterator->origin->node_count++; return 0; } int ListMutableIteratorAppend(ListMutableIterator *iterator, void *payload) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListNode *node = NULL; node = (ListNode *)xmalloc(sizeof(ListNode)); ListDetach(iterator->origin); node->next = NULL; node->payload = payload; if (iterator->current->next) { node->next = iterator->current->next; node->previous = iterator->current; iterator->current->next->previous = node; iterator->current->next = node; } else { // Last element node->next = NULL; node->previous = iterator->current; iterator->current->next = node; iterator->origin->last = node; } iterator->origin->node_count++; return 0; } bool ListMutableIteratorHasNext(const ListMutableIterator *iterator) { return iterator && iterator->current->next; } bool ListMutableIteratorHasPrevious(const ListMutableIterator *iterator) { return iterator && iterator->current->previous; } cfengine-3.6.2/libutils/dir.h0000644000175100017510000000222312352557236015603 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_DIR_H #define CFENGINE_DIR_H typedef struct Dir_ Dir; Dir *DirOpen(const char *dirname); const struct dirent *DirRead(Dir *dir); void DirClose(Dir *dir); #endif cfengine-3.6.2/libutils/json.h0000644000175100017510000003223112352022221015755 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_JSON_H #define CFENGINE_JSON_H /** @brief JSON data-structure. This is a JSON Document Object Model (DOM). Clients deal only with the opaque JsonElement, which may be either a container or a primitive (client should probably not deal much with primitive elements). A JSON container may be either an object or an array. The JSON DOM currently supports copy semantics for primitive values, but not for container types. In practice, this means that clients always just free the parent element, but an element should just have a single parent, or none. JSON primitives as JsonElement are currently not well supported. JSON DOM is currently built upon Sequence. The JSON specification may be found at @link http://www.json.org @endlink. @see Sequence */ typedef enum { JSON_ELEMENT_TYPE_CONTAINER, JSON_ELEMENT_TYPE_PRIMITIVE } JsonElementType; typedef enum { JSON_CONTAINER_TYPE_OBJECT, JSON_CONTAINER_TYPE_ARRAY } JsonContainerType; typedef enum { JSON_PRIMITIVE_TYPE_STRING, JSON_PRIMITIVE_TYPE_INTEGER, JSON_PRIMITIVE_TYPE_REAL, JSON_PRIMITIVE_TYPE_BOOL, JSON_PRIMITIVE_TYPE_NULL } JsonPrimitiveType; typedef enum { JSON_PARSE_OK = 0, JSON_PARSE_ERROR_STRING_NO_DOUBLEQUOTE_START, JSON_PARSE_ERROR_STRING_NO_DOUBLEQUOTE_END, JSON_PARSE_ERROR_STRING_UNSUPPORTED_ESCAPE, JSON_PARSE_ERROR_NUMBER_EXPONENT_NEGATIVE, JSON_PARSE_ERROR_NUMBER_EXPONENT_POSITIVE, JSON_PARSE_ERROR_NUMBER_DUPLICATE_ZERO, JSON_PARSE_ERROR_NUMBER_NO_DIGIT, JSON_PARSE_ERROR_NUMBER_EXPONENT_DUPLICATE, JSON_PARSE_ERROR_NUMBER_EXPONENT_DIGIT, JSON_PARSE_ERROR_NUMBER_EXPONENT_FOLLOW_LEADING_ZERO, JSON_PARSE_ERROR_NUMBER_BAD_SYMBOL, JSON_PARSE_ERROR_NUMBER_DIGIT_END, JSON_PARSE_ERROR_ARRAY_START, JSON_PARSE_ERROR_ARRAY_END, JSON_PARSE_ERROR_OBJECT_BAD_SYMBOL, JSON_PARSE_ERROR_OBJECT_START, JSON_PARSE_ERROR_OBJECT_END, JSON_PARSE_ERROR_OBJECT_COLON, JSON_PARSE_ERROR_OBJECT_COMMA, JSON_PARSE_ERROR_OBJECT_ARRAY_LVAL, JSON_PARSE_ERROR_OBJECT_OBJECT_LVAL, JSON_PARSE_ERROR_OBJECT_OPEN_LVAL, JSON_PARSE_ERROR_INVALID_START, JSON_PARSE_ERROR_NO_DATA, JSON_PARSE_ERROR_MAX } JsonParseError; typedef struct JsonElement_ JsonElement; #include typedef struct { const JsonElement *container; size_t index; } JsonIterator; /** @brief Create a new JSON object @param initial_capacity [in] The number of fields to preallocate space for. @returns A pointer to the created object. */ JsonElement *JsonObjectCreate(size_t initial_capacity); /** @brief Create a new JSON array @param initial_capacity [in] The number of fields to preallocate space for. @returns The pointer to the created array. */ JsonElement *JsonArrayCreate(size_t initialCapacity); /** @brief Create a new JSON string primitive. @param value [in] The string to base the primitive on. Will be copied. @returns The pointer to the created string primitive element. */ JsonElement *JsonStringCreate(const char *value); JsonElement *JsonIntegerCreate(int value); JsonElement *JsonRealCreate(double value); JsonElement *JsonBoolCreate(bool value); JsonElement *JsonNullCreate(); JsonElement *JsonCopy(const JsonElement *json); int JsonCompare(const JsonElement *a, const JsonElement *b); JsonElement *JsonMerge(const JsonElement *a, const JsonElement *b); /** @brief Destroy a JSON element @param element [in] The JSON element to destroy. */ void JsonDestroy(JsonElement *element); /** @brief Get the length of a JsonElement. This is the number of elements or fields in an array or object respectively. @param element [in] The JSON element. */ size_t JsonLength(const JsonElement *element); JsonElementType JsonGetElementType(const JsonElement *element); JsonContainerType JsonGetContainerType(const JsonElement *container); JsonPrimitiveType JsonGetPrimitiveType(const JsonElement *primitive); const char *JsonPrimitiveGetAsString(const JsonElement *primitive); bool JsonPrimitiveGetAsBool(const JsonElement *primitive); long JsonPrimitiveGetAsInteger(const JsonElement *primitive); double JsonPrimitiveGetAsReal(const JsonElement *primitive); const char *JsonGetPropertyAsString(const JsonElement *element); /** @brief Pretty-print a JsonElement recursively into a Writer. @see Writer @param writer [in] The Writer object to use as a buffer. @param element [in] The JSON element to print. @param indent_level [in] The nesting level with which the printing should be done. This is mainly to allow the function to be called recursively. Clients will normally want to set this to 0. */ void JsonWrite(Writer *writer, const JsonElement *element, size_t indent_level); void JsonWriteCompact(Writer *w, const JsonElement *element); /** @brief Append a string field to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @param value [in] The value of the field. */ void JsonObjectAppendString(JsonElement *object, const char *key, const char *value); /** @brief Append an integer field to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @param value [in] The value of the field. */ void JsonObjectAppendInteger(JsonElement *object, const char *key, int value); /** @brief Append an real number field to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @param value [in] The value of the field. */ void JsonObjectAppendReal(JsonElement *object, const char *key, double value); /** @param object [in] The JSON object parent. @param key [in] the key of the field. @param value [in] The value of the field. */ void JsonObjectAppendBool(JsonElement *object, const char *key, _Bool value); /** @brief Append null field to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. */ void JsonObjectAppendNull(JsonElement *object, const char *key); /** @brief Append an array field to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @param value [in] The value of the field. */ void JsonObjectAppendArray(JsonElement *object, const char *key, JsonElement *array); /** @brief Append an object field to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @param value [in] The value of the field. */ void JsonObjectAppendObject(JsonElement *object, const char *key, JsonElement *childObject); /** @brief Append any JSON element to an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @param element [in] The element to append */ void JsonObjectAppendElement(JsonElement *object, const char *key, JsonElement *element); /** @brief Get the value of a field in an object, as a string. @param object [in] The JSON object parent. @param key [in] the key of the field. @returns A pointer to the string value, or NULL if non-existant. */ const char *JsonObjectGetAsString(const JsonElement *object, const char *key); /** @brief Get the value of a field in an object, as an object. @param object [in] The JSON object parent. @param key [in] the key of the field. @returns A pointer to the object value, or NULL if non-existant. */ JsonElement *JsonObjectGetAsObject(JsonElement *object, const char *key); /** @brief Get the value of a field in an object, as an array. @param object [in] The JSON object parent. @param key [in] the key of the field. @returns A pointer to the array value, or NULL if non-existant. */ JsonElement *JsonObjectGetAsArray(JsonElement *object, const char *key); JsonElement *JsonObjectGet(const JsonElement *object, const char *key); /** @brief Append a string to an array. @param array [in] The JSON array parent. @param value [in] The string value to append. */ void JsonArrayAppendString(JsonElement *array, const char *value); void JsonArrayAppendBool(JsonElement *array, bool value); /** @brief Append an integer to an array. @param array [in] The JSON array parent. @param value [in] The integer value to append. */ void JsonArrayAppendInteger(JsonElement *array, int value); /** @brief Append an real to an array. @param array [in] The JSON array parent. @param value [in] The real value to append. */ void JsonArrayAppendReal(JsonElement *array, double value); /** @brief Append null to an array. @param array [in] The JSON array parent. */ void JsonArrayAppendNull(JsonElement *array); /** @brief Append an array to an array. @param array [in] The JSON array parent. @param child_array [in] The array value to append. */ void JsonArrayAppendArray(JsonElement *array, JsonElement *child_array); /** @brief Append an object to an array. @param array [in] The JSON array parent. @param object [in] The object value to append. */ void JsonArrayAppendObject(JsonElement *array, JsonElement *object); /** @brief Append any JSON element to an array. @param array [in] The JSON array parent. @param element [in] The object to append. */ void JsonArrayAppendElement(JsonElement *array, JsonElement *element); /** @brief Remove an inclusive range from a JSON array. @see SequenceRemoveRange @param array [in] The JSON array parent. @param start [in] Index of the first element to remove. @param end [in] Index of the last element to remove. */ void JsonArrayRemoveRange(JsonElement *array, size_t start, size_t end); void JsonContainerReverse(JsonElement *array); /** @brief Get a string value from an array @param array [in] The JSON array parent @param index [in] Position of the value to get @returns A pointer to the string value, or NULL if non-existant. */ const char *JsonArrayGetAsString(JsonElement *array, size_t index); /** @brief Get an object value from an array @param array [in] The JSON array parent @param index [in] Position of the value to get @returns A pointer to the object value, or NULL if non-existant. */ JsonElement *JsonArrayGetAsObject(JsonElement *array, size_t index); JsonElement *JsonArrayGet(JsonElement *array, size_t index); /** @brief Parse a string to create a JsonElement @param data [in, out] Pointer to the string to parse @param json_out Resulting JSON object @returns See JsonParseError and JsonParseErrorToString */ JsonParseError JsonParse(const char **data, JsonElement **json_out); /** * @brief Convenience function to parse JSON from a file * @param path Path to the file * @param size_max Maximum size to read in memory * @param json_out Resulting JSON object * @return See JsonParseError and JsonParseErrorToString */ JsonParseError JsonParseFile(const char *path, size_t size_max, JsonElement **json_out); const char* JsonParseErrorToString(JsonParseError error); /** @brief Remove key from the object @param object containing the key property @param property name to be removed @return True if key was removed */ bool JsonObjectRemoveKey(JsonElement *object, const char *key); /** @brief Detach json element ownership from parent object; @param object containing the key property @param property name to be detached */ JsonElement *JsonObjectDetachKey(JsonElement *object, const char *key); typedef int JsonComparator(const JsonElement *, const JsonElement *, void *user_data); void JsonSort(JsonElement *container, JsonComparator *Compare, void *user_data); JsonElement *JsonAt(const JsonElement *container, size_t index); JsonElement *JsonSelect(JsonElement *element, size_t num_indices, char **indices); const char *JsonPrimitiveTypeToString(JsonPrimitiveType type); JsonIterator JsonIteratorInit(const JsonElement *container); const char *JsonIteratorNextKey(JsonIterator *iter); const JsonElement *JsonIteratorNextValue(JsonIterator *iter); const JsonElement *JsonIteratorNextValueByType(JsonIterator *iter, JsonElementType type, bool skip_null); const char *JsonIteratorCurrentKey(const JsonIterator *iter); const JsonElement *JsonIteratorCurrentValue(const JsonIterator *iter); JsonElementType JsonIteratorCurrentElementType(const JsonIterator *iter); JsonContainerType JsonIteratorCurrentContainerType(const JsonIterator *iter); JsonPrimitiveType JsonIteratorCurrentPrimitiveType(const JsonIterator *iter); bool JsonIteratorHasMore(const JsonIterator *iter); #endif cfengine-3.6.2/libutils/regex.h0000664000175100017510000000337412400110676016134 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_REGEX_H #define CFENGINE_REGEX_H #include #include #include /* Seq */ /* Try to use CompileRegex() and StringMatchWithPrecompiledRegex(). */ pcre *CompileRegex(const char *regex); bool StringMatch(const char *regex, const char *str, int *start, int *end); bool StringMatchWithPrecompiledRegex(pcre *regex, const char *str, int *start, int *end); bool StringMatchFull(const char *regex, const char *str); bool StringMatchFullWithPrecompiledRegex(pcre *regex, const char *str); Seq *StringMatchCaptures(const char *regex, const char *str); bool CompareStringOrRegex(const char *value, const char *compareTo, bool regex); #endif /* CFENGINE_REGEX_H */ cfengine-3.6.2/ltmain.sh0000644000175100017510000105204412403654556014654 0ustar00a10038a1003800000000000000 # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.7ubuntu1 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.2 Debian-2.4.2-1.7ubuntu1" TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 cfengine-3.6.2/cf-upgrade/0000775000175100017510000000000012413020723015025 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-upgrade/cf-upgrade.c0000664000175100017510000000440212400110676017211 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #define CF_UPGRADE_VERSION "1.0.0" void usage() { puts("Usage: cf-upgrade [-c copy] <-b backup tool> <-s backup path> " "[-f CFEngine Folder] <-i command + arguments>"); puts("Usage: cf-upgrade -h: help"); puts("Usage: cf-upgrade -v: version"); puts("More detailed help can be found in the accompanying README.md file."); } int main(int argc, char **argv) { int result = 0; Configuration *configuration = NULL; logInit(); log_entry(LogVerbose, "Starting %s", argv[0]); result = parse(argc, argv, &configuration); if (result < 0) { usage(); return 1; } if (ConfigurationVersion(configuration)) { char version[] = CF_UPGRADE_VERSION; printf("cf-upgrade %s\n", version); return 0; } if (ConfigurationHelp(configuration)) { usage(); return 0; } result = RunUpdate(configuration); log_entry(LogVerbose, "Finished %s", argv[0]); logFinish(); return (result == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } cfengine-3.6.2/cf-upgrade/command_line.h0000644000175100017510000000321012316547775017644 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef COMMAND_LINE_H #define COMMAND_LINE_H #include /* * Upper boundary on the number of command line options. * We have 5 modifiers with one argument each (5 * 2 = 10). Then we have * a maximum of CF_UPGRADE_MAX_ARGUMENTS for the upgrade utility itself. */ #define COMMAND_LINE_OPTIONS (10 + CF_UPGRADE_MAX_ARGUMENTS) /** @brief Parsing of the command line arguments. @param argc Number or arguments. @param argv Array containing the arguments. @param configuration Structure containing the configuration @return 0 if successful, -1 if error. */ int parse(int argc, char *argv[], Configuration **configuration); #endif // COMMAND_LINE_H cfengine-3.6.2/cf-upgrade/command_line.c0000644000175100017510000001173612316547775017653 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #define COPY_PARAM "-c" #define BACKUP_TOOL_PARAM "-b" #define BACKUP_PATH_PARAM "-s" #define CFENGINE_PATH "-f" #define UPDATE_ARGS "-i" #define UPDATE_2ND_ARGS "-x" #define HELP_REQUESTED "-h" #define VERSION_REQUESTED "-v" int parse(int argc, char *argv[], Configuration **configuration) { if (!configuration || !argv || (argc < 2)) { log_entry(LogDebug, "configuration or argv are NULL"); return -1; } /* Create the configuration structure */ *configuration = ConfigurationNew(); /* The first value is the current executable */ ConfigurationSetCFUpgrade(*configuration, argv[0]); /* Some flags to check for errors */ bool backup_tool = false; bool command_arguments = false; bool backup_path = false; int i = 1; do { char *current = argv[i]; log_entry(LogDebug, "current: %s", current); if (0 == strcmp(COPY_PARAM, current)) { char *copy = argv[i + 1]; log_entry(LogDebug, "copy: %s", copy); ConfigurationSetCopy(*configuration, copy); i += 2; } else if (0 == strcmp(HELP_REQUESTED, current)) { log_entry(LogDebug, "help requested"); ConfigurationSetHelp(*configuration, 1); return 0; } else if (0 == strcmp(VERSION_REQUESTED, current)) { log_entry(LogDebug, "version requested"); ConfigurationSetVersion(*configuration, 1); return 0; } else if (0 == strcmp(BACKUP_TOOL_PARAM, current)) { char *path = argv[i + 1]; log_entry(LogDebug, "backup tool: %s", path); ConfigurationSetBackupTool(*configuration, path); i += 2; backup_tool = 1; } else if (0 == strcmp(BACKUP_PATH_PARAM, current)) { char *path = argv[i + 1]; log_entry(LogDebug, "backup path: %s", path); ConfigurationSetBackupPath(*configuration, path); i += 2; backup_path = true; } else if (0 == strcmp(CFENGINE_PATH, current)) { char *path = argv[i + 1]; log_entry(LogDebug, "cfengine path: %s", path); ConfigurationSetCFEnginePath(*configuration, path); i += 2; } /* * Once we find the -i/-x command we stop parsing and assume that * the rest is just update command and its arguments. */ else if (0 == strcmp(UPDATE_ARGS, current)) { log_entry(LogDebug, "Copying and forking"); int j = 0; for (j = i + 1; j < argc; ++j) { command_arguments = 1; char *argument = argv[j]; log_entry(LogDebug, "argument: %s", argument); ConfigurationAddArgument(*configuration, argument); } break; } else if (0 == strcmp(UPDATE_2ND_ARGS, current)) { log_entry(LogDebug, "Performing upgrade"); int j = 0; for (j = i + 1; j < argc; ++j) { command_arguments = 1; char *argument = argv[j]; log_entry(LogDebug, "argument: %s", argument); ConfigurationAddArgument(*configuration, argument); } ConfigurationSetPerformUpdate(*configuration, true); break; } else { log_entry (LogCritical, "Unrecognized option: %s", current); ConfigurationDestroy(configuration); return -1; } } while (i < argc); if (!backup_tool || !command_arguments || !backup_path) { log_entry(LogCritical, "Need to specify -s, -b and -i"); ConfigurationDestroy(configuration); return -1; } log_entry(LogDebug, "parsed %d options", i); return 0; } cfengine-3.6.2/cf-upgrade/log.c0000664000175100017510000000766712400110676015775 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #define MAX_LOG_ENTRY_SIZE 4096 static FILE *LOG_STREAM = NULL; static LogLevel CURRENT_LEVEL = LogVerbose; static char *prepare_message(char *format, va_list args) { char *message = NULL; int message_size = 0; char timestamp[] = "YYYY/MM/DD HH:MM:SS"; char buffer[MAX_LOG_ENTRY_SIZE]; time_t now = time(NULL); struct tm *now_tm = gmtime(&now); int timestamp_size = sizeof(timestamp); message_size = vsnprintf(buffer, MAX_LOG_ENTRY_SIZE - 1, format, args); strftime(timestamp, timestamp_size, "%Y/%m/%d %H:%M:%S", now_tm); /* '[' + ']' + ' ' + '\0' */ message = xmalloc(message_size + timestamp_size + 4); sprintf(message, "[%s] %s", timestamp, buffer); return message; } static void write_console_log_entry(const char *message) { puts(message); } static void write_file_log_entry(const char *message) { if (LOG_STREAM != NULL) { fputs(message, LOG_STREAM); fputs("\n", LOG_STREAM); fflush(LOG_STREAM); } } static void private_log_init() { char path[] = "cf-upgrade-YYYYMMDD-HHMMSS.log"; time_t now_seconds = time(NULL); struct tm *now_tm = gmtime(&now_seconds); int log_fd = -1; strftime(path, sizeof(path), "cf-upgrade-%Y%m%d-%H%M%S.log", now_tm); #ifndef __MINGW32__ log_fd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); #else log_fd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); #endif if (log_fd < 0) { puts("Could not initialize log file, only console messages will be printed"); return; } #ifndef __MINGW32__ /* * cf-upgrade spawns itself, therefore to avoid log confusion we need to * make sure that the log is closed when we call exeve. */ int result = 0; result = fcntl(log_fd, F_GETFD); if (result < 0) { puts("Could not initialize log file, only console messages will be printed"); return; } result = fcntl(log_fd, F_SETFD, result | FD_CLOEXEC); if (result < 0) { puts("Could not initialize log file, only console messages will be printed"); return; } #endif LOG_STREAM = fdopen(log_fd, "a"); } void logInit() { private_log_init(); } void logFinish() { if (LOG_STREAM) { fclose(LOG_STREAM); } } void log_entry(LogLevel level, char *format, ...) { if (level > CURRENT_LEVEL) { return; } va_list ap; va_start(ap, format); char *message = prepare_message(format, ap); va_end(ap); switch (level) { case LogCritical: case LogNormal: case LogVerbose: write_console_log_entry(message); write_file_log_entry(message); break; case LogDebug: write_file_log_entry(message); break; } free(message); } cfengine-3.6.2/cf-upgrade/log.h0000664000175100017510000000265312400110676015770 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef LOG_H #define LOG_H #include typedef enum { LogCritical, LogNormal, LogVerbose, LogDebug } LogLevel; /** @brief Initializes log system. @param path Log file */ void logInit(); /** @brief Finishes the log system. */ void logFinish(); /** @brief Write a log entry. @param level Log level. @param format Format of the entry @param ... */ void log_entry(LogLevel level, char *format, ...); #endif // LOG_H cfengine-3.6.2/cf-upgrade/update.c0000664000175100017510000002547612411001073016464 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include extern char **environ; #ifndef __MINGW32__ /* Unix implementation */ int private_copy_to_temporary_location(const char *source, const char *destination) { struct stat source_stat; int source_fd = -1; int destination_fd = -1; source_fd = open(source, O_RDONLY); if (source_fd < 0) { goto bad_nofd; } fstat(source_fd, &source_stat); unlink (destination); destination_fd = open(destination, O_WRONLY|O_CREAT|O_EXCL, S_IRWXU|S_IRGRP|S_IROTH); if (destination_fd < 0) { goto bad_onefd; } char buffer[1024]; int so_far = 0; do { int this_read = 0; int this_write = 0; this_read = read(source_fd, buffer, sizeof(buffer)); if (this_read < 0) { log_entry(LogCritical, "Failed to read from %s (read so far: %d)", source, so_far); goto bad_twofd; } this_write = write(destination_fd, buffer, this_read); if (this_write < 0) { log_entry(LogCritical, "Failed to write to %s (written so far: %d)", destination, so_far); goto bad_twofd; } if (this_write != this_read) { log_entry(LogCritical, "Short write: read: %d, written: %d (prior progress: %d)", this_read, this_write, so_far); goto bad_twofd; } so_far += this_read; } while (so_far < source_stat.st_size); fsync(destination_fd); close(source_fd); close(destination_fd); return 0; bad_twofd: close(destination_fd); unlink(destination); bad_onefd: close(source_fd); bad_nofd: return -1; } #else /* Windows implementation */ int private_copy_to_temporary_location(const char *source, const char *destination) { struct stat source_stat; int result = 0; int source_fd = -1; int destination_fd = -1; source_fd = open(source, O_BINARY|O_RDONLY); if (source_fd < 0) { goto bad_nofd; } result = fstat(source_fd, &source_stat); unlink (destination); destination_fd = open(destination, O_BINARY|O_WRONLY|O_CREAT|O_EXCL, S_IRWXU); if (destination_fd < 0) { goto bad_onefd; } char buffer[1024]; int so_far = 0; int this_read; do { this_read = read(source_fd, buffer, sizeof(buffer)); if (this_read < 0) { log_entry(LogCritical, "Failed to read from %s (read so far: %d)", source, so_far); goto bad_twofd; } else if (this_read > 0) /* Successful read() */ { so_far += this_read; int this_write = write(destination_fd, buffer, this_read); if (this_write < 0) { log_entry(LogCritical, "Failed to write to %s (written so far: %d)", destination, so_far); goto bad_twofd; } else if (this_write != this_read) { log_entry(LogCritical, "Short write: read: %d, written: %d (prior progress: %d)", this_read, this_write, so_far); goto bad_twofd; } } } while (this_read > 0); assert(this_read == 0); if (so_far != source_stat.st_size) { log_entry(LogCritical, "Unexpected, file is at EOF while %d out of %d bytes have been read", so_far, source_stat.st_size); log_entry(LogCritical, "Trying to continue, maybe it changed size while reading"); } close(source_fd); close(destination_fd); return 0; bad_twofd: close(destination_fd); unlink(destination); bad_onefd: close(source_fd); bad_nofd: return -1; } #endif int copy_to_temporary_location(const char *source, const char *destination) { if (!source || !destination) { return -1; } return private_copy_to_temporary_location(source, destination); } int perform_backup(const char *backup_tool, const char *backup_path, const char *cfengine) { char **args = NULL; char *envp[] = { NULL }; args = xcalloc(4 + 1, sizeof(char *)); args[0] = xstrdup(backup_tool); args[1] = xstrdup("BACKUP"); args[2] = xstrdup(backup_path); args[3] = xstrdup(cfengine); args[4] = NULL; int result = 0; result = run_process_wait(backup_tool, args, envp); free (args[0]); free (args[1]); free (args[2]); free (args[3]); free (args); return result; } int perform_restore(const char *backup_tool, const char *backup_path, const char *cfengine) { char **args = NULL; char *envp[] = { NULL }; args = xcalloc(4 + 1, sizeof(char *)); args[0] = xstrdup(backup_tool); args[1] = xstrdup("RESTORE"); args[2] = xstrdup(backup_path); args[3] = xstrdup(cfengine); args[4] = NULL; int result = 0; result = run_process_wait(backup_tool, args, envp); free (args[0]); free (args[1]); free (args[2]); free (args[3]); free (args); return result; } /* * The update loop goes like this: * 1. Copy this program to a temporary location (by default /tmp/cf-upgrade). * 2. Execute this program requesting to perform the upgrade. * The following steps happen on the new copy: * 3. Run the backup script. * 4. Run the upgrade command. * 4a If success, finish. * 4b If failure, run the restore command from the backup script. */ int RunUpdate(const Configuration *configuration) { if (!configuration) { return -1; } int result = 0; bool upgrade = ConfigurationPerformUpdate(configuration); if (upgrade) { /* Perform the upgrade */ /* first perform the backup */ const char *backup_path = ConfigurationBackupPath(configuration); const char *backup_tool = ConfigurationBackupTool(configuration); const char *cfengine = ConfigurationCFEnginePath(configuration); log_entry(LogVerbose, "Performing backup of '%s' to '%s' using '%s'", cfengine, backup_path, backup_tool); result = perform_backup(backup_tool, backup_path, cfengine); if (result != 0) { log_entry(LogCritical, "Failed to backup %s to %s using %s", cfengine, backup_path, backup_tool); return -1; } log_entry(LogVerbose, "Backup successful"); /* run the upgrade process */ const char *command = ConfigurationCommand(configuration); char *args[CF_UPGRADE_MAX_ARGUMENTS + 1]; int i = 0; int total = ConfigurationNumberOfArguments(configuration); for (i = 0; i < total; ++i) { args[i] = xstrdup(ConfigurationArgument(configuration, i)); } args[total] = NULL; log_entry(LogVerbose, "Running upgrade command: %s", command); result = run_process_wait(command, args, environ); /* Check that everything went according to plan */ if (result == 0) { log_entry(LogNormal, "Upgrade succeeded!"); return 0; } else { log_entry(LogCritical, "Upgrade failed! Performing restore..."); /* Well, that is why we have a backup */ result = perform_restore(backup_tool, backup_path, cfengine); if (result == 0) { log_entry(LogNormal, "Restore successful. " "CFEngine has been successfully reverted to the previous version."); return -1; } else { log_entry(LogCritical, "Failed to restore %s from %s using %s. " "Your CFEngine installation might be damaged now.", cfengine, backup_path, backup_tool); return -2; } } } else { /* Copy and run the copy */ const char *copy = ConfigurationCopy(configuration); const char *current = ConfigurationCFUpgrade(configuration); log_entry(LogVerbose, "Copying '%s' to '%s'", current, copy); result = copy_to_temporary_location(current, copy); if (result < 0) { log_entry (LogCritical, "Could not copy %s to %s", current, copy); return -1; } /* prepare the data for running the copy */ char *args[COMMAND_LINE_OPTIONS + 1]; int counter = 0; args[counter++] = xstrdup(ConfigurationCopy(configuration)); args[counter++] = xstrdup("-b"); args[counter++] = xstrdup(ConfigurationBackupTool(configuration)); args[counter++] = xstrdup("-f"); args[counter++] = xstrdup(ConfigurationCFEnginePath(configuration)); args[counter++] = xstrdup("-s"); args[counter++] = xstrdup(ConfigurationBackupPath(configuration)); /* set the perform update flag and copy the arguments */ args[counter++] = xstrdup("-x"); int i = 0; int total = ConfigurationNumberOfArguments(configuration); for (i = 0; i < total; ++i) { args[counter + i] = xstrdup(ConfigurationArgument(configuration, i)); } /* Replace current process with the copy. */ args[counter + total] = NULL; log_entry(LogVerbose, "Reexecuting cf-upgrade from the copy: %s", copy); /* Effectively this does execvp(), i.e. preserves current environment. */ result = run_process_replace(copy, args, environ); } assert(false); /* unreachable */ return -1; } cfengine-3.6.2/cf-upgrade/update.h0000644000175100017510000000264012316547775016507 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef UPDATE_H #define UPDATE_H #include /** @brief Update logic Although cf-update is a lightweight tool, there is some logic that makes sure that the update process goes according to plan. */ /** @brief Run update process with the corresponding parameters @param configuration Update configuration @return 0 if successful, -1 if not. */ int RunUpdate(const Configuration *configuration); #endif // UPDATE_H cfengine-3.6.2/cf-upgrade/Makefile.in0000664000175100017510000005554212412324464017115 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ sbin_PROGRAMS = cf-upgrade$(EXEEXT) subdir = cf-upgrade DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am_cf_upgrade_OBJECTS = alloc-mini.$(OBJEXT) command_line.$(OBJEXT) \ configuration.$(OBJEXT) log.$(OBJEXT) process.$(OBJEXT) \ update.$(OBJEXT) cf-upgrade.$(OBJEXT) cf_upgrade_OBJECTS = $(am_cf_upgrade_OBJECTS) cf_upgrade_LDADD = $(LDADD) cf_upgrade_DEPENDENCIES = ../libcompat/libcompat.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(cf_upgrade_SOURCES) DIST_SOURCES = $(cf_upgrade_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = # This tool should not link to anything LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ AM_LDFLAGS = AM_CPPFLAGS = LDADD = ../libcompat/libcompat.la cf_upgrade_SOURCES = \ alloc-mini.c alloc-mini.h \ command_line.c command_line.h \ configuration.c configuration.h \ log.c log.h \ process.c process.h \ update.c update.h \ cf-upgrade.c CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-upgrade/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-upgrade/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-upgrade$(EXEEXT): $(cf_upgrade_OBJECTS) $(cf_upgrade_DEPENDENCIES) $(EXTRA_cf_upgrade_DEPENDENCIES) @rm -f cf-upgrade$(EXEEXT) $(AM_V_CCLD)$(LINK) $(cf_upgrade_OBJECTS) $(cf_upgrade_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc-mini.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-upgrade.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command_line.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS cscopelist-am ctags ctags-am \ 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-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/cf-upgrade/Makefile.am0000664000175100017510000000067212411001073017061 0ustar00a10038a1003800000000000000sbin_PROGRAMS = cf-upgrade LIBS= # This tool should not link to anything AM_LDFLAGS= AM_CPPFLAGS= LDADD=../libcompat/libcompat.la cf_upgrade_SOURCES = \ alloc-mini.c alloc-mini.h \ command_line.c command_line.h \ configuration.c configuration.h \ log.c log.h \ process.c process.h \ update.c update.h \ cf-upgrade.c CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/cf-upgrade/alloc-mini.c0000664000175100017510000000327212363272247017237 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include /* * Copied from libutils to avoid having a dependency to it. */ static void *CheckResult(void *ptr, const char *fn, bool check_result) { if ((ptr == NULL) && (check_result)) { fputs(fn, stderr); fputs(": Unable to allocate memory\n", stderr); exit(255); } return ptr; } void *xmalloc(size_t size) { return CheckResult(malloc(size), "xmalloc", size != 0); } void *xcalloc(size_t nmemb, size_t size) { return CheckResult(calloc(nmemb, size), "xcalloc", (nmemb != 0) && (size != 0)); } char *xstrdup(const char *str) { return CheckResult(strdup(str), "xstrdup", true); } cfengine-3.6.2/cf-upgrade/alloc-mini.h0000664000175100017510000000230712363272247017242 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef ALLOC_H #define ALLOC_H /* * Copied from libutils to avoid having a dependency to it. */ #include void *xcalloc(size_t nmemb, size_t size); void *xmalloc(size_t size); char *xstrdup(const char *str); #endif cfengine-3.6.2/cf-upgrade/configuration.h0000644000175100017510000001305212316547775020073 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CONFIGURATION_H #define CONFIGURATION_H #include #define CF_UPGRADE_MAX_ARGUMENTS 32 typedef struct Configuration Configuration; /** @brief Creates a new Configuration structure. @return A new Configuration structure or NULL in case of error. */ Configuration *ConfigurationNew(); /** @brief Destroys a Configuration structure. @param configuration Structure to be destroyed. */ void ConfigurationDestroy(Configuration **configuration); /** @brief Backup tool path. @param configuration Structure. @return The path of the backup tool, or NULL in case of error. */ const char *ConfigurationBackupTool(const Configuration *configuration); /** @brief Sets the backup tool path. @param configuration Structure. @param path Path of the backup tool. */ void ConfigurationSetBackupTool(Configuration *configuration, char *path); /** @brief Path to create the backup archive. @param configuration Structure. @return A const char to the path of the backup or NULL in case of error. */ const char *ConfigurationBackupPath(const Configuration *configuration); /** @brief Sets the path to write the backup archive. @param configuration Structure. @param path Path to the backup archive. */ void ConfigurationSetBackupPath(Configuration *configuration, char *path); /** @brief Path to cf-upgrade. @param configuration Structure. @return A const char to the path of cf-upgrade or NULL in case of error. */ const char *ConfigurationCFUpgrade(const Configuration *configuration); /** @brief Sets the path to cf-upgrade. @param configuration Structure. @param path Path to cf-upgrade. */ void ConfigurationSetCFUpgrade(Configuration *configuration, char *path); /** @brief Path to the copy of cf-upgrade. @param configuration Structure. @return A const char to the path of the copy or NULL in case of error. */ const char *ConfigurationCopy(const Configuration *configuration); /** @brief Sets the path to the copy of cf-update. @param configuration Structure. @param path Path to the copy of cf-update. */ void ConfigurationSetCopy(Configuration *configuration, char *path); /** @brief CFEngine path, by default /var/cfengine. @param configuration Structure. @return A const char to the path of CFEngine or NULL in case of error. */ const char *ConfigurationCFEnginePath(const Configuration *configuration); /** @brief Sets the CFEngine path. @param configuration Structure. @param path Path to CFEngine. */ void ConfigurationSetCFEnginePath(Configuration *configuration, char *path); /** @brief Command to run to perform the actual update. @param configuration Structure. @return A const char to the command to run the update process. */ const char *ConfigurationCommand(const Configuration *configuration); /** @brief Arguments for the update command. @param configuration Structure. @return A const char pointer the nth Argument. */ const char *ConfigurationArgument(const Configuration *configuration, int number); /** @brief Sets the arguments for the update command. @remarks At most 31 parameters can be passed to the update command. @param configuration Structure. @param argument The argument to add to the arguments. */ void ConfigurationAddArgument(Configuration *configuration, char *argument); /** @brief Number of arguments to the upgrade command. @param configuration Structure. @return The number of arguments for the update command or -1 in case of error. */ int ConfigurationNumberOfArguments(const Configuration *configuration); /** @brief Whether we should perform update or copy. @param configuration Structure. @return True if update, false otherwise. */ bool ConfigurationPerformUpdate(const Configuration *configuration); /** @brief Sets whether we should perform update or copy. @param configuration Structure. @param perform True if update should be performed. */ void ConfigurationSetPerformUpdate(Configuration *configuration, bool perform); /** @brief cf-upgrade version @param configuration @return True if version was requested, false in other case. */ bool ConfigurationVersion(Configuration *configuration); /** @brief Sets the version requested flag. @param configuration */ void ConfigurationSetVersion(Configuration *configuration, bool version); /** @brief cf-upgrade help @param configuration @return True if help was requested, false in other case. */ bool ConfigurationHelp(Configuration *configuration); /** @brief Sets the help requested flag. @param configuration */ void ConfigurationSetHelp(Configuration *configuration, bool help); #endif // CONFIGURATION_H cfengine-3.6.2/cf-upgrade/process.h0000664000175100017510000000412512400110676016661 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef PROCESS_H #define PROCESS_H #define RUN_PROCESS_FAILURE_VALUE -10 #define RUN_PROCESS_FAILURE(x) \ (x == RUN_PROCESS_FAILURE_VALUE) ? true : false; /** @brief Runs the specified process by replacing the current one. @param command Full path of the command to run. @param args Arguments for the program @param envp Environment to use. @return The exit status of the process or a negative value in case of error. @remarks This function does not return, unless there was an error. */ int run_process_replace(const char *command, char **args, char **envp); /** @brief Runs the specified process and redirects the output to a file, waiting for the process to terminate. @param command Full path of the command to run. @param args Arguments for the program @param envp Environment to use. @return The exit status of the process or a negative value in case of error. @remarks Use RUN_PROCESS_FAILURE with the return value of this method to detect if the error was caused by the process or the function itself. */ int run_process_wait(const char *command, char **args, char **envp); #endif // PROCESS_H cfengine-3.6.2/cf-upgrade/process.c0000664000175100017510000002221012400110676016647 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Different includes for Unix and Windows */ #ifndef __MINGW32__ #include #else /* * According to the documentation, the access rights given to the caller * process (what would be the parent process in Unix) suffered a modification * in Windows 2008 and upwards. The ALL_ACCESS flag changed value, therefore * to keep backward compatibility we need to define the supported OS to the * lowest OS level we want to support. * If this is not defined, then we will have problems in Windows 2003. * Yes, this is the right value there is no WIN2003 flag. */ #define _WIN32_WINNT _WIN32_WINNT_WINXP #include #include #include #endif // __MINGW32__ This covers both 32 and 64 bits MinGW #ifndef __MINGW32__ /* Unix implementation */ int private_run_process_replace(const char *command, char **args, char **envp) { /* Execute the command */ execve(command, args, envp); /* If we reach here, then we have already failed */ log_entry(LogCritical, "Temporary copy failed to run, aborting"); return -1; } /* * Due to differences between Unixes and Windows, this code can only * be compiled in Unix. * Basically this code waits for the child process to die and then * returns the status. In Windows we cannot do that because Windows does * not have that kind of information. And the only kind of information * that is available is by using their calls, therefore we implement this * differently for Windows. * This site contains more information: * http://www.interopcommunity.com/dictionary/waitpid-entry.php */ int private_run_process_wait(const char *command, char **args, char **envp) { char *filename = basename(xstrdup(command)); time_t now_seconds = time(NULL); struct tm *now_tm = gmtime(&now_seconds); size_t filenamelog_size = (strlen(filename) + strlen("-YYYYMMDD-HHMMSS") + strlen(".log") + 1); char *filenamelog = xmalloc(filenamelog_size); snprintf(filenamelog, filenamelog_size, "%s-%04d%02d%02d-%02d%02d%02d.log", filename, now_tm->tm_year + 1900, now_tm->tm_mon, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec); int exit_status = 0; pid_t child = fork(); if (child < 0) { log_entry(LogCritical, "Could not fork child process: %s", command); return RUN_PROCESS_FAILURE_VALUE; } else if (child == 0) { execve(command, args, envp); /* If we reach here, the we failed */ log_entry(LogCritical, "Could not execute helper process %s", command); exit(-1); } else { /* Parent */ int status = -1; free(filenamelog); waitpid(child, &status, 0); if (WIFEXITED(status)) { exit_status = WEXITSTATUS(status); } } return exit_status; } #else /* * Windows implementations. * The Windows implementations were taken from Microsoft's documentation and * modified accordingly to fit our purposes. */ static void args_to_command_line(char *command_line, char **args, unsigned long command_line_size) { /* * Windows does not use an array for the command line arguments, but * a string. Therefore we need to revert the parsing we did before and * build the string. */ /* TODO put arguments in quotes! */ command_line[0] = '\0'; char *arg; while ((arg = *args) != NULL) { strlcat(command_line, arg, command_line_size); /* Add a space before the next argument */ strlcat(command_line, " ", command_line_size); args++; } } int private_run_process_replace(const char *command, char **args, char **envp) { STARTUPINFO si; PROCESS_INFORMATION pi; char command_line[32768]; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); ZeroMemory( command_line, sizeof(command_line) ); args_to_command_line(command_line, args, sizeof(command_line)); log_entry(LogVerbose, "Creating process with command line: %s", command_line); // Start the child process. if( !CreateProcess( command, // No module name (use command line) command_line, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { log_entry(LogCritical, "Temporary copy failed to run, aborting"); return -1; } /* * The fork-exec paradigm does not exist in Windows. Basically once a process * is created, there is no parent-child relationship as in Unix, the two * processes are independent. So, now we just need to exit the parent process * and hope for the best. Notice that if the process failed to start we * would have caught it in the if loop above. */ exit(EXIT_SUCCESS); } /* * There is an interesting difference in the Windows way of doing things versus * the Unix way. On Windows, programs usually do not use STDOUT or STDERR because * they have other reporting mechanisms. In addition the installers we run * are run using the silent flags, so they do not disturb the user. Therefore * there is no need to redirect the output to a log file. */ int private_run_process_wait(const char *command, char **args, char **envp) { STARTUPINFO si; PROCESS_INFORMATION pi; char command_line[32768]; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); ZeroMemory( command_line, sizeof(command_line) ); args_to_command_line(command_line, args, sizeof(command_line)); log_entry(LogVerbose, "Creating process with command line: %s", command_line); // Start the child process. if( !CreateProcess( command, // No module name (use command line) command_line, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory &si, // Pointer to STARTUPINFO structure &pi ) // Pointer to PROCESS_INFORMATION structure ) { log_entry(LogCritical, "Could not create child process: %s", command); return RUN_PROCESS_FAILURE_VALUE; } // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); /* Get exit status */ DWORD exit_status = 0; if ( !GetExitCodeProcess( pi.hProcess, &exit_status) ) { log_entry(LogCritical, "Could not get exit status from process: %s", command); } // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return (int)exit_status; } #endif int run_process_replace(const char *command, char **args, char **envp) { if (!command || !args || !envp) { return -1; } return private_run_process_replace(command, args, envp); } int run_process_wait(const char *command, char **args, char **envp) { if (!command || !args || !envp) { return RUN_PROCESS_FAILURE_VALUE; } return private_run_process_wait(command, args, envp); } cfengine-3.6.2/cf-upgrade/configuration.c0000664000175100017510000001443312363272247020063 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #define CF_UPGRADE_COPY "/tmp/cf-upgrade" #define CF_UPGRADE_CFENGINE "/var/cfengine/" struct Configuration { char *cf_upgrade; /*!< Path to cf-upgrade binary */ char *backup_tool; /*!< Path to the backup script */ char *backup_path; /*!< Path to the backup archive */ char *copy_path; /*!< Path to the copy of cf-upgrade, default /tmp/cf-upgrade */ char *cfengine_path; /*!< CFEngine folder, default /var/cfengine */ int number_of_arguments; /*!< Number of arguments to the upgrade command */ bool perform_update; /*!< Internal flag, whether to copy and fork or not */ char *arguments[CF_UPGRADE_MAX_ARGUMENTS]; /*!< upgrade command and arguments */ bool help; /*!< Internal flag, whether to print the help message or not */ bool version; /*!< Internal flag, whether to print the version or not */ }; Configuration *ConfigurationNew() { Configuration *configuration = NULL; configuration = xcalloc(1, sizeof(Configuration)); configuration->copy_path = xstrdup(CF_UPGRADE_COPY); configuration->cfengine_path = xstrdup(CF_UPGRADE_CFENGINE); return configuration; } void ConfigurationDestroy(Configuration **configuration) { if (!configuration || !*configuration) { return; } free ((*configuration)->cf_upgrade); free ((*configuration)->backup_path); free ((*configuration)->backup_tool); free ((*configuration)->copy_path); free ((*configuration)->cfengine_path); free (*configuration); *configuration = NULL; } const char *ConfigurationBackupTool(const Configuration *configuration) { return configuration ? configuration->backup_tool : NULL; } void ConfigurationSetBackupTool(Configuration *configuration, char *path) { if (!configuration || !path) { return; } free (configuration->backup_tool); configuration->backup_tool = xstrdup(path); } const char *ConfigurationBackupPath(const Configuration *configuration) { return configuration ? configuration->backup_path : NULL; } void ConfigurationSetBackupPath(Configuration *configuration, char *path) { if (!configuration || !path) { return; } free (configuration->backup_path); configuration->backup_path = xstrdup(path); } const char *ConfigurationCopy(const Configuration *configuration) { return configuration ? configuration->copy_path : NULL; } void ConfigurationSetCopy(Configuration *configuration, char *path) { if (!configuration || !path) { return; } free (configuration->copy_path); configuration->copy_path = xstrdup(path); } const char *ConfigurationCFUpgrade(const Configuration *configuration) { return configuration ? configuration->cf_upgrade : NULL; } void ConfigurationSetCFUpgrade(Configuration *configuration, char *path) { if (!configuration || !path) { return; } free (configuration->cf_upgrade); configuration->cf_upgrade = xstrdup(path); } const char *ConfigurationCFEnginePath(const Configuration *configuration) { return configuration ? configuration->cfengine_path : NULL; } void ConfigurationSetCFEnginePath(Configuration *configuration, char *path) { if (!configuration || !path) { return; } free (configuration->cfengine_path); configuration->cfengine_path = xstrdup(path); } const char *ConfigurationCommand(const Configuration *configuration) { return configuration ? configuration->arguments[0] : NULL; } const char *ConfigurationArgument(const Configuration *configuration, int number) { if (!configuration || (number < 0) || (number >= configuration->number_of_arguments)) { return NULL; } return configuration->arguments[number]; } void ConfigurationAddArgument(Configuration *configuration, char *argument) { if (!configuration || !argument) { return; } if (configuration->number_of_arguments < CF_UPGRADE_MAX_ARGUMENTS) { configuration->arguments[configuration->number_of_arguments] = xstrdup(argument); ++configuration->number_of_arguments; } else { log_entry(LogCritical, "A maximum of %d arguments can be specified, aborting", CF_UPGRADE_MAX_ARGUMENTS); exit(EXIT_FAILURE); } } int ConfigurationNumberOfArguments(const Configuration *configuration) { return configuration ? configuration->number_of_arguments : -1; } bool ConfigurationPerformUpdate(const Configuration *configuration) { return configuration ? configuration->perform_update : false; } void ConfigurationSetPerformUpdate(Configuration *configuration, bool perform) { if (configuration) { configuration->perform_update = perform; } } bool ConfigurationVersion(Configuration *configuration) { return configuration ? configuration->version : false; } void ConfigurationSetVersion(Configuration *configuration, bool version) { if (configuration) { configuration->version = version; } } bool ConfigurationHelp(Configuration *configuration) { return configuration ? configuration->help : false; } void ConfigurationSetHelp(Configuration *configuration, bool help) { if (configuration) { configuration->help = help; } } cfengine-3.6.2/libcfnet/0000775000175100017510000000000012413020722014575 5ustar00a10038a1003800000000000000cfengine-3.6.2/libcfnet/classic.h0000644000175100017510000000226612321511253016375 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CLASSIC_H #define CLASSIC_H #include int RecvSocketStream(int sd, char buffer[CF_BUFSIZE], int toget); int SendSocketStream(int sd, const char buffer[CF_BUFSIZE], int tosend); #endif // CLASSIC_H cfengine-3.6.2/libcfnet/client_protocol.c0000664000175100017510000004037012411001073020140 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* BN_* */ #include #include /* libutils */ #include /* Log */ /* TODO remove all includes from libpromises. */ extern char VIPADDRESS[CF_MAX_IP_LEN]; extern char VDOMAIN[]; extern char VFQNAME[]; #include /* GetCurrentUsername */ #include /* LastSaw */ #include /* PublicKeyFile */ #include /* HashString,HashesMatch,HashPubKey*/ #include #include #include /*********************************************************************/ static bool SKIPIDENTIFY = false; /* GLOBAL_P */ /*********************************************************************/ void SetSkipIdentify(bool enabled) { SKIPIDENTIFY = enabled; } /*********************************************************************/ int IdentifyAgent(ConnectionInfo *conn_info) { char uname[CF_BUFSIZE], sendbuff[CF_BUFSIZE]; char dnsname[CF_MAXVARSIZE], localip[CF_MAX_IP_LEN]; int ret; if ((!SKIPIDENTIFY) && (strcmp(VDOMAIN, CF_START_DOMAIN) == 0)) { Log(LOG_LEVEL_ERR, "Undefined domain name"); return false; } if (!SKIPIDENTIFY) { /* First we need to find out the IP address and DNS name of the socket we are sending from. This is not necessarily the same as VFQNAME if the machine has a different uname from its IP name (!) This can happen on poorly set up machines or on hosts with multiple interfaces, with different names on each interface ... */ struct sockaddr_storage myaddr = {0}; socklen_t myaddr_len = sizeof(myaddr); if (getsockname(conn_info->sd, (struct sockaddr *) &myaddr, &myaddr_len) == -1) { Log(LOG_LEVEL_ERR, "Couldn't get socket address. (getsockname: %s)", GetErrorStr()); return false; } /* No lookup, just convert the bound address to string. */ ret = getnameinfo((struct sockaddr *) &myaddr, myaddr_len, localip, sizeof(localip), NULL, 0, NI_NUMERICHOST); if (ret != 0) { Log(LOG_LEVEL_ERR, "During agent identification. (getnameinfo: %s)", gai_strerror(ret)); return false; } /* dnsname: Reverse lookup of the bound IP address. */ ret = getnameinfo((struct sockaddr *) &myaddr, myaddr_len, dnsname, sizeof(dnsname), NULL, 0, 0); if (ret != 0) { /* getnameinfo doesn't fail on resolution failure, it just prints * the IP, so here something else is wrong. */ Log(LOG_LEVEL_ERR, "During agent identification for '%s'. (getnameinfo: %s)", localip, gai_strerror(ret)); return false; } /* getnameinfo() should always return FQDN. Some resolvers will not * return FQNAME and missing PTR will give numerical result */ if ((strlen(VDOMAIN) > 0) /* TODO true always? */ && (!IsIPV6Address(dnsname)) && (!strchr(dnsname, '.'))) { strcat(dnsname, "."); strncat(dnsname, VDOMAIN, CF_MAXVARSIZE / 2); } /* Seems to be a bug in some resolvers that adds garbage, when it just * returns the input. */ if (strncmp(dnsname, localip, strlen(localip)) == 0 && dnsname[strlen(localip)] != '\0') { dnsname[strlen(localip)] = '\0'; Log(LOG_LEVEL_WARNING, "getnameinfo() seems to append garbage to unresolvable IPs, bug mitigated by CFEngine but please report your platform!"); } } else { assert(sizeof(localip) >= sizeof(VIPADDRESS)); strcpy(localip, VIPADDRESS); Log(LOG_LEVEL_VERBOSE, "skipidentify was promised, so we are trusting and simply announcing the identity as '%s' for this host", strlen(VFQNAME) > 0 ? VFQNAME : "skipident"); if (strlen(VFQNAME) > 0) { strcpy(dnsname, VFQNAME); } else { strcpy(dnsname, "skipident"); } } /* client always identifies as root on windows */ #ifdef __MINGW32__ snprintf(uname, sizeof(uname), "%s", "root"); #else GetCurrentUserName(uname, sizeof(uname)); #endif snprintf(sendbuff, sizeof(sendbuff), "CAUTH %s %s %s %d", localip, dnsname, uname, 0); if (SendTransaction(conn_info, sendbuff, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "During identify agent, could not send auth response. (SendTransaction: %s)", GetErrorStr()); return false; } return true; } /*********************************************************************/ static bool SetSessionKey(AgentConnection *conn) { BIGNUM *bp; int session_size = CfSessionKeySize(conn->encryption_type); bp = BN_new(); if (bp == NULL) { Log(LOG_LEVEL_ERR, "Could not allocate session key"); return false; } // session_size is in bytes if (!BN_rand(bp, session_size * 8, -1, 0)) { Log(LOG_LEVEL_ERR, "Can't generate cryptographic key"); BN_clear_free(bp); return false; } conn->session_key = (unsigned char *) bp->d; return true; } int AuthenticateAgent(AgentConnection *conn, bool trust_key) { char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len, nonce_len = 0, len, session_size; bool need_to_implicitly_trust_server; char enterprise_field = 'c'; RSA *server_pubkey = NULL; if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { /* Try once more to load the keys, maybe the system is converging. */ LoadSecretKeys(); if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { char *pubkeyfile = PublicKeyFile(GetWorkDir()); Log(LOG_LEVEL_ERR, "No public/private key pair found at: %s", pubkeyfile); free(pubkeyfile); return false; } } enterprise_field = CfEnterpriseOptions(); session_size = CfSessionKeySize(enterprise_field); /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); if (nonce_challenge == NULL) { Log(LOG_LEVEL_ERR, "Cannot allocate BIGNUM structure for server challenge"); return false; } BN_rand(nonce_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(nonce_challenge, in); if (FIPS_MODE) { HashString(in, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(in, nonce_len, digest, HASH_METHOD_MD5); } /* We assume that the server bound to the remote socket is the official one i.e. = root's */ /* Ask the server to send us the public key if we don't have it. */ if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip))) { need_to_implicitly_trust_server = false; encrypted_len = RSA_size(server_pubkey); } else { need_to_implicitly_trust_server = true; encrypted_len = nonce_len; } // Server pubkey is what we want to has as a unique ID snprintf(sendbuffer, sizeof(sendbuffer), "SAUTH %c %d %d %c", need_to_implicitly_trust_server ? 'n': 'y', encrypted_len, nonce_len, enterprise_field); out = xmalloc(encrypted_len); if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len, in, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Public encryption failed. (RSA_public_encrypt: %s)", CryptoLastErrorString()); free(out); RSA_free(server_pubkey); return false; } memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, out, encrypted_len); } else { memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, in, nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(conn->conn_info, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, len, CF_DONE); /* check reply about public key - server can break conn_info here */ /* proposition S1 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (1). (ReceiveTransaction: %s)", GetErrorStr()); RSA_free(server_pubkey); return false; } if (BadProtoReply(in)) { Log(LOG_LEVEL_ERR, "Bad protocol reply: %s", in); RSA_free(server_pubkey); return false; } /* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */ /* proposition S2 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, in, NULL) == -1) { Log(LOG_LEVEL_ERR, "Protocol transaction broken off (2). (ReceiveTransaction: %s)", GetErrorStr()); RSA_free(server_pubkey); return false; } /* Check if challenge reply was correct */ if ((HashesMatch(digest, in, CF_DEFAULT_DIGEST)) || (HashesMatch(digest, in, HASH_METHOD_MD5))) // Legacy { if (need_to_implicitly_trust_server == false) { /* The IP was found in lastseen. */ Log(LOG_LEVEL_VERBOSE, ".....................[.h.a.i.l.]................................."); Log(LOG_LEVEL_VERBOSE, "Strong authentication of server '%s' connection confirmed", conn->this_server); } else /* IP was not found in lastseen */ { if (trust_key) { Log(LOG_LEVEL_VERBOSE, "Trusting server identity, promise to accept key from '%s' = '%s'", conn->this_server, conn->remoteip); } else { Log(LOG_LEVEL_ERR, "Not authorized to trust public key of server '%s' (trustkey = false)", conn->this_server); RSA_free(server_pubkey); return false; } } } else { Log(LOG_LEVEL_ERR, "Challenge response from server '%s/%s' was incorrect", conn->this_server, conn->remoteip); RSA_free(server_pubkey); return false; } /* Receive counter challenge from server */ /* proposition S3 */ memset(in, 0, CF_BUFSIZE); encrypted_len = ReceiveTransaction(conn->conn_info, in, NULL); if (encrypted_len <= 0) { Log(LOG_LEVEL_ERR, "Protocol transaction sent illegal cipher length"); RSA_free(server_pubkey); return false; } decrypted_cchall = xmalloc(encrypted_len); if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Private decrypt failed, abandoning. (RSA_private_decrypt: %s)", CryptoLastErrorString()); RSA_free(server_pubkey); return false; } /* proposition C4 */ if (FIPS_MODE) { HashString(decrypted_cchall, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(decrypted_cchall, nonce_len, digest, HASH_METHOD_MD5); } if (FIPS_MODE) { SendTransaction(conn->conn_info, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE); } else { SendTransaction(conn->conn_info, digest, CF_MD5_LEN, CF_DONE); } free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); Log(LOG_LEVEL_VERBOSE, "Collecting public key from server!"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(conn->conn_info, in, NULL)) <= 0) { Log(LOG_LEVEL_ERR, "Protocol error in RSA authentation from IP '%s'", conn->this_server); return false; } if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Private key decrypt failed. (BN_mpi2bn: %s)", CryptoLastErrorString()); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len = ReceiveTransaction(conn->conn_info, in, NULL)) <= 0) { Log(LOG_LEVEL_INFO, "Protocol error in RSA authentation from IP '%s'", conn->this_server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Public key decrypt failed. (BN_mpi2bn: %s)", CryptoLastErrorString()); RSA_free(newkey); return false; } server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } assert(server_pubkey != NULL); /* proposition C5 */ if (!SetSessionKey(conn)) { Log(LOG_LEVEL_ERR, "Unable to set session key"); return false; } if (conn->session_key == NULL) { Log(LOG_LEVEL_ERR, "A random session key could not be established"); RSA_free(server_pubkey); return false; } encrypted_len = RSA_size(server_pubkey); out = xmalloc(encrypted_len); if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { Log(LOG_LEVEL_ERR, "Public encryption failed. (RSA_public_encrypt: %s)", CryptoLastErrorString()); free(out); RSA_free(server_pubkey); return false; } SendTransaction(conn->conn_info, out, encrypted_len, CF_DONE); Key *key = KeyNew(server_pubkey, CF_DEFAULT_DIGEST); conn->conn_info->remote_key = key; Log(LOG_LEVEL_VERBOSE, "Public key identity of host '%s' is: %s", conn->remoteip, KeyPrintableHash(conn->conn_info->remote_key)); SavePublicKey(conn->username, KeyPrintableHash(conn->conn_info->remote_key), server_pubkey); unsigned int length = 0; LastSaw(conn->remoteip, KeyBinaryHash(conn->conn_info->remote_key, &length), LAST_SEEN_ROLE_CONNECT); free(out); return true; } /*********************************************************************/ int BadProtoReply(char *buf) { return (strncmp(buf, "BAD: ", 5) == 0); } /*********************************************************************/ int OKProtoReply(char *buf) { return (strncmp(buf, "OK:", 3) == 0); } /*********************************************************************/ int FailedProtoReply(char *buf) { return (strncmp(buf, CF_FAILEDSTR, strlen(CF_FAILEDSTR)) == 0); } cfengine-3.6.2/libcfnet/misc.c0000644000175100017510000000737112316547775015732 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* Convert IP address in src (which can be struct sockaddr_storage (best * choice for any IP version), struct sockaddr, struct sockaddr_in or struct * sockaddr_in6) to string dst. * Better use getnameinfo(NI_NUMERICHOST) if available. */ const char *sockaddr_ntop(const void *src, char *dst, socklen_t size) { int family = ((struct sockaddr *) src)->sa_family; void *addr; switch (family) { case AF_INET: addr = & ((struct sockaddr_in *) src)->sin_addr.s_addr; break; #ifdef HAVE_GETADDRINFO case AF_INET6: addr = & ((struct sockaddr_in6 *) src)->sin6_addr.s6_addr; break; #endif #ifdef AF_LOCAL case AF_LOCAL: strcpy(dst, "127.0.0.1"); return dst; #endif default: ProgrammingError("sockaddr_ntop: address family was %d", family); } const char *ret = inet_ntop(family, addr, dst, size); return ret; } /* Return the port number in host byte order. */ uint16_t sockaddr_port(const void *sa) { int family = ((struct sockaddr *) sa)->sa_family; uint16_t port; switch (family) { case AF_INET: port = ((struct sockaddr_in *) sa)->sin_port; break; #ifdef HAVE_GETADDRINFO case AF_INET6: addr = ((struct sockaddr_in6 *) sa)->sin6_port; break; #endif default: ProgrammingError("sockaddr_port: address family was %d", family); } return ntohs(port); } int sockaddr_AddrCompare(const void *sa1, const void *sa2) { int sa1_family = ((struct sockaddr *) sa1)->sa_family; int sa2_family = ((struct sockaddr *) sa2)->sa_family; if ((sa1_family != AF_INET && sa1_family != AF_INET6) || (sa2_family != AF_INET && sa2_family != AF_INET6)) { ProgrammingError("sockaddr_AddrCompare: Unknown address families %d %d", sa1_family, sa2_family); } if (sa1_family != sa2_family) { /* We consider any IPv4 address smaller than any IPv6 one. */ return (sa1_family == AF_INET) ? -1 : 1; } int result; switch (sa1_family) { case AF_INET: { struct in_addr *addr1 = & ((struct sockaddr_in *) sa1)->sin_addr; struct in_addr *addr2 = & ((struct sockaddr_in *) sa2)->sin_addr; result = memcmp(addr1, addr2, sizeof(*addr1)); } case AF_INET6: { struct in6_addr *addr1 = & ((struct sockaddr_in6 *) sa1)->sin6_addr; struct in6_addr *addr2 = & ((struct sockaddr_in6 *) sa2)->sin6_addr; result = memcmp(addr1, addr2, sizeof(*addr1)); } default: assert(0); result = 0; } return result; } /* int sockaddr_AddrCompareMasked(const void *sa1, const void *sa2, int cidr_mask) */ /* { */ /* assert(cidr_mask >= 0 && cidr_mask <= 128); */ /* } */ cfengine-3.6.2/libcfnet/tls_client.h0000644000175100017510000000262412332665147017130 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_TLS_CLIENT_H #define CFENGINE_TLS_CLIENT_H #include bool TLSClientInitialize(void); void TLSDeInitialize(void); int TLSClientIdentificationDialog(ConnectionInfo *conn_info, const char *username); int TLSConnect(ConnectionInfo *conn_info, bool trust_server, const char *ipaddr, const char *username); int TLSTry(ConnectionInfo *conn_info); #endif cfengine-3.6.2/libcfnet/key.h0000644000175100017510000000517512352022221015542 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef KEY_H #define KEY_H #include #include /** @brief Structure to simplify the key management. */ typedef struct Key Key; /** @brief Creates a new Key structure. @param key RSA structure @param hash Hash method to use when hashing the key. @return A fully initialized Key structure or NULL in case of error. */ Key *KeyNew(RSA *rsa, HashMethod method); /** @brief Destroys a structure of type Key. @param key Structure to be destroyed. */ void KeyDestroy(Key **key); /** @brief Constant pointer to the key data. @param key Key @return A pointer to the RSA structure. */ RSA *KeyRSA(const Key *key); /** @brief Binary hash of the key @param key Key structure @param length Length of the binary hash @return A pointer to the binary hash or NULL in case of error. */ const unsigned char *KeyBinaryHash(const Key *key, unsigned int *length); /** @brief Printable hash of the key. @param key @return A pointer to the printable hash of the key. */ const char *KeyPrintableHash(const Key *key); /** @brief Method use to hash the key. @param key Structure @return Method used to hash the key. */ HashMethod KeyHashMethod(const Key *key); /** @brief Changes the method used to hash the key. This method triggers a rehashing of the key. This can be an expensive operation. @param key Structure @param hash New hashing mechanism. @return 0 if successful, -1 in case of error. */ int KeySetHashMethod(Key *key, HashMethod method); /** @brief Internal Hash data @param key Structure @return A pointer to the Hash structure or NULL in case of error. */ const Hash *KeyData(Key *key); #endif // KEY_H cfengine-3.6.2/libcfnet/cfnet.h0000664000175100017510000001161412411001073016044 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CFNET_H #define CFENGINE_CFNET_H #include /* Only set with DetermineCfenginePort() and from cf-serverd */ extern char CFENGINE_PORT_STR[16]; /* GLOBAL_P GLOBAL_E */ extern int CFENGINE_PORT; /* GLOBAL_P GLOBAL_E */ /* max size of plaintext in one transaction, see net.c:SendTransaction(), leave space for encryption padding (assuming max 64*8 = 512-bit cipher block size). */ #define CF_BUFSIZE 4096 #define CF_SMALLBUF 128 #define CF_MAX_IP_LEN 64 /* max IPv4/IPv6 address length */ #define CF_DONE 't' #define CF_MORE 'm' #define SOCKET_INVALID -1 #define MAXIP4CHARLEN 16 #define CF_RSA_PROTO_OFFSET 24 #define CF_PROTO_OFFSET 16 #define CF_INBAND_OFFSET 8 /** Available protocol versions. When connection is initialised ProtocolVersion is 0, i.e. undefined. It is after the call to ServerConnection() that protocol version is decided, according to body copy_from and body common control. All protocol numbers are numbered incrementally starting from 1. */ typedef enum { CF_PROTOCOL_UNDEFINED = 0, CF_PROTOCOL_CLASSIC = 1, /* --- Greater versions use TLS as secure communications layer --- */ CF_PROTOCOL_TLS = 2 } ProtocolVersion; /* We use CF_PROTOCOL_LATEST as the default for new connections. */ #define CF_PROTOCOL_LATEST CF_PROTOCOL_TLS static const char * const PROTOCOL_VERSION_STRING[CF_PROTOCOL_LATEST + 1] = { "undefined", "classic", "latest" }; typedef struct { ProtocolVersion protocol_version : 3; bool cache_connection : 1; bool force_ipv4 : 1; bool trust_server : 1; } ConnectionFlags; #include "connection_info.h" /* needs ProtocolVersion */ /* TODO Shouldn't this be in libutils? */ typedef enum { FILE_TYPE_REGULAR, FILE_TYPE_LINK, FILE_TYPE_DIR, FILE_TYPE_FIFO, FILE_TYPE_BLOCK, FILE_TYPE_CHAR_, /* Conflict with winbase.h */ FILE_TYPE_SOCK } FileType; typedef struct Stat_ Stat; struct Stat_ { char *cf_filename; /* What file are we statting? */ char *cf_server; /* Which server did this come from? */ FileType cf_type; /* enum filetype */ mode_t cf_lmode; /* Mode of link, if link */ mode_t cf_mode; /* Mode of remote file, not link */ uid_t cf_uid; /* User ID of the file's owner */ gid_t cf_gid; /* Group ID of the file's group */ off_t cf_size; /* File size in bytes */ time_t cf_atime; /* Time of last access */ time_t cf_mtime; /* Time of last data modification */ time_t cf_ctime; /* Time of last file status change */ char cf_makeholes; /* what we need to know from blksize and blks */ char *cf_readlink; /* link value or NULL */ int cf_failed; /* stat returned -1 */ int cf_nlink; /* Number of hard links */ int cf_ino; /* inode number on server */ dev_t cf_dev; /* device number */ Stat *next; }; /* * TLS support */ #define DEFAULT_TLS_TIMEOUT_SECONDS 5 #define DEFAULT_TLS_TIMEOUT_USECONDS 0 #define SET_DEFAULT_TLS_TIMEOUT(x) \ x.tv_sec = DEFAULT_TLS_TIMEOUT_SECONDS; \ x.tv_usec = DEFAULT_TLS_TIMEOUT_USECONDS #define DEFAULT_TLS_TRIES 5 typedef struct { ConnectionInfo *conn_info; int authenticated; char username[CF_SMALLBUF]; /* Unused for now... */ /* char localip[CF_MAX_IP_LEN]; */ char remoteip[CF_MAX_IP_LEN]; unsigned char *session_key; char encryption_type; short error; ConnectionFlags flags; /* mostly copy_from connection attributes */ char *this_server; Stat *cache; /* cache for stat() (SYNCH command) */ } AgentConnection; /* misc.c */ const char *sockaddr_ntop(const void *src, char *dst, socklen_t size); #endif cfengine-3.6.2/libcfnet/communication.h0000664000175100017510000000335212411001073017612 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_COMMUNICATION_H #define CFENGINE_COMMUNICATION_H #include /** @brief Creates a new connection from Agent to Server. @param server_name Server to connect to. @return A fully initialized AgentConnection or NULL in case of error. */ AgentConnection *NewAgentConn(const char *server_name); /** @brief Destroys an AgentConnection. @param ap AgentConnection structure. */ void DeleteAgentConn(AgentConnection *ap); int IsIPV6Address(char *name); int IsIPV4Address(char *name); int Hostname2IPString(char *dst, const char *hostname, size_t dst_size); int IPString2Hostname(char *dst, const char *ipaddr, size_t dst_size); int GetMyHostInfo(char nameBuf[MAXHOSTNAMELEN], char ipBuf[MAXIP4CHARLEN]); unsigned short SocketFamily(int sd); #endif cfengine-3.6.2/libcfnet/classic.c0000664000175100017510000000673712411001073016373 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include static bool LastRecvTimedOut(void) { #ifndef __MINGW32__ if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { return true; } #else int lasterror = GetLastError(); if (lasterror == EAGAIN || lasterror == WSAEWOULDBLOCK) { return true; } #endif return false; } /** * @brief Receive up to #toget bytes, plus a '\0', into buffer from sd. * @param sd Socket descriptor * @param buffer Buffer into which to read data * @param toget Number of bytes to read; a '\0' shall be written after * the data; buffer must have space for that. * @return -1 on error; or actual length read. */ int RecvSocketStream(int sd, char buffer[CF_BUFSIZE], int toget) { int already, got; if (toget > CF_BUFSIZE - 1 || toget < 0) { Log(LOG_LEVEL_ERR, "Bad software request to receive %d bytes", toget); return -1; } for (already = 0; already < toget; already += got) { got = recv(sd, buffer + already, toget - already, 0); if (got == -1) { if (errno == EINTR) { continue; } else if (LastRecvTimedOut()) { Log(LOG_LEVEL_ERR, "Timeout - remote end did not respond with the expected amount of data (received=%d, expecting=%d). (recv: %s)", already, toget, GetErrorStr()); } else { Log(LOG_LEVEL_ERR, "Couldn't receive. (recv: %s)", GetErrorStr()); } return -1; } else if (got == 0) /* doesn't happen unless sock is closed */ { break; } } assert(already <= toget); buffer[already] = '\0'; return already; } /*************************************************************************/ int SendSocketStream(int sd, const char buffer[CF_BUFSIZE], int tosend) { int sent, already = 0; if (tosend <= 0) { Log(LOG_LEVEL_ERR, "Bad software request to send %d bytes", tosend); return -1; } do { sent = send(sd, buffer + already, tosend - already, 0); if ((sent == -1) && (errno == EINTR)) { continue; } if (sent == -1) { Log(LOG_LEVEL_VERBOSE, "Couldn't send. (send: %s)", GetErrorStr()); return -1; } already += sent; } while (already < tosend); return already; } cfengine-3.6.2/libcfnet/communication.c0000664000175100017510000001733212411001073017610 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* xmalloc,... */ #include /* Log */ #include /* ProgrammingError */ #include /* Buffer */ #include /* IPAddress */ AgentConnection *NewAgentConn(const char *server_name) { AgentConnection *conn = xcalloc(1, sizeof(AgentConnection)); ConnectionInfo *info = ConnectionInfoNew(); conn->conn_info = info; conn->encryption_type = 'c'; conn->this_server = xstrdup(server_name); conn->authenticated = false; return conn; } void DeleteAgentConn(AgentConnection *conn) { Stat *sp = conn->cache; while (sp != NULL) { Stat *sps = sp; sp = sp->next; free(sps); } ConnectionInfoDestroy(&conn->conn_info); if (conn->session_key) { free(conn->session_key); } if (conn->this_server) { free(conn->this_server); } *conn = (AgentConnection) {0}; free(conn); } int IsIPV6Address(char *name) { if (!name) { return false; } Buffer *buffer = BufferNewFrom(name, strlen(name)); if (!buffer) { return false; } IPAddress *ip_address = NULL; bool is_ip = false; is_ip = IPAddressIsIPAddress(buffer, &ip_address); if (!is_ip) { BufferDestroy(buffer); return false; } if (IPAddressType(ip_address) != IP_ADDRESS_TYPE_IPV6) { BufferDestroy(buffer); IPAddressDestroy(&ip_address); return false; } BufferDestroy(buffer); IPAddressDestroy(&ip_address); return true; } /*******************************************************************/ int IsIPV4Address(char *name) { if (!name) { return false; } Buffer *buffer = BufferNewFrom(name, strlen(name)); if (!buffer) { return false; } IPAddress *ip_address = NULL; bool is_ip = false; is_ip = IPAddressIsIPAddress(buffer, &ip_address); if (!is_ip) { BufferDestroy(buffer); return false; } if (IPAddressType(ip_address) != IP_ADDRESS_TYPE_IPV4) { BufferDestroy(buffer); IPAddressDestroy(&ip_address); return false; } BufferDestroy(buffer); IPAddressDestroy(&ip_address); return true; } /*****************************************************************************/ /** * @brief DNS lookup of hostname, store the address as string into dst of size * dst_size. * @return -1 in case of unresolvable hostname or other error. */ int Hostname2IPString(char *dst, const char *hostname, size_t dst_size) { int ret; struct addrinfo *response = NULL, *ap; struct addrinfo query = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; if (dst_size < CF_MAX_IP_LEN) { ProgrammingError("Hostname2IPString got %zu, needs at least" " %d length buffer for IPv6 portability!", dst_size, CF_MAX_IP_LEN); } ret = getaddrinfo(hostname, NULL, &query, &response); if (ret != 0) { Log(LOG_LEVEL_INFO, "Unable to lookup hostname '%s' or cfengine service. (getaddrinfo: %s)", hostname, gai_strerror(ret)); if (response != NULL) { freeaddrinfo(response); } return -1; } for (ap = response; ap != NULL; ap = ap->ai_next) { /* No lookup, just convert numeric IP to string. */ int ret2 = getnameinfo(ap->ai_addr, ap->ai_addrlen, dst, dst_size, NULL, 0, NI_NUMERICHOST); if (ret2 == 0) { freeaddrinfo(response); return 0; /* Success */ } } assert(response != NULL); /* getaddrinfo() was successful */ freeaddrinfo(response); Log(LOG_LEVEL_ERR, "Hostname2IPString: ERROR even though getaddrinfo returned success!"); return -1; } /*****************************************************************************/ /** * @brief Reverse DNS lookup of ipaddr, store the address as string into dst * of size dst_size. * @return -1 in case of unresolvable IP address or other error. */ int IPString2Hostname(char *dst, const char *ipaddr, size_t dst_size) { int ret; struct addrinfo *response = NULL; /* First convert ipaddr string to struct sockaddr, with no DNS query. */ struct addrinfo query = { .ai_flags = AI_NUMERICHOST }; ret = getaddrinfo(ipaddr, NULL, &query, &response); if (ret != 0) { Log(LOG_LEVEL_ERR, "Unable to convert IP address '%s'. (getaddrinfo: %s)", ipaddr, gai_strerror(ret)); if (response != NULL) { freeaddrinfo(response); } return -1; } /* response should only have one reply, so no need to iterate over the * response struct addrinfo. */ /* Reverse DNS lookup. NI_NAMEREQD forces an error if not resolvable. */ ret = getnameinfo(response->ai_addr, response->ai_addrlen, dst, dst_size, NULL, 0, NI_NAMEREQD); if (ret != 0) { Log(LOG_LEVEL_INFO, "Couldn't reverse resolve '%s'. (getaddrinfo: %s)", ipaddr, gai_strerror(ret)); freeaddrinfo(response); return -1; } assert(response != NULL); /* getaddrinfo() was successful */ freeaddrinfo(response); return 0; /* Success */ } /*****************************************************************************/ int GetMyHostInfo(char nameBuf[MAXHOSTNAMELEN], char ipBuf[MAXIP4CHARLEN]) { char *ip; struct hostent *hostinfo; if (gethostname(nameBuf, MAXHOSTNAMELEN) == 0) { if ((hostinfo = gethostbyname(nameBuf)) != NULL) { ip = inet_ntoa(*(struct in_addr *) *hostinfo->h_addr_list); strlcpy(ipBuf, ip, MAXIP4CHARLEN); return true; } else { Log(LOG_LEVEL_ERR, "Could not get host entry for local host. (gethostbyname: %s)", GetErrorStr()); } } else { Log(LOG_LEVEL_ERR, "Could not get host name. (gethostname: %s)", GetErrorStr()); } return false; } /*****************************************************************************/ unsigned short SocketFamily(int sd) { struct sockaddr_storage ss = {0}; socklen_t len = sizeof(ss); if (getsockname(sd, (struct sockaddr *) &ss, &len) == -1) { Log(LOG_LEVEL_ERR, "Could not get socket family. (getsockname: %s)", GetErrorStr()); } return ss.ss_family; } cfengine-3.6.2/libcfnet/Makefile.in0000664000175100017510000005214312412324464016660 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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 = libcfnet DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcfnet_la_LIBADD = am_libcfnet_la_OBJECTS = misc.lo net.lo communication.lo \ client_protocol.lo client_code.lo classic.lo tls_client.lo \ tls_generic.lo connection_info.lo key.lo libcfnet_la_OBJECTS = $(am_libcfnet_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcfnet_la_SOURCES) DIST_SOURCES = $(libcfnet_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcfnet.la AM_CPPFLAGS = $(OPENSSL_CPPFLAGS) $(PCRE_CPPFLAGS) \ -I$(top_srcdir)/libutils -I$(top_srcdir)/libpromises # \ cf3.defs.h libcfnet_la_SOURCES = \ misc.c \ net.c net.h \ communication.c communication.h \ client_protocol.c client_protocol.h cfnet.h\ client_code.c client_code.h \ classic.c classic.h \ tls_client.c tls_client.h \ tls_generic.c tls_generic.h \ connection_info.c connection_info.h \ key.c key.h 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) --foreign libcfnet/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libcfnet/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcfnet.la: $(libcfnet_la_OBJECTS) $(libcfnet_la_DEPENDENCIES) $(EXTRA_libcfnet_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcfnet_la_OBJECTS) $(libcfnet_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/classic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_code.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_protocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/communication.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection_info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_generic.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi 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-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 TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am 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 tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-3.6.2/libcfnet/client_code.h0000664000175100017510000000460112411001073017213 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CLIENT_CODE_H #define CFENGINE_CLIENT_CODE_H #include #include #include bool cfnet_init(void); void cfnet_shut(void); void DetermineCfenginePort(void); /** @param err Set to 0 on success, -1 no server responce, -2 authentication failure. */ AgentConnection *ServerConnection(const char *server, const char *port, unsigned int connect_timeout, ConnectionFlags flags, int *err); void DisconnectServer(AgentConnection *conn); int cf_remote_stat(const char *file, struct stat *buf, const char *stattype, bool encrypt, AgentConnection *conn); int CompareHashNet(const char *file1, const char *file2, bool encrypt, AgentConnection *conn); int CopyRegularFileNet(const char *source, const char *dest, off_t size, bool encrypt, AgentConnection *conn); Item *RemoteDirList(const char *dirname, bool encrypt, AgentConnection *conn); const Stat *ClientCacheLookup(AgentConnection *conn, const char *server_name, const char *file_name); /* Mark connection as free */ AgentConnection *GetIdleConnectionToServer(const char *server); void MarkServerOffline(const char *server); bool ServerOffline(const char *server); void CacheServerConnection(AgentConnection *conn, const char *server); void ServerNotBusy(AgentConnection *conn); int TLSConnectCallCollect(ConnectionInfo *conn_info, const char *username); #endif cfengine-3.6.2/libcfnet/connection_info.h0000664000175100017510000001225412411001073020120 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CONNECTION_INFO_H #define CONNECTION_INFO_H #include #include #include /** @brief ConnectionInfo Structure and support routines ConnectionInfo is used to abstract the underlying type of connection from our protocol implementation. It can hold both a normal socket connection and a TLS stream. */ /** @brief States of the connection. @note Status of the connection so we can detect if we need to negotiate a new connection or not */ typedef enum { CF_CONNECTION_NOT_ESTABLISHED, CF_CONNECTION_ESTABLISHED } ConnectionStatus; struct ConnectionInfo { ProtocolVersion type; ConnectionStatus status; int sd; /* Socket descriptor */ SSL *ssl; /* OpenSSL struct for TLS connections */ Key *remote_key; socklen_t ss_len; struct sockaddr_storage ss; bool is_call_collect; /* Maybe replace with a bitfield later ... */ }; typedef struct ConnectionInfo ConnectionInfo; /** @brief Creates a new ConnectionInfo structure. @return A initialized ConnectionInfo structure, needs to be populated. */ ConnectionInfo *ConnectionInfoNew(void); /** @brief Destroys a ConnectionInfo structure. @param info Pointer to the ConectionInfo structure to be destroyed. */ void ConnectionInfoDestroy(ConnectionInfo **info); /** @brief Protocol Version @param info ConnectionInfo structure @return Returns the protocol version or CF_PROTOCOL_UNDEFINED in case of error. */ ProtocolVersion ConnectionInfoProtocolVersion(const ConnectionInfo *info); /** @brief Sets the protocol version Notice that if an invalid protocol version is passed, the value will not be changed. @param info ConnectionInfo structure. @param version New protocol version */ void ConnectionInfoSetProtocolVersion(ConnectionInfo *info, ProtocolVersion version); /** @brief Connection status @param info ConnectionInfo structure @return Returns the status of the connection or CF_CONNECTION_NOT_ESTABLISHED in case of error. */ ConnectionStatus ConnectionInfoConnectionStatus(const ConnectionInfo *info); /** @brief Sets the connection status. @param info ConnectionInfo structure. @param status New status */ void ConnectionInfoSetConnectionStatus(ConnectionInfo *info, ConnectionStatus status); /** @brief Connection socket For practical reasons there is no difference between an invalid socket and an error on this routine. @param info ConnectionInfo structure. @return Returns the connection socket or -1 in case of error. */ int ConnectionInfoSocket(const ConnectionInfo *info); /** @brief Sets the connection socket. @param info ConnectionInfo structure. @param s New connection socket. */ void ConnectionInfoSetSocket(ConnectionInfo *info, int s); /** @brief SSL structure. @param info ConnectionInfo structure. @return The SSL structure attached to this connection or NULL in case of error. */ SSL *ConnectionInfoSSL(const ConnectionInfo *info); /** @brief Sets the SSL structure. @param info ConnectionInfo structure. @param ssl SSL structure to attached to this connection. */ void ConnectionInfoSetSSL(ConnectionInfo *info, SSL *ssl); /** @brief RSA key @param info ConnectionInfo structure. @return Returns the RSA key or NULL in case of error. */ const Key *ConnectionInfoKey(const ConnectionInfo *info); /** @brief Sets the key for the connection structure. This triggers a calculation of two other fields. @param info ConnectionInfo structure. @param key RSA key. */ void ConnectionInfoSetKey(ConnectionInfo *info, Key *key); /** @brief A constant pointer to the binary hash of the key @param info ConnectionInfo structure @param length Length of the hash @return Returns a constant pointer to the binary hash and if length is not NULL the size is stored there. */ const unsigned char *ConnectionInfoBinaryKeyHash(ConnectionInfo *info, unsigned int *length); /** @brief A constant pointer to the binary hash of the key @param info ConnectionInfo structure @return Returns a printable representation of the hash. The string is '\0' terminated or NULL in case of failure. */ const char *ConnectionInfoPrintableKeyHash(ConnectionInfo *info); #endif // CONNECTION_INFO_H cfengine-3.6.2/libcfnet/client_code.c0000664000175100017510000012215412411001073017212 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include /* struct ConnectionInfo */ #include #include #include #include /* RecvSocketStream */ #include /* SendTransaction,ReceiveTransaction */ #include /* TLSTry */ #include /* TLSVerifyPeer */ #include #include #include /* AllocateDirentForFilename */ #include #include /* CryptoInitialize,SavePublicKey,EncryptString */ #include #include /* HashFile */ #include /* ThreadLock */ #include /* FullWrite,safe_open */ #include /* MemSpan,MemSpanInverse */ #include /* ProgrammingError */ #include /* PRINTSIZE */ #include /* LastSaw */ typedef struct { char *server; AgentConnection *conn; int busy; } ServerItem; #define CFENGINE_SERVICE "cfengine" #define CF_COULD_NOT_CONNECT -2 static pthread_mutex_t cft_serverlist = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; static void NewClientCache(Stat *data, AgentConnection *conn); static void FlushFileStream(int sd, int toget); static int CacheStat(const char *file, struct stat *statbuf, const char *stattype, AgentConnection *conn); /** * Initialize client's network library. */ bool cfnet_init() { CryptoInitialize(); if (TLSClientInitialize()) return true; else return false; } void cfnet_shut() { TLSDeInitialize(); CryptoDeInitialize(); } static Seq *GetGlobalServerList(void) { /* Only ip address strings are stored in this list, so don't put any * hostnames. TODO convert to list of (sockaddr_storage *) to enforce this. */ /* TODO replace Seq or lock properly. Someone changed this SERVERLIST from * RList to Seq, but didn't think of the implications. As a result this * list now is in great danger of corruption when written from multiple * threads. Luckily multi-threaded access is not the common case. */ static Seq *server_list = NULL; /* GLOBAL_X */ if (!server_list) { server_list = SeqNew(100, free); } return server_list; } static int FSWrite(const char *destination, int dd, const char *buf, size_t n_write) { const void *cur = buf; const void *end = buf + n_write; while (cur < end) { const void *skip_span = MemSpan(cur, 0, end - cur); if (skip_span > cur) { if (lseek(dd, skip_span - cur, SEEK_CUR) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying to '%s' from network '%s'", destination, GetErrorStr()); return false; } cur = skip_span; } const void *copy_span = MemSpanInverse(cur, 0, end - cur); if (copy_span > cur) { if (FullWrite(dd, cur, copy_span - cur) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying to '%s' from network '%s'", destination, GetErrorStr()); return false; } cur = copy_span; } } return true; } int CFENGINE_PORT = 5308; char CFENGINE_PORT_STR[16] = "5308"; void DetermineCfenginePort() { struct servent *server; assert(sizeof(CFENGINE_PORT_STR) >= PRINTSIZE(CFENGINE_PORT)); /* ... but we leave more space, as service names can be longer */ errno = 0; if ((server = getservbyname(CFENGINE_SERVICE, "tcp")) != NULL) { CFENGINE_PORT = ntohs(server->s_port); snprintf(CFENGINE_PORT_STR, sizeof(CFENGINE_PORT_STR), "%d", CFENGINE_PORT); } else { if (errno == 0) { Log(LOG_LEVEL_VERBOSE, "No registered cfengine service, using default"); } else { Log(LOG_LEVEL_VERBOSE, "Unable to query services database, using default. (getservbyname: %s)", GetErrorStr()); } } Log(LOG_LEVEL_VERBOSE, "Setting cfengine default port to %d", CFENGINE_PORT); } /** * @return 1 success, 0 auth/ID error, -1 other error */ int TLSConnect(ConnectionInfo *conn_info, bool trust_server, const char *ipaddr, const char *username) { int ret; ret = TLSTry(conn_info); if (ret == -1) { return -1; } /* TODO username is local, fix. */ ret = TLSVerifyPeer(conn_info, ipaddr, username); if (ret == -1) /* error */ { return -1; } if (ret == 1) { Log(LOG_LEVEL_VERBOSE, "Server is TRUSTED, received key %s MATCHES stored one.", ConnectionInfoPrintableKeyHash(conn_info)); } else /* ret == 0 */ { if (trust_server) /* We're most probably bootstrapping. */ { Log(LOG_LEVEL_NOTICE, "Trusting new key: %s", ConnectionInfoPrintableKeyHash(conn_info)); SavePublicKey(username, ConnectionInfoPrintableKeyHash(conn_info), KeyRSA(ConnectionInfoKey(conn_info))); } else { Log(LOG_LEVEL_ERR, "TRUST FAILED, server presented an untrusted key, dropping connection!"); Log(LOG_LEVEL_ERR, "Rebootstrap the client if you really want to start trusting this new key"); return -1; } } /* TLS CONNECTION IS ESTABLISHED, negotiate protocol version and send * identification data. */ ret = TLSClientIdentificationDialog(conn_info, username); return ret; } /** * @NOTE if #flags.protocol_version is CF_PROTOCOL_UNDEFINED, then classic * protocol is used by default. */ AgentConnection *ServerConnection(const char *server, const char *port, unsigned int connect_timeout, ConnectionFlags flags, int *err) { AgentConnection *conn = NULL; int ret; *err = 0; conn = NewAgentConn(server); conn->flags = flags; #if !defined(__MINGW32__) signal(SIGPIPE, SIG_IGN); sigset_t signal_mask; sigemptyset(&signal_mask); sigaddset(&signal_mask, SIGPIPE); pthread_sigmask(SIG_BLOCK, &signal_mask, NULL); /* FIXME: username is local */ GetCurrentUserName(conn->username, CF_SMALLBUF); #else /* Always say "root" as username from windows. */ snprintf(conn->username, CF_SMALLBUF, "root"); #endif if (port == NULL || *port == '\0') { port = CFENGINE_PORT_STR; } char txtaddr[CF_MAX_IP_LEN] = ""; conn->conn_info->sd = SocketConnect(server, port, connect_timeout, flags.force_ipv4, txtaddr, sizeof(txtaddr)); if (conn->conn_info->sd == -1) { Log(LOG_LEVEL_INFO, "No server is responding on this port"); DisconnectServer(conn); *err = -1; return NULL; } assert(sizeof(conn->remoteip) >= sizeof(txtaddr)); strcpy(conn->remoteip, txtaddr); switch (flags.protocol_version) { case CF_PROTOCOL_TLS: /* Set the version to request during protocol negotiation. After * TLSConnect() it will have the version we finally ended up with. */ conn->conn_info->type = CF_PROTOCOL_LATEST; ret = TLSConnect(conn->conn_info, flags.trust_server, conn->remoteip, conn->username); if (ret == -1) /* Error */ { DisconnectServer(conn); *err = -1; return NULL; } else if (ret == 0) /* Auth/ID error */ { DisconnectServer(conn); errno = EPERM; *err = -2; return NULL; } assert(ret == 1); ConnectionInfoSetConnectionStatus(conn->conn_info, CF_CONNECTION_ESTABLISHED); LastSaw1(conn->remoteip, ConnectionInfoPrintableKeyHash(conn->conn_info), LAST_SEEN_ROLE_CONNECT); break; case CF_PROTOCOL_UNDEFINED: case CF_PROTOCOL_CLASSIC: conn->conn_info->type = CF_PROTOCOL_CLASSIC; conn->encryption_type = CfEnterpriseOptions(); if (!IdentifyAgent(conn->conn_info)) { Log(LOG_LEVEL_ERR, "Id-authentication for '%s' failed", VFQNAME); errno = EPERM; DisconnectServer(conn); *err = -2; // auth err return NULL; } if (!AuthenticateAgent(conn, flags.trust_server)) { Log(LOG_LEVEL_ERR, "Authentication dialogue with '%s' failed", server); errno = EPERM; DisconnectServer(conn); *err = -2; // auth err return NULL; } ConnectionInfoSetConnectionStatus(conn->conn_info, CF_CONNECTION_ESTABLISHED); break; default: ProgrammingError("ServerConnection: ProtocolVersion %d!", flags.protocol_version); } conn->authenticated = true; return conn; } /*********************************************************************/ void DisconnectServer(AgentConnection *conn) { /* Socket needs to be closed even after SSL_shutdown. */ if (ConnectionInfoSocket(conn->conn_info) >= 0) /* Not INVALID or OFFLINE */ { if (ConnectionInfoProtocolVersion(conn->conn_info) >= CF_PROTOCOL_TLS && ConnectionInfoSSL(conn->conn_info) != NULL) { SSL_shutdown(ConnectionInfoSSL(conn->conn_info)); } cf_closesocket(ConnectionInfoSocket(conn->conn_info)); ConnectionInfoSetSocket(conn->conn_info, SOCKET_INVALID); Log(LOG_LEVEL_VERBOSE, "Connection to %s is closed", conn->remoteip); } DeleteAgentConn(conn); } /*********************************************************************/ int cf_remote_stat(const char *file, struct stat *buf, const char *stattype, bool encrypt, AgentConnection *conn) /* If a link, this reads readlink and sends it back in the same package. It then caches the value for each copy command */ { char sendbuffer[CF_BUFSIZE]; char recvbuffer[CF_BUFSIZE]; char in[CF_BUFSIZE], out[CF_BUFSIZE]; int ret, tosend, cipherlen; time_t tloc; memset(recvbuffer, 0, CF_BUFSIZE); if (strlen(file) > CF_BUFSIZE - 30) { Log(LOG_LEVEL_ERR, "Filename too long"); return -1; } ret = CacheStat(file, buf, stattype, conn); if (ret != 1) { return ret; } if ((tloc = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_ERR, "Couldn't read system clock"); } sendbuffer[0] = '\0'; /* We encrypt only for CLASSIC protocol. The TLS protocol is always over * encrypted layer, so it does not support encrypted (S*) commands. */ encrypt = encrypt && (ConnectionInfoProtocolVersion(conn->conn_info) == CF_PROTOCOL_CLASSIC); if (encrypt) { if (conn->session_key == NULL) { Log(LOG_LEVEL_ERR, "Cannot do encrypted copy without keys (use cf-key)"); return -1; } snprintf(in, CF_BUFSIZE - 1, "SYNCH %jd STAT %s", (intmax_t) tloc, file); cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + 1); snprintf(sendbuffer, CF_BUFSIZE - 1, "SSYNCH %d", cipherlen); memcpy(sendbuffer + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; } else { snprintf(sendbuffer, CF_BUFSIZE, "SYNCH %jd STAT %s", (intmax_t) tloc, file); tosend = strlen(sendbuffer); } if (SendTransaction(conn->conn_info, sendbuffer, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_INFO, "Transmission failed/refused talking to %.255s:%.255s. (stat: %s)", conn->this_server, file, GetErrorStr()); return -1; } if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1) { /* TODO mark connection in the cache as closed. */ return -1; } if (strstr(recvbuffer, "unsynchronized")) { Log(LOG_LEVEL_ERR, "Clocks differ too much to do copy by date (security), server reported: %s", recvbuffer + strlen("BAD: ")); return -1; } if (BadProtoReply(recvbuffer)) { Log(LOG_LEVEL_VERBOSE, "Server returned error: %s", recvbuffer + strlen("BAD: ")); errno = EPERM; return -1; } if (OKProtoReply(recvbuffer)) { Stat cfst; // use intmax_t here to provide enough space for large values coming over the protocol intmax_t d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12 = 0, d13 = 0; ret = sscanf(recvbuffer, "OK: " "%1" PRIdMAX // 01 cfst.cf_type " %5" PRIdMAX // 02 cfst.cf_mode " %14" PRIdMAX // 03 cfst.cf_lmode " %14" PRIdMAX // 04 cfst.cf_uid " %14" PRIdMAX // 05 cfst.cf_gid " %18" PRIdMAX // 06 cfst.cf_size " %14" PRIdMAX // 07 cfst.cf_atime " %14" PRIdMAX // 08 cfst.cf_mtime " %14" PRIdMAX // 09 cfst.cf_ctime " %1" PRIdMAX // 10 cfst.cf_makeholes " %14" PRIdMAX // 11 cfst.cf_ino " %14" PRIdMAX // 12 cfst.cf_nlink " %18" PRIdMAX, // 13 cfst.cf_dev &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13); if (ret < 13) { Log(LOG_LEVEL_ERR, "Cannot read SYNCH reply from '%s', only %d/13 items parsed", conn->remoteip, ret ); return -1; } cfst.cf_type = (FileType) d1; cfst.cf_mode = (mode_t) d2; cfst.cf_lmode = (mode_t) d3; cfst.cf_uid = (uid_t) d4; cfst.cf_gid = (gid_t) d5; cfst.cf_size = (off_t) d6; cfst.cf_atime = (time_t) d7; cfst.cf_mtime = (time_t) d8; cfst.cf_ctime = (time_t) d9; cfst.cf_makeholes = (char) d10; cfst.cf_ino = d11; cfst.cf_nlink = d12; cfst.cf_dev = (dev_t)d13; /* Use %?d here to avoid memory overflow attacks */ memset(recvbuffer, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1) { /* TODO mark connection in the cache as closed. */ return -1; } if (strlen(recvbuffer) > 3) { cfst.cf_readlink = xstrdup(recvbuffer + 3); } else { cfst.cf_readlink = NULL; } switch (cfst.cf_type) { case FILE_TYPE_REGULAR: cfst.cf_mode |= (mode_t) S_IFREG; break; case FILE_TYPE_DIR: cfst.cf_mode |= (mode_t) S_IFDIR; break; case FILE_TYPE_CHAR_: cfst.cf_mode |= (mode_t) S_IFCHR; break; case FILE_TYPE_FIFO: cfst.cf_mode |= (mode_t) S_IFIFO; break; case FILE_TYPE_SOCK: cfst.cf_mode |= (mode_t) S_IFSOCK; break; case FILE_TYPE_BLOCK: cfst.cf_mode |= (mode_t) S_IFBLK; break; case FILE_TYPE_LINK: cfst.cf_mode |= (mode_t) S_IFLNK; break; } cfst.cf_filename = xstrdup(file); cfst.cf_server = xstrdup(conn->this_server); cfst.cf_failed = false; if (cfst.cf_lmode != 0) { cfst.cf_lmode |= (mode_t) S_IFLNK; } NewClientCache(&cfst, conn); if ((cfst.cf_lmode != 0) && (strcmp(stattype, "link") == 0)) { buf->st_mode = cfst.cf_lmode; } else { buf->st_mode = cfst.cf_mode; } buf->st_uid = cfst.cf_uid; buf->st_gid = cfst.cf_gid; buf->st_size = cfst.cf_size; buf->st_mtime = cfst.cf_mtime; buf->st_ctime = cfst.cf_ctime; buf->st_atime = cfst.cf_atime; buf->st_ino = cfst.cf_ino; buf->st_dev = cfst.cf_dev; buf->st_nlink = cfst.cf_nlink; return 0; } Log(LOG_LEVEL_ERR, "Transmission refused or failed statting '%s', got '%s'", file, recvbuffer); errno = EPERM; return -1; } /*********************************************************************/ Item *RemoteDirList(const char *dirname, bool encrypt, AgentConnection *conn) { char sendbuffer[CF_BUFSIZE]; char recvbuffer[CF_BUFSIZE]; char in[CF_BUFSIZE]; char out[CF_BUFSIZE]; int n, cipherlen = 0, tosend; char *sp; Item *files = NULL; Item *ret = NULL; if (strlen(dirname) > CF_BUFSIZE - 20) { Log(LOG_LEVEL_ERR, "Directory name too long"); return NULL; } /* We encrypt only for CLASSIC protocol. The TLS protocol is always over * encrypted layer, so it does not support encrypted (S*) commands. */ encrypt = encrypt && (ConnectionInfoProtocolVersion(conn->conn_info) == CF_PROTOCOL_CLASSIC); if (encrypt) { if (conn->session_key == NULL) { Log(LOG_LEVEL_ERR, "Cannot do encrypted copy without keys (use cf-key)"); return NULL; } snprintf(in, CF_BUFSIZE, "OPENDIR %s", dirname); cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + 1); snprintf(sendbuffer, CF_BUFSIZE - 1, "SOPENDIR %d", cipherlen); memcpy(sendbuffer + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; } else { snprintf(sendbuffer, CF_BUFSIZE, "OPENDIR %s", dirname); tosend = strlen(sendbuffer); } if (SendTransaction(conn->conn_info, sendbuffer, tosend, CF_DONE) == -1) { return NULL; } while (true) { if ((n = ReceiveTransaction(conn->conn_info, recvbuffer, NULL)) == -1) { /* TODO mark connection in the cache as closed. */ return NULL; } if (n == 0) { break; } if (encrypt) { memcpy(in, recvbuffer, n); DecryptString(conn->encryption_type, in, recvbuffer, conn->session_key, n); } if (FailedProtoReply(recvbuffer)) { Log(LOG_LEVEL_INFO, "Network access to '%s:%s' denied", conn->this_server, dirname); return NULL; } if (BadProtoReply(recvbuffer)) { Log(LOG_LEVEL_INFO, "%s", recvbuffer + strlen("BAD: ")); return NULL; } for (sp = recvbuffer; *sp != '\0'; sp++) { Item *ip; if (strncmp(sp, CFD_TERMINATOR, strlen(CFD_TERMINATOR)) == 0) /* End transmission */ { return ret; } ip = xcalloc(1, sizeof(Item)); ip->name = (char *) AllocateDirentForFilename(sp); if (files == NULL) /* First element */ { ret = ip; files = ip; } else { files->next = ip; files = ip; } while (*sp != '\0') { sp++; } } } return ret; } /*********************************************************************/ static void NewClientCache(Stat *data, AgentConnection *conn) { Stat *sp = xmemdup(data, sizeof(Stat)); sp->next = conn->cache; conn->cache = sp; } const Stat *ClientCacheLookup(AgentConnection *conn, const char *server_name, const char *file_name) { for (const Stat *sp = conn->cache; sp != NULL; sp = sp->next) { if (strcmp(server_name, sp->cf_server) == 0 && strcmp(file_name, sp->cf_filename) == 0) { return sp; } } return NULL; } int CompareHashNet(const char *file1, const char *file2, bool encrypt, AgentConnection *conn) { unsigned char d[EVP_MAX_MD_SIZE + 1]; char *sp, sendbuffer[CF_BUFSIZE], recvbuffer[CF_BUFSIZE], in[CF_BUFSIZE], out[CF_BUFSIZE]; int i, tosend, cipherlen; HashFile(file2, d, CF_DEFAULT_DIGEST); memset(recvbuffer, 0, CF_BUFSIZE); /* We encrypt only for CLASSIC protocol. The TLS protocol is always over * encrypted layer, so it does not support encrypted (S*) commands. */ encrypt = encrypt && (ConnectionInfoProtocolVersion(conn->conn_info) == CF_PROTOCOL_CLASSIC); if (encrypt) { snprintf(in, CF_BUFSIZE, "MD5 %s", file1); sp = in + strlen(in) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { *sp++ = d[i]; } cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN); snprintf(sendbuffer, CF_BUFSIZE, "SMD5 %d", cipherlen); memcpy(sendbuffer + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; } else { snprintf(sendbuffer, CF_BUFSIZE, "MD5 %s", file1); sp = sendbuffer + strlen(sendbuffer) + CF_SMALL_OFFSET; for (i = 0; i < CF_DEFAULT_DIGEST_LEN; i++) { *sp++ = d[i]; } tosend = strlen(sendbuffer) + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN; } if (SendTransaction(conn->conn_info, sendbuffer, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Failed send. (SendTransaction: %s)", GetErrorStr()); return false; } if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1) { /* TODO mark connection in the cache as closed. */ Log(LOG_LEVEL_ERR, "Failed receive. (ReceiveTransaction: %s)", GetErrorStr()); Log(LOG_LEVEL_VERBOSE, "No answer from host, assuming checksum ok to avoid remote copy for now..."); return false; } if (strcmp(CFD_TRUE, recvbuffer) == 0) { return true; /* mismatch */ } else { return false; } /* Not reached */ } /*********************************************************************/ int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size, AgentConnection *conn) { int dd, blocksize = 2048, n_read = 0, towrite, plainlen, more = true, finlen, cnt = 0; int tosend, cipherlen = 0; char *buf, in[CF_BUFSIZE], out[CF_BUFSIZE], workbuf[CF_BUFSIZE], cfchangedstr[265]; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; long n_read_total = 0; EVP_CIPHER_CTX crypto_ctx; snprintf(cfchangedstr, 255, "%s%s", CF_CHANGEDSTR1, CF_CHANGEDSTR2); if ((strlen(dest) > CF_BUFSIZE - 20)) { Log(LOG_LEVEL_ERR, "Filename too long"); return false; } unlink(dest); /* To avoid link attacks */ if ((dd = safe_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, 0600)) == -1) { Log(LOG_LEVEL_ERR, "Copy from server '%s' to destination '%s' failed (open: %s)", conn->this_server, dest, GetErrorStr()); unlink(dest); return false; } if (size == 0) { // No sense in copying an empty file close(dd); return true; } workbuf[0] = '\0'; EVP_CIPHER_CTX_init(&crypto_ctx); snprintf(in, CF_BUFSIZE - CF_PROTO_OFFSET, "GET dummykey %s", source); cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + 1); snprintf(workbuf, CF_BUFSIZE, "SGET %4d %4d", cipherlen, blocksize); memcpy(workbuf + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; /* Send proposition C0 - query */ if (SendTransaction(conn->conn_info, workbuf, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Couldn't send data. (SendTransaction: %s)", GetErrorStr()); close(dd); return false; } buf = xmalloc(CF_BUFSIZE + sizeof(int)); n_read_total = 0; while (more) { if ((cipherlen = ReceiveTransaction(conn->conn_info, buf, &more)) == -1) { free(buf); return false; } cnt++; /* If the first thing we get is an error message, break. */ if ((n_read_total == 0) && (strncmp(buf + CF_INBAND_OFFSET, CF_FAILEDSTR, strlen(CF_FAILEDSTR)) == 0)) { Log(LOG_LEVEL_INFO, "Network access to '%s:%s' denied", conn->this_server, source); close(dd); free(buf); return false; } if (strncmp(buf + CF_INBAND_OFFSET, cfchangedstr, strlen(cfchangedstr)) == 0) { Log(LOG_LEVEL_INFO, "Source '%s:%s' changed while copying", conn->this_server, source); close(dd); free(buf); return false; } EVP_DecryptInit_ex(&crypto_ctx, CfengineCipher(CfEnterpriseOptions()), NULL, conn->session_key, iv); if (!EVP_DecryptUpdate(&crypto_ctx, workbuf, &plainlen, buf, cipherlen)) { close(dd); free(buf); return false; } if (!EVP_DecryptFinal_ex(&crypto_ctx, workbuf + plainlen, &finlen)) { close(dd); free(buf); return false; } towrite = n_read = plainlen + finlen; n_read_total += n_read; if (!FSWrite(dest, dd, workbuf, towrite)) { Log(LOG_LEVEL_ERR, "Local disk write failed copying '%s:%s' to '%s:%s'", conn->this_server, source, dest, GetErrorStr()); if (conn) { conn->error = true; } free(buf); unlink(dest); close(dd); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } } /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. Write a null character and truncate it again. */ if (ftruncate(dd, n_read_total) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying '%s' from network '%s'", dest, GetErrorStr()); free(buf); unlink(dest); close(dd); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } close(dd); free(buf); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return true; } int CopyRegularFileNet(const char *source, const char *dest, off_t size, bool encrypt, AgentConnection *conn) { int dd, buf_size, n_read = 0, toget, towrite; int tosend, value; char *buf, workbuf[CF_BUFSIZE], cfchangedstr[265]; off_t n_read_total = 0; EVP_CIPHER_CTX crypto_ctx; /* We encrypt only for CLASSIC protocol. The TLS protocol is always over * encrypted layer, so it does not support encrypted (S*) commands. */ encrypt = encrypt && (ConnectionInfoProtocolVersion(conn->conn_info) == CF_PROTOCOL_CLASSIC); if (encrypt) { return EncryptCopyRegularFileNet(source, dest, size, conn); } snprintf(cfchangedstr, 255, "%s%s", CF_CHANGEDSTR1, CF_CHANGEDSTR2); if ((strlen(dest) > CF_BUFSIZE - 20)) { Log(LOG_LEVEL_ERR, "Filename too long"); return false; } unlink(dest); /* To avoid link attacks */ if ((dd = safe_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, 0600)) == -1) { Log(LOG_LEVEL_ERR, "Copy from server '%s' to destination '%s' failed (open: %s)", conn->this_server, dest, GetErrorStr()); unlink(dest); return false; } workbuf[0] = '\0'; buf_size = 2048; /* Send proposition C0 */ snprintf(workbuf, CF_BUFSIZE, "GET %d %s", buf_size, source); tosend = strlen(workbuf); if (SendTransaction(conn->conn_info, workbuf, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Couldn't send data"); close(dd); return false; } buf = xmalloc(CF_BUFSIZE + sizeof(int)); /* Note CF_BUFSIZE not buf_size !! */ Log(LOG_LEVEL_VERBOSE, "Copying remote file '%s:%s', expecting %jd bytes", conn->this_server, source, (intmax_t)size); n_read_total = 0; while (n_read_total < size) { if ((size - n_read_total) >= buf_size) { toget = towrite = buf_size; } else if (size != 0) { towrite = (size - n_read_total); toget = towrite; } else { toget = towrite = 0; } /* Stage C1 - receive */ switch(ConnectionInfoProtocolVersion(conn->conn_info)) { case CF_PROTOCOL_CLASSIC: n_read = RecvSocketStream(ConnectionInfoSocket(conn->conn_info), buf, toget); break; case CF_PROTOCOL_TLS: n_read = TLSRecv(ConnectionInfoSSL(conn->conn_info), buf, toget); break; default: UnexpectedError("CopyRegularFileNet: ProtocolVersion %d!", ConnectionInfoProtocolVersion(conn->conn_info)); n_read = -1; } if (n_read == -1) { /* This may happen on race conditions, * where the file has shrunk since we asked for its size in SYNCH ... STAT source */ Log(LOG_LEVEL_ERR, "Error in client-server stream (has %s:%s shrunk?)", conn->this_server, source); close(dd); free(buf); return false; } /* If the first thing we get is an error message, break. */ if ((n_read_total == 0) && (strncmp(buf, CF_FAILEDSTR, strlen(CF_FAILEDSTR)) == 0)) { Log(LOG_LEVEL_INFO, "Network access to '%s:%s' denied", conn->this_server, source); close(dd); free(buf); return false; } if (strncmp(buf, cfchangedstr, strlen(cfchangedstr)) == 0) { Log(LOG_LEVEL_INFO, "Source '%s:%s' changed while copying", conn->this_server, source); close(dd); free(buf); return false; } value = -1; /* Check for mismatch between encryption here and on server - can lead to misunderstanding */ sscanf(buf, "t %d", &value); if ((value > 0) && (strncmp(buf + CF_INBAND_OFFSET, "BAD: ", 5) == 0)) { Log(LOG_LEVEL_INFO, "Network access to cleartext '%s:%s' denied", conn->this_server, source); close(dd); free(buf); return false; } if (!FSWrite(dest, dd, buf, n_read)) { Log(LOG_LEVEL_ERR, "Local disk write failed copying '%s:%s' to '%s'. (FSWrite: %s)", conn->this_server, source, dest, GetErrorStr()); if (conn) { conn->error = true; } free(buf); unlink(dest); close(dd); FlushFileStream(ConnectionInfoSocket(conn->conn_info), size - n_read_total); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } n_read_total += towrite; /* n_read; */ } /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. Write a null character and truncate it again. */ if (ftruncate(dd, n_read_total) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying '%s' from network '%s'", dest, GetErrorStr()); free(buf); unlink(dest); close(dd); FlushFileStream(ConnectionInfoSocket(conn->conn_info), size - n_read_total); return false; } close(dd); free(buf); return true; } /*********************************************************************/ bool ServerOffline(const char *server) { char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, server, sizeof(ipaddr)) == -1) { /* Ignore the error for now, resolution will probably fail again soon... TODO return true? */ return false; } ThreadLock(&cft_serverlist); Seq *srvlist_tmp = GetGlobalServerList(); ThreadUnlock(&cft_serverlist); for (size_t i = 0; i < SeqLength(srvlist_tmp); i++) { ServerItem *svp = SeqAt(srvlist_tmp, i); if (svp == NULL) { ProgrammingError("SERVERLIST had NULL ServerItem!"); } if (strcmp(ipaddr, svp->server) == 0) { if (svp->conn == NULL) { ProgrammingError("ServerOffline:" " NULL connection in SERVERLIST for %s!", ipaddr); } if (ConnectionInfoSocket(svp->conn->conn_info) == CF_COULD_NOT_CONNECT) return true; else return false; } } return false; } AgentConnection *GetIdleConnectionToServer(const char *server) { char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, server, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_WARNING, "Could not resolve: %s", server); return NULL; } ThreadLock(&cft_serverlist); Seq *srvlist_tmp = GetGlobalServerList(); ThreadUnlock(&cft_serverlist); for (size_t i = 0; i < SeqLength(srvlist_tmp); i++) { ServerItem *svp = SeqAt(srvlist_tmp, i); if (svp == NULL) { ProgrammingError("SERVERLIST had NULL ServerItem!"); } if ((strcmp(ipaddr, svp->server) == 0)) { if (svp->conn == NULL) { ProgrammingError("GetIdleConnectionToServer:" " NULL connection in SERVERLIST for %s!", ipaddr); } if (svp->busy) { Log(LOG_LEVEL_VERBOSE, "GetIdleConnectionToServer:" " connection to '%s' seems to be busy.", ipaddr); } else if (ConnectionInfoSocket(svp->conn->conn_info) == CF_COULD_NOT_CONNECT) { Log(LOG_LEVEL_VERBOSE, "GetIdleConnectionToServer:" " connection to '%s' is marked as offline.", ipaddr); } else if (ConnectionInfoSocket(svp->conn->conn_info) > 0) { Log(LOG_LEVEL_VERBOSE, "GetIdleConnectionToServer:" " found connection to '%s' already open and ready.", ipaddr); svp->busy = true; return svp->conn; } else { Log(LOG_LEVEL_VERBOSE, " connection to '%s' is in unknown state %d!", ipaddr, ConnectionInfoSocket(svp->conn->conn_info)); } } } Log(LOG_LEVEL_VERBOSE, "GetIdleConnectionToServer:" " no existing connection to '%s' is established.", ipaddr); return NULL; } /*********************************************************************/ void ServerNotBusy(AgentConnection *conn) { ThreadLock(&cft_serverlist); Seq *srvlist_tmp = GetGlobalServerList(); ThreadUnlock(&cft_serverlist); for (size_t i = 0; i < SeqLength(srvlist_tmp); i++) { ServerItem *svp = SeqAt(srvlist_tmp, i); if (svp->conn == conn) { svp->busy = false; Log(LOG_LEVEL_DEBUG, "Existing connection just became free..."); return; } } ProgrammingError("ServerNotBusy: No connection found!"); } /*********************************************************************/ void MarkServerOffline(const char *server) /* Unable to contact the server so don't waste time trying for other connections, mark it offline */ { AgentConnection *conn = NULL; char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, server, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_ERR, "Could not resolve: %s", server); return; } ThreadLock(&cft_serverlist); Seq *srvlist_tmp = GetGlobalServerList(); for (size_t i = 0; i < SeqLength(srvlist_tmp); i++) { ServerItem *svp = SeqAt(srvlist_tmp, i); if (svp == NULL) { ProgrammingError("SERVERLIST had NULL ServerItem!"); } conn = svp->conn; if (strcmp(ipaddr, svp->server) == 0) /* TODO assert conn->remoteip == svp->server? Why do we need both? */ { /* Found it, mark offline */ ConnectionInfoSetSocket(conn->conn_info, CF_COULD_NOT_CONNECT); ThreadUnlock(&cft_serverlist); return; } } /* If no existing connection, create one and mark it unconnectable. */ ServerItem *svp = xmalloc(sizeof(*svp)); svp->server = xstrdup(ipaddr); svp->busy = false; svp->conn = NewAgentConn(ipaddr); ConnectionInfoSetProtocolVersion(svp->conn->conn_info, CF_PROTOCOL_CLASSIC); ConnectionInfoSetConnectionStatus(svp->conn->conn_info, CF_CONNECTION_NOT_ESTABLISHED); ConnectionInfoSetSocket(svp->conn->conn_info, CF_COULD_NOT_CONNECT); SeqAppend(srvlist_tmp, svp); ThreadUnlock(&cft_serverlist); } /*********************************************************************/ void CacheServerConnection(AgentConnection *conn, const char *server) /* First time we open a connection, so store it */ { char ipaddr[CF_MAX_IP_LEN]; if (Hostname2IPString(ipaddr, server, sizeof(ipaddr)) == -1) { Log(LOG_LEVEL_ERR, "Failed to resolve: %s", server); return; } ServerItem *svp = xmalloc(sizeof(*svp)); svp->server = xstrdup(ipaddr); svp->busy = true; svp->conn = conn; ThreadLock(&cft_serverlist); SeqAppend(GetGlobalServerList(), svp); ThreadUnlock(&cft_serverlist); } /*********************************************************************/ static int CacheStat(const char *file, struct stat *statbuf, const char *stattype, AgentConnection *conn) { Stat *sp; for (sp = conn->cache; sp != NULL; sp = sp->next) { if ((strcmp(conn->this_server, sp->cf_server) == 0) && (strcmp(file, sp->cf_filename) == 0)) { if (sp->cf_failed) /* cached failure from cfopendir */ { errno = EPERM; return -1; } if ((strcmp(stattype, "link") == 0) && (sp->cf_lmode != 0)) { statbuf->st_mode = sp->cf_lmode; } else { statbuf->st_mode = sp->cf_mode; } statbuf->st_uid = sp->cf_uid; statbuf->st_gid = sp->cf_gid; statbuf->st_size = sp->cf_size; statbuf->st_atime = sp->cf_atime; statbuf->st_mtime = sp->cf_mtime; statbuf->st_ctime = sp->cf_ctime; statbuf->st_ino = sp->cf_ino; statbuf->st_dev = sp->cf_dev; statbuf->st_nlink = sp->cf_nlink; return 0; } } return 1; } /*********************************************************************/ static void FlushFileStream(int sd, int toget) { int i; char buffer[2]; Log(LOG_LEVEL_VERBOSE, "Flushing rest of file...%d bytes", toget); for (i = 0; i < toget; i++) { recv(sd, buffer, 1, 0); /* flush to end of current file */ } } /*********************************************************************/ void ConnectionsInit(void) { ThreadLock(&cft_serverlist); SeqClear(GetGlobalServerList()); ThreadUnlock(&cft_serverlist); } /*********************************************************************/ /* No locking taking place in here, so make sure you've finalised all threads * before calling this one! */ void ConnectionsCleanup(void) { Seq *srvlist_tmp = GetGlobalServerList(); for (size_t i = 0; i < SeqLength(srvlist_tmp); i++) { ServerItem *svp = SeqAt(srvlist_tmp, i); if (svp == NULL) { ProgrammingError("SERVERLIST had NULL ServerItem!"); } if (svp->conn == NULL) { ProgrammingError("ConnectionsCleanup:" "NULL connection in SERVERLIST!"); } DisconnectServer(svp->conn); } SeqClear(srvlist_tmp); } cfengine-3.6.2/libcfnet/Makefile.am0000664000175100017510000000100612411001073016622 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcfnet.la AM_CPPFLAGS = $(OPENSSL_CPPFLAGS) AM_CPPFLAGS += $(PCRE_CPPFLAGS) AM_CPPFLAGS += -I$(top_srcdir)/libutils # platform.h AM_CPPFLAGS += -I$(top_srcdir)/libpromises # cf3.defs.h libcfnet_la_SOURCES = \ misc.c \ net.c net.h \ communication.c communication.h \ client_protocol.c client_protocol.h cfnet.h\ client_code.c client_code.h \ classic.c classic.h \ tls_client.c tls_client.h \ tls_generic.c tls_generic.h \ connection_info.c connection_info.h \ key.c key.h cfengine-3.6.2/libcfnet/net.h0000644000175100017510000000335612321511215015541 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ /* Low Level networking routines. */ #ifndef CFENGINE_NET_H #define CFENGINE_NET_H #include int SendTransaction(const ConnectionInfo *conn_info, const char *buffer, int len, char status); int ReceiveTransaction(const ConnectionInfo *conn_info, char *buffer, int *more); int SetReceiveTimeout(int fd, unsigned long ms); int SocketConnect(const char *host, const char *port, unsigned int connect_timeout, bool force_ipv4, char *txtaddr, size_t txtaddr_size); /** * @NOTE DO NOT USE THIS FUNCTION. The only reason it is non-static is because * of a separate implementation for windows in Enterprise. */ bool TryConnect(int sd, unsigned long timeout_ms, const struct sockaddr *sa, socklen_t sa_len); #endif cfengine-3.6.2/libcfnet/key.c0000644000175100017510000000474012352022221015532 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include struct Key { RSA *key; Hash *hash; }; Key *KeyNew(RSA *rsa, HashMethod method) { if (!rsa) { return NULL; } Key *key = xmalloc (sizeof(Key)); key->key = rsa; /* Hash the key */ key->hash = HashNewFromKey(rsa, method); if (key->hash == NULL) { free (key); return NULL; } return key; } void KeyDestroy(Key **key) { if (!key || !*key) { return; } if ((*key)->key) { RSA_free((*key)->key); } HashDestroy(&(*key)->hash); free (*key); *key = NULL; } RSA *KeyRSA(const Key *key) { return key ? key->key : NULL; } const unsigned char *KeyBinaryHash(const Key *key, unsigned int *length) { if (!key || !length) { return NULL; } return HashData(key->hash, length); } const char *KeyPrintableHash(const Key *key) { return key ? HashPrintable(key->hash) : NULL; } HashMethod KeyHashMethod(const Key *key) { return key ? HashType(key->hash) : HASH_METHOD_NONE; } int KeySetHashMethod(Key *key, HashMethod method) { if (!key) { return -1; } /* We calculate the new hash before changing the value, in case there is an error. */ Hash *hash = NULL; hash = HashNewFromKey(key->key, method); if (hash == NULL) { return -1; } if (key->hash) { HashDestroy(&key->hash); } key->hash = hash; return 0; } const Hash *KeyData(Key *key) { return key ? key->hash : NULL; } cfengine-3.6.2/libcfnet/tls_client.c0000664000175100017510000002036412411001073017102 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include /* SendTransaction, ReceiveTransaction */ /* TODO move crypto.h to libutils */ #include /* LoadSecretKeys */ extern RSA *PRIVKEY, *PUBKEY; extern char CFWORKDIR[]; /* Global SSL context for client connections over new TLS protocol. */ static SSL_CTX *SSLCLIENTCONTEXT = NULL; /* GLOBAL_X */ static X509 *SSLCLIENTCERT = NULL; /* GLOBAL_X */ /** * @warning Make sure you've called CryptoInitialize() first! */ bool TLSClientInitialize() { int ret; static bool is_initialised = false; if (is_initialised) { return true; } if (!TLSGenericInitialize()) { return false; } SSLCLIENTCONTEXT = SSL_CTX_new(SSLv23_client_method()); if (SSLCLIENTCONTEXT == NULL) { Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s", TLSErrorString(ERR_get_error())); goto err1; } TLSSetDefaultOptions(SSLCLIENTCONTEXT); if (PRIVKEY == NULL || PUBKEY == NULL) { Log(CryptoGetMissingKeyLogLevel(), "No public/private key pair is loaded, trying to reload"); LoadSecretKeys(); if (PRIVKEY == NULL || PUBKEY == NULL) { Log(CryptoGetMissingKeyLogLevel(), "No public/private key pair found"); goto err2; } } /* Create cert into memory and load it into SSL context. */ SSLCLIENTCERT = TLSGenerateCertFromPrivKey(PRIVKEY); if (SSLCLIENTCERT == NULL) { Log(LOG_LEVEL_ERR, "Failed to generate in-memory-certificate from private key"); goto err2; } SSL_CTX_use_certificate(SSLCLIENTCONTEXT, SSLCLIENTCERT); ret = SSL_CTX_use_RSAPrivateKey(SSLCLIENTCONTEXT, PRIVKEY); if (ret != 1) { Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s", TLSErrorString(ERR_get_error())); goto err3; } /* Verify cert consistency. */ ret = SSL_CTX_check_private_key(SSLCLIENTCONTEXT); if (ret != 1) { Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s", TLSErrorString(ERR_get_error())); goto err3; } is_initialised = true; return true; err3: X509_free(SSLCLIENTCERT); SSLCLIENTCERT = NULL; err2: SSL_CTX_free(SSLCLIENTCONTEXT); SSLCLIENTCONTEXT = NULL; err1: return false; } void TLSDeInitialize() { if (PUBKEY) { RSA_free(PUBKEY); PUBKEY = NULL; } if (PRIVKEY) { RSA_free(PRIVKEY); PRIVKEY = NULL; } if (SSLCLIENTCERT != NULL) { X509_free(SSLCLIENTCERT); SSLCLIENTCERT = NULL; } if (SSLCLIENTCONTEXT != NULL) { SSL_CTX_free(SSLCLIENTCONTEXT); SSLCLIENTCONTEXT = NULL; } } /** * 1. Receive "CFE_v%d" server hello * 2. Send two lines: one "CFE_v%d" with the protocol version we wish to have, * and another with id, e.g. "IDENTITY USERNAME=blah". * 3. Receive "OK WELCOME" * * @return > 0: success. #conn_info->type has been updated with the negotiated * protocol version. * 0: server denial * -1: error */ int TLSClientIdentificationDialog(ConnectionInfo *conn_info, const char *username) { char line[1024] = ""; int ret; /* Receive CFE_v%d ... That's the first thing the server sends. */ ret = TLSRecvLines(conn_info->ssl, line, sizeof(line)); ProtocolVersion wanted_version; if (conn_info->type == CF_PROTOCOL_UNDEFINED) { /* TODO parse CFE_v%d received and use that version if it's lower. */ wanted_version = CF_PROTOCOL_LATEST; } else { wanted_version = conn_info->type; } /* Send "CFE_v%d cf-agent version". */ char version_string[128]; int len = snprintf(version_string, sizeof(version_string), "CFE_v%d %s %s\n", wanted_version, "cf-agent", VERSION); /* TODO argv[0] */ ret = TLSSend(conn_info->ssl, version_string, len); if (ret != len) { Log(LOG_LEVEL_ERR, "Connection was hung up during identification!"); return -1; } strcpy(line, "IDENTITY"); size_t line_len = strlen(line); if (username != NULL) { ret = snprintf(&line[line_len], sizeof(line) - line_len, " USERNAME=%s", username); if (ret >= sizeof(line) - line_len) { Log(LOG_LEVEL_ERR, "Sending IDENTITY truncated: %s", line); return -1; } line_len += ret; } /* Overwrite the terminating '\0', we don't need it anyway. */ line[line_len] = '\n'; line_len++; ret = TLSSend(conn_info->ssl, line, line_len); if (ret == -1) { Log(LOG_LEVEL_ERR, "Connection was hung up during identification! (2)"); return -1; } /* Server might hang up here, after we sent identification! We * must get the "OK WELCOME" message for everything to be OK. */ static const char OK[] = "OK WELCOME"; size_t OK_len = sizeof(OK) - 1; ret = TLSRecvLines(conn_info->ssl, line, sizeof(line)); if (ret == -1) { Log(LOG_LEVEL_ERR, "Connection was hung up during identification! (3)"); return -1; } if (ret < OK_len || strncmp(line, OK, OK_len) != 0) { Log(LOG_LEVEL_ERR, "Peer did not accept our identity! Responded: %s", line); return 0; } /* Before it contained the protocol version we requested from the server, * now we put in the value that was negotiated. */ conn_info->type = wanted_version; return 1; } /** * We directly initiate a TLS handshake with the server. If the server is old * version (does not speak TLS) the connection will be denied. * @note the socket file descriptor in #conn_info must be connected and *not* * non-blocking * @return -1 in case of error */ int TLSTry(ConnectionInfo *conn_info) { /* SSL Context might not be initialised up to now due to lack of keys, as * they might be generated as part of the policy (e.g. failsafe.cf). */ if (!TLSClientInitialize()) { return -1; } assert(SSLCLIENTCONTEXT != NULL && PRIVKEY != NULL && PUBKEY != NULL); ConnectionInfoSetSSL(conn_info, SSL_new(SSLCLIENTCONTEXT)); SSL *ssl = ConnectionInfoSSL(conn_info); if (ssl == NULL) { Log(LOG_LEVEL_ERR, "SSL_new: %s", TLSErrorString(ERR_get_error())); return -1; } /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn_info); /* Initiate the TLS handshake over the already open TCP socket. */ SSL_set_fd(ssl, ConnectionInfoSocket(conn_info)); int ret = SSL_connect(ssl); if (ret <= 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "Failed to establish TLS connection", ret); return -1; } Log(LOG_LEVEL_VERBOSE, "TLS cipher negotiated: %s, %s", SSL_get_cipher_name(ssl), SSL_get_cipher_version(ssl)); Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust..."); return 0; } cfengine-3.6.2/libcfnet/tls_generic.h0000664000175100017510000000336312400110676017255 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_TLS_GENERIC_H #define CFENGINE_TLS_GENERIC_H #include #include #include /* LogLevel */ extern int CONNECTIONINFO_SSL_IDX; bool TLSGenericInitialize(void); int TLSVerifyCallback(X509_STORE_CTX *ctx, void *arg); int TLSVerifyPeer(ConnectionInfo *conn_info, const char *remoteip, const char *username); X509 *TLSGenerateCertFromPrivKey(RSA *privkey); void TLSLogError(SSL *ssl, LogLevel level, const char *prepend, int code); int TLSSend(SSL *ssl, const char *buffer, int length); int TLSRecv(SSL *ssl, char *buffer, int length); int TLSRecvLines(SSL *ssl, char *buf, size_t buf_size); void TLSSetDefaultOptions(SSL_CTX *ssl_ctx); const char *TLSErrorString(intmax_t errcode); #endif cfengine-3.6.2/libcfnet/connection_info.c0000664000175100017510000000731512411001073020115 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include ConnectionInfo *ConnectionInfoNew(void) { struct ConnectionInfo *info = xcalloc(1, sizeof(struct ConnectionInfo)); info->sd = SOCKET_INVALID; return info; } void ConnectionInfoDestroy(ConnectionInfo **info) { if (!info || !*info) { return; } /* Destroy everything */ if ((*info)->ssl) { SSL_free((*info)->ssl); } KeyDestroy(&(*info)->remote_key); free (*info); *info = NULL; } ProtocolVersion ConnectionInfoProtocolVersion(const ConnectionInfo *info) { return info ? info->type : CF_PROTOCOL_UNDEFINED; } void ConnectionInfoSetProtocolVersion(ConnectionInfo *info, ProtocolVersion version) { if (!info) { return; } switch (version) { case CF_PROTOCOL_UNDEFINED: case CF_PROTOCOL_CLASSIC: case CF_PROTOCOL_TLS: info->type = version; break; default: break; } } ConnectionStatus ConnectionInfoConnectionStatus(const ConnectionInfo *info) { return info ? info->status : CF_CONNECTION_NOT_ESTABLISHED; } void ConnectionInfoSetConnectionStatus(ConnectionInfo *info, ConnectionStatus status) { if (!info) { return; } switch (status) { case CF_CONNECTION_NOT_ESTABLISHED: case CF_CONNECTION_ESTABLISHED: info->status = status; default: break; } } int ConnectionInfoSocket(const ConnectionInfo *info) { return info ? info->sd : -1; } void ConnectionInfoSetSocket(ConnectionInfo *info, int s) { if (!info) { return; } info->sd = s; } SSL *ConnectionInfoSSL(const ConnectionInfo *info) { return info ? info->ssl : NULL; } void ConnectionInfoSetSSL(ConnectionInfo *info, SSL *ssl) { if (!info) { return; } info->ssl = ssl; } const Key *ConnectionInfoKey(const ConnectionInfo *info) { const Key *key = info ? info->remote_key : NULL; return key; } void ConnectionInfoSetKey(ConnectionInfo *info, Key *key) { if (!info) { return; } /* The key can be assigned only once on a session */ if (info->remote_key) { return; } if (!key) { return; } info->remote_key = key; } const unsigned char *ConnectionInfoBinaryKeyHash(ConnectionInfo *info, unsigned int *length) { if (!info) { return NULL; } Key *connection_key = info->remote_key; unsigned int real_length = 0; const char *binary = KeyBinaryHash(connection_key, &real_length); if (length) { *length = real_length; } return binary; } const char *ConnectionInfoPrintableKeyHash(ConnectionInfo *info) { return info ? KeyPrintableHash(info->remote_key) : NULL; } cfengine-3.6.2/libcfnet/client_protocol.h0000664000175100017510000000241312243421446020156 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CLIENT_PROTOCOL_H #define CFENGINE_CLIENT_PROTOCOL_H #include int IdentifyAgent(ConnectionInfo *connection); int AuthenticateAgent(AgentConnection *conn, bool trust_key); int BadProtoReply(char *buf); int OKProtoReply(char *buf); int FailedProtoReply(char *buf); #endif cfengine-3.6.2/libcfnet/net.c0000664000175100017510000003451712411001073015535 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* CF_BUFSIZE */ #include #include /* BINDINTERFACE */ #include #include #include #include #include #include /** * @param len is the number of bytes to send, or 0 if buffer is a * '\0'-terminated string so strlen(buffer) can used. */ int SendTransaction(const ConnectionInfo *conn_info, const char *buffer, int len, char status) { assert(status == CF_MORE || status == CF_DONE); char work[CF_BUFSIZE] = { 0 }; int ret; if (len == 0) { len = strlen(buffer); } if (len > CF_BUFSIZE - CF_INBAND_OFFSET) { Log(LOG_LEVEL_ERR, "SendTransaction: len (%d) > %d - %d", len, CF_BUFSIZE, CF_INBAND_OFFSET); return -1; } snprintf(work, CF_INBAND_OFFSET, "%c %d", status, len); memcpy(work + CF_INBAND_OFFSET, buffer, len); Log(LOG_LEVEL_DEBUG, "SendTransaction header: %s", work); LogRaw(LOG_LEVEL_DEBUG, "SendTransaction data: ", work + CF_INBAND_OFFSET, len); switch(ConnectionInfoProtocolVersion(conn_info)) { case CF_PROTOCOL_CLASSIC: ret = SendSocketStream(ConnectionInfoSocket(conn_info), work, len + CF_INBAND_OFFSET); break; case CF_PROTOCOL_TLS: ret = TLSSend(ConnectionInfoSSL(conn_info), work, len + CF_INBAND_OFFSET); break; default: UnexpectedError("SendTransaction: ProtocolVersion %d!", ConnectionInfoProtocolVersion(conn_info)); ret = -1; } if (ret == -1) return -1; else return 0; } /*************************************************************************/ /** * @return 0 in case of socket closed, -1 in case of other error, or * >0 the number of bytes read. */ int ReceiveTransaction(const ConnectionInfo *conn_info, char *buffer, int *more) { char proto[CF_INBAND_OFFSET + 1] = { 0 }; char status = 'x'; unsigned int len = 0; int ret; /* Get control channel. */ switch(ConnectionInfoProtocolVersion(conn_info)) { case CF_PROTOCOL_CLASSIC: ret = RecvSocketStream(ConnectionInfoSocket(conn_info), proto, CF_INBAND_OFFSET); break; case CF_PROTOCOL_TLS: ret = TLSRecv(ConnectionInfoSSL(conn_info), proto, CF_INBAND_OFFSET); break; default: UnexpectedError("ReceiveTransaction: ProtocolVersion %d!", ConnectionInfoProtocolVersion(conn_info)); ret = -1; } if (ret == -1 || ret == 0) return ret; LogRaw(LOG_LEVEL_DEBUG, "ReceiveTransaction header: ", proto, ret); ret = sscanf(proto, "%c %u", &status, &len); if (ret != 2) { Log(LOG_LEVEL_ERR, "ReceiveTransaction: Bad packet -- bogus header: %s", proto); return -1; } if (len > CF_BUFSIZE - CF_INBAND_OFFSET) { Log(LOG_LEVEL_ERR, "ReceiveTransaction: Bad packet -- too long (len=%d)", len); return -1; } if (status != CF_MORE && status != CF_DONE) { Log(LOG_LEVEL_ERR, "ReceiveTransaction: Bad packet -- bogus header (more='%c')", status); return -1; } if (more != NULL) { switch (status) { case CF_MORE: *more = true; break; case CF_DONE: *more = false; break; default: ProgrammingError("Unreachable, " "bogus headers have already been checked!"); } } /* Get data. */ switch(ConnectionInfoProtocolVersion(conn_info)) { case CF_PROTOCOL_CLASSIC: ret = RecvSocketStream(ConnectionInfoSocket(conn_info), buffer, len); break; case CF_PROTOCOL_TLS: ret = TLSRecv(ConnectionInfoSSL(conn_info), buffer, len); break; default: UnexpectedError("ReceiveTransaction: ProtocolVersion %d!", ConnectionInfoProtocolVersion(conn_info)); ret = -1; } LogRaw(LOG_LEVEL_DEBUG, "ReceiveTransaction data: ", buffer, ret); return ret; } /*************************************************************************/ /** Tries to connect() to server #host, returns the socket descriptor and the IP address that succeeded in #txtaddr. @param #connect_timeout how long to wait for connect(), zero blocks forever @param #txtaddr If connected successfully return the IP connected in textual representation @return Connected socket descriptor or -1 in case of failure. */ int SocketConnect(const char *host, const char *port, unsigned int connect_timeout, bool force_ipv4, char *txtaddr, size_t txtaddr_size) { struct addrinfo *response = NULL, *ap; bool connected = false; int sd = -1; struct addrinfo query = { .ai_family = force_ipv4 ? AF_INET : AF_UNSPEC, .ai_socktype = SOCK_STREAM }; int ret = getaddrinfo(host, port, &query, &response); if (ret != 0) { Log(LOG_LEVEL_INFO, "Unable to find host '%s' service '%s' (%s)", host, port, gai_strerror(ret)); if (response != NULL) { freeaddrinfo(response); } return -1; } for (ap = response; !connected && ap != NULL; ap = ap->ai_next) { /* Convert address to string. */ getnameinfo(ap->ai_addr, ap->ai_addrlen, txtaddr, txtaddr_size, NULL, 0, NI_NUMERICHOST); Log(LOG_LEVEL_VERBOSE, "Connecting to host %s, port %s as address %s", host, port, txtaddr); sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol); if (sd == -1) { Log(LOG_LEVEL_ERR, "Couldn't open a socket to '%s' (socket: %s)", txtaddr, GetErrorStr()); } else { /* Bind socket to specific interface, if requested. */ if (BINDINTERFACE[0] != '\0') { struct addrinfo query2 = { .ai_family = force_ipv4 ? AF_INET : AF_UNSPEC, .ai_socktype = SOCK_STREAM, /* returned address is for bind() */ .ai_flags = AI_PASSIVE }; struct addrinfo *response2 = NULL, *ap2; int ret2 = getaddrinfo(BINDINTERFACE, NULL, &query2, &response2); if (ret2 != 0) { Log(LOG_LEVEL_ERR, "Unable to lookup interface '%s' to bind. (getaddrinfo: %s)", BINDINTERFACE, gai_strerror(ret2)); if (response2 != NULL) { freeaddrinfo(response2); } assert(response); /* first getaddrinfo was successful */ freeaddrinfo(response); cf_closesocket(sd); return -1; } for (ap2 = response2; ap2 != NULL; ap2 = ap2->ai_next) { if (bind(sd, ap2->ai_addr, ap2->ai_addrlen) == 0) { break; } } if (ap2 == NULL) { Log(LOG_LEVEL_ERR, "Unable to bind to interface '%s'. (bind: %s)", BINDINTERFACE, GetErrorStr()); } assert(response2); /* second getaddrinfo was successful */ freeaddrinfo(response2); } connected = TryConnect(sd, connect_timeout * 1000, ap->ai_addr, ap->ai_addrlen); if (!connected) { Log(LOG_LEVEL_VERBOSE, "Unable to connect to address %s (%s)", txtaddr, GetErrorStr()); cf_closesocket(sd); sd = -1; } } } assert(response != NULL); /* first getaddrinfo was successful */ freeaddrinfo(response); if (connected) { Log(LOG_LEVEL_VERBOSE, "Connected to host %s address %s port %s", host, txtaddr, port); } else { Log(LOG_LEVEL_VERBOSE, "Unable to connect to host %s port %s", host, port); } return sd; } #if !defined(__MINGW32__) #if defined(__hpux) && defined(__GNUC__) #pragma GCC diagnostic ignored "-Wstrict-aliasing" // HP-UX GCC type-pun warning on FD_SET() macro: // While the "fd_set" type is defined in /usr/include/sys/_fd_macros.h as a // struct of an array of "long" values in accordance with the XPG4 standard's // requirements, the macros for the FD operations "pretend it is an array of // int32_t's so the binary layout is the same for both Narrow and Wide // processes," as described in _fd_macros.h. In the FD_SET, FD_CLR, and // FD_ISSET macros at line 101, the result is cast to an "__fd_mask *" type, // which is defined as int32_t at _fd_macros.h:82. // // This conflict between the "long fds_bits[]" array in the XPG4-compliant // fd_set structure, and the cast to an int32_t - not long - pointer in the // macros, causes a type-pun warning if -Wstrict-aliasing is enabled. // The warning is merely a side effect of HP-UX working as designed, // so it can be ignored. #endif /** * Tries to connect for #timeout_ms milliseconds. On success sets the recv() * timeout to #timeout_ms as well. * * @param #timeout_ms How long to wait for connect(), if zero wait forever. * @return true on success, false otherwise. **/ bool TryConnect(int sd, unsigned long timeout_ms, const struct sockaddr *sa, socklen_t sa_len) { assert(sa != NULL); if (sd >= FD_SETSIZE) { Log(LOG_LEVEL_ERR, "Open connections exceed FD_SETSIZE limit of %d", FD_SETSIZE); return false; } /* set non-blocking socket */ int arg = fcntl(sd, F_GETFL, NULL); int ret = fcntl(sd, F_SETFL, arg | O_NONBLOCK); if (ret == -1) { Log(LOG_LEVEL_ERR, "Failed to set socket to non-blocking mode (fcntl: %s)", GetErrorStr()); } ret = connect(sd, sa, sa_len); if (ret == -1) { if (errno != EINPROGRESS) { Log(LOG_LEVEL_INFO, "Failed to connect to server (connect: %s)", GetErrorStr()); return false; } int errcode; socklen_t opt_len = sizeof(errcode); fd_set myset; FD_ZERO(&myset); FD_SET(sd, &myset); Log(LOG_LEVEL_VERBOSE, "Waiting to connect..."); struct timeval tv, *tvp; if (timeout_ms > 0) { tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; tvp = &tv; } else { tvp = NULL; /* wait indefinitely */ } ret = select(sd + 1, NULL, &myset, NULL, tvp); if (ret == 0) { Log(LOG_LEVEL_INFO, "Timeout connecting to server"); return false; } if (ret == -1) { if (errno == EINTR) { Log(LOG_LEVEL_ERR, "Socket connect was interrupted by signal"); } else { Log(LOG_LEVEL_ERR, "Failure while connecting (select: %s)", GetErrorStr()); } return false; } ret = getsockopt(sd, SOL_SOCKET, SO_ERROR, (void *) &errcode, &opt_len); if (ret == -1) { Log(LOG_LEVEL_ERR, "Could not check connection status (getsockopt: %s)", GetErrorStr()); return false; } if (errcode != 0) { Log(LOG_LEVEL_INFO, "Failed to connect to server: %s", GetErrorStrFromCode(errcode)); return false; } } /* Connection suceeded, return to blocking mode. */ ret = fcntl(sd, F_SETFL, arg); if (ret == -1) { Log(LOG_LEVEL_ERR, "Failed to set socket back to blocking mode (fcntl: %s)", GetErrorStr()); } if (timeout_ms > 0) { SetReceiveTimeout(sd, timeout_ms); } return true; } #if defined(__hpux) && defined(__GNUC__) #pragma GCC diagnostic warning "-Wstrict-aliasing" #endif #endif /* !defined(__MINGW32__) */ /** * Set timeout for recv(), in milliseconds. * @param ms must be > 0. */ int SetReceiveTimeout(int fd, unsigned long ms) { assert(ms > 0); Log(LOG_LEVEL_VERBOSE, "Setting socket timeout to %lu seconds.", ms/1000); /* On windows SO_RCVTIMEO is set by a DWORD indicating the timeout in * milliseconds, on UNIX it's a struct timeval. */ #if !defined(__MINGW32__) struct timeval tv = { .tv_sec = ms / 1000, .tv_usec = (ms % 1000) * 1000 }; int ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); #else int ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &ms, sizeof(ms)); #endif if (ret != 0) { Log(LOG_LEVEL_INFO, "Failed to set socket timeout to %lu milliseconds.", ms); return -1; } return 0; } cfengine-3.6.2/libcfnet/tls_generic.c0000664000175100017510000006101512411001073017236 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include /* LogLevel */ #include /* TODO move crypto.h to libutils */ #include /* HavePublicKeyByIP */ #include /* HashPubKey */ #include int CONNECTIONINFO_SSL_IDX = -1; const char *TLSErrorString(intmax_t errcode) { const char *errmsg = ERR_reason_error_string((unsigned long) errcode); return (errmsg != NULL) ? errmsg : "no error message"; } bool TLSGenericInitialize() { static bool is_initialised = false; /* We must make sure that SSL_get_ex_new_index() is called only once! */ if (is_initialised) { return true; } /* OpenSSL is needed for TLS. */ SSL_library_init(); SSL_load_error_strings(); /* Register a unique place to store ConnectionInfo within SSL struct. */ CONNECTIONINFO_SSL_IDX = SSL_get_ex_new_index(0, "Pointer to ConnectionInfo", NULL, NULL, NULL); is_initialised = true; return true; } /** * @retval 1 equal * @retval 0 not equal * @retval -1 error */ static int CompareCertToRSA(X509 *cert, RSA *rsa_key) { int ret; int retval = -1; /* ERROR */ EVP_PKEY *cert_pkey = X509_get_pubkey(cert); if (cert_pkey == NULL) { Log(LOG_LEVEL_ERR, "X509_get_pubkey: %s", TLSErrorString(ERR_get_error())); goto ret1; } if (EVP_PKEY_type(cert_pkey->type) != EVP_PKEY_RSA) { Log(LOG_LEVEL_ERR, "Received key of unknown type, only RSA currently supported!"); goto ret2; } RSA *cert_rsa_key = EVP_PKEY_get1_RSA(cert_pkey); if (cert_rsa_key == NULL) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_get1_RSA failed!"); goto ret2; } EVP_PKEY *rsa_pkey = EVP_PKEY_new(); if (rsa_pkey == NULL) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_new allocation failed!"); goto ret3; } ret = EVP_PKEY_set1_RSA(rsa_pkey, rsa_key); if (ret == 0) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_set1_RSA failed!"); goto ret4; } ret = EVP_PKEY_cmp(cert_pkey, rsa_pkey); if (ret == 1) { Log(LOG_LEVEL_DEBUG, "Public key to certificate compare equal"); retval = 1; /* EQUAL */ } else if (ret == 0 || ret == -1) { Log(LOG_LEVEL_DEBUG, "Public key to certificate compare different"); retval = 0; /* NOT EQUAL */ } else { Log(LOG_LEVEL_ERR, "OpenSSL EVP_PKEY_cmp: %d %s", ret, TLSErrorString(ERR_get_error())); } ret4: EVP_PKEY_free(rsa_pkey); ret3: RSA_free(cert_rsa_key); ret2: EVP_PKEY_free(cert_pkey); ret1: return retval; } /** * The only thing we make sure here is that any key change is not allowed. All * the rest of authentication happens separately *after* the initial * handshake, thus *after* this callback has returned successfully and TLS * session has been established. */ int TLSVerifyCallback(X509_STORE_CTX *store_ctx, void *arg ARG_UNUSED) { /* It's kind of tricky to get custom connection-specific info in this * callback. We first acquire a pointer to the SSL struct of the * connection and... */ int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); SSL *ssl = X509_STORE_CTX_get_ex_data(store_ctx, ssl_idx); if (ssl == NULL) { UnexpectedError("No SSL context during handshake, denying!"); return 0; } /* ...and then we ask for the custom data we attached there. */ ConnectionInfo *conn_info = SSL_get_ex_data(ssl, CONNECTIONINFO_SSL_IDX); if (conn_info == NULL) { UnexpectedError("No conn_info at index %d", CONNECTIONINFO_SSL_IDX); return 0; } /* From that data get the key if the connection is already established. */ RSA *already_negotiated_key = KeyRSA(ConnectionInfoKey(conn_info)); /* Is there an already negotiated certificate? */ X509 *previous_tls_cert = SSL_get_peer_certificate(ssl); if (previous_tls_cert == NULL) { Log(LOG_LEVEL_DEBUG, "TLSVerifyCallback: no ssl->peer_cert"); if (already_negotiated_key == NULL) { Log(LOG_LEVEL_DEBUG, "TLSVerifyCallback: no conn_info->key"); Log(LOG_LEVEL_DEBUG, "This must be the initial TLS handshake, accepting"); return 1; /* ACCEPT HANDSHAKE */ } else { UnexpectedError("Initial handshake, but old keys differ, denying!"); return 0; } } else /* TLS renegotiation handshake */ { if (already_negotiated_key == NULL) { Log(LOG_LEVEL_DEBUG, "TLSVerifyCallback: no conn_info->key"); Log(LOG_LEVEL_ERR, "Renegotiation handshake before trust was established, denying!"); X509_free(previous_tls_cert); return 0; /* fishy */ } else { /* previous_tls_cert key should match already_negotiated_key. */ if (CompareCertToRSA(previous_tls_cert, already_negotiated_key) != 1) { UnexpectedError("Renegotiation caused keys to differ, denying!"); X509_free(previous_tls_cert); return 0; } else { /* THIS IS THE ONLY WAY TO CONTINUE */ } } } assert(previous_tls_cert != NULL); assert(already_negotiated_key != NULL); /* At this point we have ensured that previous_tls_cert->key is equal * to already_negotiated_key, so we might as well forget the former. */ X509_free(previous_tls_cert); /* We want to compare already_negotiated_key to the one the peer * negotiates in this TLS renegotiation. So, extract first certificate out * of the chain the peer sent. It should be the only one since we do not * support certificate chains, we just want the RSA key. */ STACK_OF(X509) *chain = X509_STORE_CTX_get_chain(store_ctx); if (chain == NULL) { Log(LOG_LEVEL_ERR, "No certificate chain inside TLS handshake, denying!"); return 0; } int chain_len = sk_X509_num(chain); if (chain_len != 1) { Log(LOG_LEVEL_ERR, "More than one certificate presented in TLS handshake, refusing handshake!"); return 0; } X509 *new_cert = sk_X509_value(chain, 0); if (new_cert == NULL) { UnexpectedError("NULL certificate at the beginning of chain!"); return 0; } if (CompareCertToRSA(new_cert, already_negotiated_key) != 1) { Log(LOG_LEVEL_ERR, "Peer attempted to change key during TLS renegotiation, denying!"); return 0; } Log(LOG_LEVEL_DEBUG, "TLS renegotiation occurred but keys are still the same, accepting"); return 1; /* ACCEPT HANDSHAKE */ } /** * @retval 1 if the public key used by the peer in the TLS handshake is the * same with the one stored for that host. * @retval 0 if stored key for the host is missing or differs from the one * received. * @retval -1 in case of other error (error will be Log()ed). * @note When return value is != -1 (so no error occured) the #conn_info struct * should have been populated, with key received and its hash. */ int TLSVerifyPeer(ConnectionInfo *conn_info, const char *remoteip, const char *username) { int ret, retval; X509 *received_cert = SSL_get_peer_certificate(ConnectionInfoSSL(conn_info)); if (received_cert == NULL) { Log(LOG_LEVEL_ERR, "No certificate presented by remote peer (openssl: %s)", TLSErrorString(ERR_get_error())); retval = -1; goto ret1; } EVP_PKEY *received_pubkey = X509_get_pubkey(received_cert); if (received_pubkey == NULL) { Log(LOG_LEVEL_ERR, "X509_get_pubkey: %s", TLSErrorString(ERR_get_error())); retval = -1; goto ret2; } if (EVP_PKEY_type(received_pubkey->type) != EVP_PKEY_RSA) { Log(LOG_LEVEL_ERR, "Received key of unknown type, only RSA currently supported!"); retval = -1; goto ret3; } RSA *remote_key = EVP_PKEY_get1_RSA(received_pubkey); if (remote_key == NULL) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_get1_RSA failed!"); retval = -1; goto ret3; } Key *key = KeyNew(remote_key, CF_DEFAULT_DIGEST); ConnectionInfoSetKey(conn_info, key); /* * Compare the key received with the one stored. */ RSA *expected_rsa_key = HavePublicKey(username, remoteip, KeyPrintableHash(key)); if (expected_rsa_key == NULL) { Log(LOG_LEVEL_VERBOSE, "Public key for remote host not found in ppkeys"); retval = 0; goto ret4; } EVP_PKEY *expected_pubkey = EVP_PKEY_new(); if (expected_pubkey == NULL) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_new allocation failed!"); retval = -1; goto ret5; } ret = EVP_PKEY_set1_RSA(expected_pubkey, expected_rsa_key); if (ret == 0) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_set1_RSA failed!"); retval = -1; goto ret6; } ret = EVP_PKEY_cmp(received_pubkey, expected_pubkey); if (ret == 1) { Log(LOG_LEVEL_VERBOSE, "Received public key compares equal to the one we have stored"); retval = 1; /* TRUSTED KEY, equal to the expected one */ goto ret6; } else if (ret == 0 || ret == -1) { Log(LOG_LEVEL_VERBOSE, "Public key for remote host compares different to the one in ppkeys"); retval = 0; goto ret6; } else { Log(LOG_LEVEL_ERR, "OpenSSL EVP_PKEY_cmp: %d %s", ret, TLSErrorString(ERR_get_error())); retval = -1; goto ret6; } UnexpectedError("Unreachable!"); return 0; ret6: EVP_PKEY_free(expected_pubkey); ret5: RSA_free(expected_rsa_key); ret4: if (retval == -1) { /* We won't be needing conn_info->key */ KeyDestroy(&key); ConnectionInfoSetKey(conn_info, NULL); } ret3: EVP_PKEY_free(received_pubkey); ret2: X509_free(received_cert); ret1: return retval; } /** * @brief Generate and return a dummy in-memory X509 certificate signed with * the private key passed. It is valid from now to 50 years later... */ X509 *TLSGenerateCertFromPrivKey(RSA *privkey) { int ret; X509 *x509 = X509_new(); if (x509 == NULL) { Log(LOG_LEVEL_ERR, "X509_new: %s", TLSErrorString(ERR_get_error())); goto err1; } ASN1_TIME *t1 = X509_gmtime_adj(X509_get_notBefore(x509), 0); ASN1_TIME *t2 = X509_gmtime_adj(X509_get_notAfter(x509), 60*60*24*365*10); if (t1 == NULL || t2 == NULL) { Log(LOG_LEVEL_ERR, "X509_gmtime_adj: %s", TLSErrorString(ERR_get_error())); goto err2; } EVP_PKEY *pkey = EVP_PKEY_new(); if (pkey == NULL) { Log(LOG_LEVEL_ERR, "EVP_PKEY_new: %s", TLSErrorString(ERR_get_error())); goto err2; } ret = EVP_PKEY_set1_RSA(pkey, privkey); if (ret != 1) { Log(LOG_LEVEL_ERR, "EVP_PKEY_set1_RSA: %s", TLSErrorString(ERR_get_error())); goto err3; } X509_NAME *name = X509_get_subject_name(x509); if (name == NULL) { Log(LOG_LEVEL_ERR, "X509_get_subject_name: %s", TLSErrorString(ERR_get_error())); goto err3; } ret = 0; ret += X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const char *) "a", -1, -1, 0); ret += X509_set_issuer_name(x509, name); ret += X509_set_pubkey(x509, pkey); if (ret < 3) { Log(LOG_LEVEL_ERR, "Failed to set certificate details: %s", TLSErrorString(ERR_get_error())); goto err3; } const EVP_MD *md = EVP_get_digestbyname("sha384"); if (md == NULL) { Log(LOG_LEVEL_ERR, "OpenSSL: Uknown digest algorithm %s", "sha384"); goto err3; } if (getenv("CFENGINE_TEST_PURIFY_OPENSSL") != NULL) { RSA_blinding_off(privkey); } /* Not really needed since the other side does not verify the signature. */ ret = X509_sign(x509, pkey, md); /* X509_sign obscurely returns the length of the signature... */ if (ret == 0) { Log(LOG_LEVEL_ERR, "X509_sign: %s", TLSErrorString(ERR_get_error())); goto err3; } EVP_PKEY_free(pkey); assert (x509 != NULL); return x509; err3: EVP_PKEY_free(pkey); err2: X509_free(x509); err1: return NULL; } static const char *TLSPrimarySSLError(int code) { switch (code) { case SSL_ERROR_NONE: return "TLSGetSSLErrorString: No SSL error!"; case SSL_ERROR_ZERO_RETURN: return "TLS session has been terminated (SSL_ERROR_ZERO_RETURN)"; case SSL_ERROR_WANT_READ: return "SSL_ERROR_WANT_READ"; case SSL_ERROR_WANT_WRITE: return "SSL_ERROR_WANT_WRITE"; case SSL_ERROR_WANT_CONNECT: return "SSL_ERROR_WANT_CONNECT"; case SSL_ERROR_WANT_ACCEPT: return "SSL_ERROR_WANT_ACCEPT"; case SSL_ERROR_WANT_X509_LOOKUP: return "SSL_ERROR_WANT_X509_LOOKUP"; case SSL_ERROR_SYSCALL: return "SSL_ERROR_SYSCALL"; case SSL_ERROR_SSL: return "SSL_ERROR_SSL"; } return "Unknown OpenSSL error code!"; } /** * @brief OpenSSL is missing an SSL_reason_error_string() like * ERR_reason_error_string(). Provide missing functionality here, * since it's kind of complicated. * @param #prepend String to prepend to the SSL error. * @param #code Return code from the OpenSSL function call. * @warning Use only for SSL_connect(), SSL_accept(), SSL_do_handshake(), * SSL_read(), SSL_peek(), SSL_write(), see SSL_get_error man page. */ void TLSLogError(SSL *ssl, LogLevel level, const char *prepend, int retcode) { assert(prepend != NULL); /* For when retcode==SSL_ERROR_SYSCALL. */ const char *syserr = (errno != 0) ? GetErrorStr() : ""; int errcode = SSL_get_error(ssl, retcode); const char *errstr1 = TLSPrimarySSLError(errcode); /* For SSL_ERROR_SSL, SSL_ERROR_SYSCALL (man SSL_get_error). It's not * useful for SSL_read() and SSL_write(). */ const char *errstr2 = ERR_reason_error_string(ERR_get_error()); /* We know the socket is always blocking. However our blocking sockets * have a timeout set via means of setsockopt(SO_RCVTIMEO), so internally * OpenSSL can still get the EWOULDBLOCK error code from recv(). In that * case OpenSSL gives us SSL_ERROR_WANT_READ despite the socket being * blocking. So we log a proper error message! */ if (errcode == SSL_ERROR_WANT_READ) { Log(level, "%s: receive timeout", prepend); } else if (errcode == SSL_ERROR_WANT_WRITE) { Log(level, "%s: send timeout", prepend); } /* if we got SSL_ERROR_SYSCALL and ERR_get_error() returned 0 then take * ret into account (man SSL_get_error). */ else if (errcode == SSL_ERROR_SYSCALL && errstr2 == NULL && (retcode == 0 || retcode == -1)) { /* This is not described in SSL_get_error manual, but play it safe. */ if ((SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) != 0) { Log(level, "%s: remote peer terminated TLS session", prepend); } /* "an EOF was observed that violates the protocol" */ else if (retcode == 0) { Log(level, "%s: socket closed", prepend); } /* "the underlying BIO reported an I/O error" */ else if (retcode == -1) { Log(level, "%s: underlying network error (%s)", prepend, syserr); } } else /* generic error printing fallback */ { Log(level, "%s: (%d %s) %s %s", prepend, retcode, errstr1, (errstr2 == NULL) ? "" : errstr2, /* most likely empty */ syserr); } } static void assert_SSLIsBlocking(const SSL *ssl) { #if !defined(NDEBUG) && !defined(__MINGW32__) int fd = SSL_get_fd(ssl); if (fd >= 0) { int flags = fcntl(fd, F_GETFL, 0); if (flags != -1 && (flags & O_NONBLOCK) != 0) { ProgrammingError("OpenSSL socket is non-blocking!"); } } #endif } /** * @brief Sends the data stored on the buffer using a TLS session. * @param ssl SSL information. * @param buffer Data to send. * @param length Length of the data to send. * @return The length of the data sent (which could be smaller than the * requested length) or -1 in case of error. * @note Use only for *blocking* sockets. Set * SSL_CTX_set_mode(SSL_MODE_AUTO_RETRY) to make sure that either * operation completed or an error occured. * * @TODO ERR_get_error is only meaningful for some error codes, so check and * return empty string otherwise. */ int TLSSend(SSL *ssl, const char *buffer, int length) { assert(length >= 0); assert_SSLIsBlocking(ssl); if (length == 0) { UnexpectedError("TLSSend: Zero length buffer!"); return 0; } int sent = SSL_write(ssl, buffer, length); if (sent == 0) { if ((SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) != 0) { Log(LOG_LEVEL_VERBOSE, "Remote peer terminated TLS session"); return 0; } else { TLSLogError(ssl, LOG_LEVEL_ERR, "Connection unexpectedly closed. SSL_write", sent); return 0; } } if (sent < 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "SSL_write", sent); return -1; } return sent; } /** * @brief Receives data from the SSL session and stores it on the buffer. * @param ssl SSL information. * @param buffer Buffer, of size at least CF_BUFSIZE, to store received data. * @param length Length of the data to receive, must be < CF_BUFSIZE. * @return The length of the received data, which could be smaller or equal * than the requested or -1 in case of error or 0 if connection was * closed. * @note Use only for *blocking* sockets. Set * SSL_CTX_set_mode(SSL_MODE_AUTO_RETRY) to make sure that either * operation completed or an error occured. */ int TLSRecv(SSL *ssl, char *buffer, int length) { assert(length > 0); assert(length < CF_BUFSIZE); assert_SSLIsBlocking(ssl); int received = SSL_read(ssl, buffer, length); if (received < 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "SSL_read", received); return -1; } else if (received == 0) { if ((SSL_get_shutdown(ssl) & SSL_RECEIVED_SHUTDOWN) != 0) { Log(LOG_LEVEL_VERBOSE, "Remote peer terminated TLS session"); } else { TLSLogError(ssl, LOG_LEVEL_ERR, "Connection unexpectedly closed. SSL_read", received); } } assert(received < CF_BUFSIZE); buffer[received] = '\0'; return received; } /** * @brief Repeat receiving until last byte received is '\n'. * * @param #buf on return will contain all received lines, and '\0' will be * appended to it. * @return Return value is #buf 's length (excluding manually appended '\0') * or -1 in case of error. * * @note This function is intended for line-oriented communication, this means * the peer sends us one line (or a bunch of lines) and waits for reply, * so that '\n' is the last character in the underlying SSL_read(). */ int TLSRecvLines(SSL *ssl, char *buf, size_t buf_size) { int ret; int got = 0; buf_size -= 1; /* Reserve one space for terminating '\0' */ /* Repeat until we receive end of line. */ do { buf[got] = '\0'; ret = TLSRecv(ssl, &buf[got], buf_size - got); if (ret <= 0) { Log(LOG_LEVEL_ERR, "Connection was hung up while receiving line: %s", buf); return -1; } got += ret; } while ((buf[got-1] != '\n') && (got < buf_size)); assert(got <= buf_size); /* Append '\0', there is room because buf_size has been decremented. */ buf[got] = '\0'; if ((got == buf_size) && (buf[got-1] != '\n')) { Log(LOG_LEVEL_ERR, "Received line too long, hanging up! Length %d, line: %s", got, buf); return -1; } LogRaw(LOG_LEVEL_DEBUG, "TLSRecvLines(): ", buf, got); return got; } /** * Set safe OpenSSL defaults commonly used by both clients and servers. */ void TLSSetDefaultOptions(SSL_CTX *ssl_ctx) { #if HAVE_DECL_SSL_CTX_CLEAR_OPTIONS /* Clear all flags, we do not want compatibility tradeoffs like * SSL_OP_LEGACY_SERVER_CONNECT. */ SSL_CTX_clear_options(ssl_ctx, SSL_CTX_get_options(ssl_ctx)); #else /* According to OpenSSL code v.0.9.8m, the first option to be added * by default (SSL_OP_LEGACY_SERVER_CONNECT) was added at the same * time SSL_CTX_clear_options appeared. Therefore, it is OK not to * clear options if they are not set. * If this assertion is proven to be false, output a clear warning * to let the user know what happens. */ if (SSL_CTX_get_options(ssl_ctx) != 0) { Log(LOG_LEVEL_WARNING, "This version of CFEngine was compiled against OpenSSL < 0.9.8m, using it with a later OpenSSL version is insecure."); Log(LOG_LEVEL_WARNING, "The current version uses compatibility workarounds that may allow CVE-2009-3555 exploitation."); Log(LOG_LEVEL_WARNING, "Please update your CFEngine package or compile it against your current OpenSSL version."); } #endif /* Use only TLS v1 or later. TODO policy option for SSL_OP_NO_TLSv{1,1_1} */ long options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; /* No session resumption or renegotiation for now. */ options |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; #ifdef SSL_OP_NO_TICKET /* Disable another way of resumption, session tickets (RFC 5077). */ options |= SSL_OP_NO_TICKET; #endif SSL_CTX_set_options(ssl_ctx, options); /* Disable both server-side and client-side session caching, to complement the previous options. Safe for now, might enable for performance in the future. */ SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF); /* Never bother with retransmissions, SSL_write() should * always either write the whole amount or fail. */ SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); /* Set options to always request a certificate from the peer, either we are client or server. */ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); /* Always accept that certificate, we do proper checking after TLS * connection is established since OpenSSL can't pass a connection * specific pointer to the callback (so we would have to lock). */ SSL_CTX_set_cert_verify_callback(ssl_ctx, TLSVerifyCallback, NULL); } cfengine-3.6.2/cf-serverd/0000775000175100017510000000000012413020723015050 5ustar00a10038a1003800000000000000cfengine-3.6.2/cf-serverd/server_transform.c0000664000175100017510000013201312411001073020610 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* HashControls */ #include /* IsDirReal */ #include /* IsRegex */ #include "server_common.h" /* PreprocessRequestPath */ #include "server_access.h" #include "strlist.h" static void KeepContextBundles(EvalContext *ctx, const Policy *policy); static PromiseResult KeepServerPromise(EvalContext *ctx, const Promise *pp, void *param); static void InstallServerAuthPath(const char *path, Auth **list, Auth **listtail); static void KeepServerRolePromise(EvalContext *ctx, const Promise *pp); static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy); static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config); static Auth *GetAuthPath(const char *path, Auth *list); extern int COLLECT_INTERVAL; extern int COLLECT_WINDOW; extern bool SERVER_LISTEN; /*******************************************************************/ /* GLOBAL VARIABLES */ /*******************************************************************/ extern int CFD_MAXPROCESSES; extern int NO_FORK; extern bool DENYBADCLOCKS; extern int MAXTRIES; extern bool LOGENCRYPT; /*******************************************************************/ static void KeepFileAccessPromise(const EvalContext *ctx, const Promise *pp); static void KeepLiteralAccessPromise(EvalContext *ctx, const Promise *pp, const char *type); static void KeepQueryAccessPromise(EvalContext *ctx, const Promise *pp); /*******************************************************************/ /* Level */ /*******************************************************************/ void Summarize() { Log(LOG_LEVEL_VERBOSE, " === BEGIN summary of access promises === "); size_t i, j; for (i = 0; i < paths_acl->len; i++) { Log(LOG_LEVEL_VERBOSE, "\tPath: %s", StrList_At(paths_acl->resource_names, i)); const struct resource_acl *racl = &paths_acl->acls[i]; for (j = 0; j < StrList_Len(racl->admit.ips); j++) { Log(LOG_LEVEL_VERBOSE, "\t\tadmit_ips: %s", StrList_At(racl->admit.ips, j)); } for (j = 0; j < StrList_Len(racl->admit.hostnames); j++) { Log(LOG_LEVEL_VERBOSE, "\t\tadmit_hostnames: %s", StrList_At(racl->admit.hostnames, j)); } for (j = 0; j < StrList_Len(racl->admit.keys); j++) { Log(LOG_LEVEL_VERBOSE, "\t\tadmit_keys: %s", StrList_At(racl->admit.keys, j)); } for (j = 0; j < StrList_Len(racl->deny.ips); j++) { Log(LOG_LEVEL_VERBOSE, "\t\tdeny_ips: %s", StrList_At(racl->deny.ips, j)); } for (j = 0; j < StrList_Len(racl->deny.hostnames); j++) { Log(LOG_LEVEL_VERBOSE, "\t\tdeny_hostnames: %s", StrList_At(racl->deny.hostnames, j)); } for (j = 0; j < StrList_Len(racl->deny.keys); j++) { Log(LOG_LEVEL_VERBOSE, "\t\tdeny_keys: %s", StrList_At(racl->deny.keys, j)); } } Auth *ptr; Item *ip, *ipr; Log(LOG_LEVEL_VERBOSE, "Granted access to paths for classic protocol:"); for (ptr = SV.admit; ptr != NULL; ptr = ptr->next) { /* Don't report empty entries. */ if (ptr->maproot != NULL || ptr->accesslist != NULL) { Log(LOG_LEVEL_VERBOSE, "\tPath: %s", ptr->path); } for (ipr = ptr->maproot; ipr != NULL; ipr = ipr->next) { Log(LOG_LEVEL_VERBOSE, "\t\tmaproot user: %s,", ipr->name); } for (ip = ptr->accesslist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "\t\tadmit: %s", ip->name); } } Log(LOG_LEVEL_VERBOSE, "Denied access to paths for classic protocol:"); for (ptr = SV.deny; ptr != NULL; ptr = ptr->next) { /* Don't report empty entries. */ if (ptr->accesslist != NULL) { Log(LOG_LEVEL_VERBOSE, "\tPath: %s", ptr->path); } for (ip = ptr->accesslist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "\t\tdeny: %s", ip->name); } } Log(LOG_LEVEL_VERBOSE, "Granted access to literal/variable/query data :"); for (ptr = SV.varadmit; ptr != NULL; ptr = ptr->next) { Log(LOG_LEVEL_VERBOSE, "Object: %s", ptr->path); for (ipr = ptr->maproot; ipr != NULL; ipr = ipr->next) { Log(LOG_LEVEL_VERBOSE, "%s,", ipr->name); } for (ip = ptr->accesslist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "Admit '%s' root=", ip->name); } } Log(LOG_LEVEL_VERBOSE, "Denied access to literal/variable/query data:"); for (ptr = SV.vardeny; ptr != NULL; ptr = ptr->next) { Log(LOG_LEVEL_VERBOSE, "Object %s", ptr->path); for (ip = ptr->accesslist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "Deny '%s'", ip->name); } } Log(LOG_LEVEL_VERBOSE, "Host IPs allowed connection access:"); for (ip = SV.nonattackerlist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "IP '%s'", ip->name); } Log(LOG_LEVEL_VERBOSE, "Host IPs denied connection access:"); for (ip = SV.attackerlist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "IP '%s'", ip->name); } Log(LOG_LEVEL_VERBOSE, "Host IPs allowed multiple connection access:"); for (ip = SV.multiconnlist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "IP '%s'", ip->name); } Log(LOG_LEVEL_VERBOSE, "Host IPs whose keys we shall establish trust to:"); for (ip = SV.trustkeylist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "IP '%s'", ip->name); } Log(LOG_LEVEL_VERBOSE, "Host IPs allowed legacy connections:"); for (ip = SV.allowlegacyconnects; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "IP '%s'", ip->name); } Log(LOG_LEVEL_VERBOSE, "Users from whom we accept connections:"); for (ip = SV.allowuserlist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "USERS '%s'", ip->name); } Log(LOG_LEVEL_VERBOSE, " === END summary of access promises === "); } void KeepPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { if (paths_acl != NULL || classes_acl != NULL || vars_acl != NULL || literals_acl != NULL || query_acl != NULL || SV.path_shortcuts != NULL) { UnexpectedError("ACLs are not NULL - we are probably leaking memory!"); } paths_acl = calloc(1, sizeof(*paths_acl)); classes_acl = calloc(1, sizeof(*classes_acl)); vars_acl = calloc(1, sizeof(*vars_acl)); literals_acl = calloc(1, sizeof(*literals_acl)); query_acl = calloc(1, sizeof(*query_acl)); SV.path_shortcuts = StringMapNew(); if (paths_acl == NULL || classes_acl == NULL || vars_acl == NULL || literals_acl == NULL || query_acl == NULL || SV.path_shortcuts == NULL) { Log(LOG_LEVEL_CRIT, "calloc: %s", GetErrorStr()); exit(255); } KeepContextBundles(ctx, policy); KeepControlPromises(ctx, policy, config); KeepPromiseBundles(ctx, policy); } /*******************************************************************/ static void KeepControlPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config) { CFD_MAXPROCESSES = 30; MAXTRIES = 5; DENYBADCLOCKS = true; CFRUNCOMMAND[0] = '\0'; SetChecksumUpdatesDefault(ctx, true); /* Keep promised agent behaviour - control bodies */ Banner("Server control promises.."); PolicyResolve(ctx, policy, config); /* Now expand */ Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_SERVER); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_server"); const void *value = EvalContextVariableGet(ctx, ref, NULL); VarRefDestroy(ref); if (!value) { Log(LOG_LEVEL_ERR, "Unknown lval '%s' in server control body", cp->lval); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SERVER_FACILITY].lval) == 0) { SetFacility(value); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_BAD_CLOCKS].lval) == 0) { DENYBADCLOCKS = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting denybadclocks to '%s'", DENYBADCLOCKS ? "true" : "false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ENCRYPTED_TRANSFERS].lval) == 0) { LOGENCRYPT = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting logencrypt to '%s'", LOGENCRYPT ? "true" : "false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LOG_ALL_CONNECTIONS].lval) == 0) { SV.logconns = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting logconns to %d", SV.logconns); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_MAX_CONNECTIONS].lval) == 0) { CFD_MAXPROCESSES = (int) IntFromString(value); MAXTRIES = CFD_MAXPROCESSES / 3; Log(LOG_LEVEL_VERBOSE, "Setting maxconnections to %d", CFD_MAXPROCESSES); #ifdef LMDB static int LSD_MAXREADERS = 0; if (LSD_MAXREADERS < CFD_MAXPROCESSES) { int rc = UpdateLastSeenMaxReaders(CFD_MAXPROCESSES); if (rc == 0) { LSD_MAXREADERS = CFD_MAXPROCESSES; } } #endif continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_INTERVAL].lval) == 0) { COLLECT_INTERVAL = (int) 60 * IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting call_collect_interval to %d (seconds)", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_LISTEN].lval) == 0) { SERVER_LISTEN = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting server listen to '%s' ", (SERVER_LISTEN)? "true":"false"); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CALL_COLLECT_WINDOW].lval) == 0) { COLLECT_WINDOW = (int) IntFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting collect_window to %d (seconds)", COLLECT_INTERVAL); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_CF_RUN_COMMAND].lval) == 0) { strlcpy(CFRUNCOMMAND, value, sizeof(CFRUNCOMMAND)); Log(LOG_LEVEL_VERBOSE, "Setting cfruncommand to '%s'", CFRUNCOMMAND); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_CONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting allowing connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.nonattackerlist, RlistScalarValue(rp))) { PrependItem(&SV.nonattackerlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_DENY_CONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting denying connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.attackerlist, RlistScalarValue(rp))) { PrependItem(&SV.attackerlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_SKIP_VERIFY].lval) == 0) { continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_ALL_CONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting allowing multiple connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.multiconnlist, RlistScalarValue(rp))) { PrependItem(&SV.multiconnlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOW_USERS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "SET Allowing users ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowuserlist, RlistScalarValue(rp))) { PrependItem(&SV.allowuserlist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_TRUST_KEYS_FROM].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting trust keys from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.trustkeylist, RlistScalarValue(rp))) { PrependItem(&SV.trustkeylist, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOWLEGACYCONNECTS].lval) == 0) { Log(LOG_LEVEL_VERBOSE, "Setting allowing legacy connections from ..."); for (const Rlist *rp = value; rp != NULL; rp = rp->next) { if (!IsItemIn(SV.allowlegacyconnects, RlistScalarValue(rp))) { PrependItem(&SV.allowlegacyconnects, RlistScalarValue(rp), cp->classes); } } continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_PORT_NUMBER].lval) == 0) { CFENGINE_PORT = IntFromString(value); strlcpy(CFENGINE_PORT_STR, value, sizeof(CFENGINE_PORT_STR)); Log(LOG_LEVEL_VERBOSE, "Setting default port number to %d", CFENGINE_PORT); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_BIND_TO_INTERFACE].lval) == 0) { strlcpy(BINDINTERFACE, value, sizeof(BINDINTERFACE)); Log(LOG_LEVEL_VERBOSE, "Setting bindtointerface to '%s'", BINDINTERFACE); continue; } if (strcmp(cp->lval, CFS_CONTROLBODY[SERVER_CONTROL_ALLOWCIPHERS].lval) == 0) { SV.allowciphers = xstrdup(value); Log(LOG_LEVEL_VERBOSE, "Setting allowciphers to '%s'", SV.allowciphers); continue; } } } const void *value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_HOST); if (value) { /* Don't resolve syslog_host now, better do it per log request. */ if (!SetSyslogHost(value)) { Log(LOG_LEVEL_ERR, "Failed to set syslog_host, '%s' too long", (const char *)value); } else { Log(LOG_LEVEL_VERBOSE, "Setting syslog_host to '%s'", (const char *)value); } } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_SYSLOG_PORT); if (value) { SetSyslogPort(IntFromString(value)); } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_FIPS_MODE); if (value) { FIPS_MODE = BooleanFromString(value); Log(LOG_LEVEL_VERBOSE, "Setting FIPS mode to to '%s'", FIPS_MODE ? "true" : "false"); } value = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_LASTSEEN_EXPIRE_AFTER); if (value) { LASTSEENEXPIREAFTER = IntFromString(value) * 60; } } /*********************************************************************/ static void KeepContextBundles(EvalContext *ctx, const Policy *policy) { /* Dial up the generic promise expansion with a callback */ for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { if (RlistLen(bp->args) > 0) { Log(LOG_LEVEL_WARNING, "Cannot implicitly evaluate bundle '%s %s', as this bundle takes arguments.", bp->type, bp->name); continue; } BannerBundle(bp, NULL); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); if ((strcmp(sp->name, "vars") != 0) && (strcmp(sp->name, "classes") != 0)) { continue; } BannerPromiseType(bp->name, sp->name, 0); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); } } } /*********************************************************************/ static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy) { /* Dial up the generic promise expansion with a callback */ CleanReportBookFilterSet(); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { if (RlistLen(bp->args) > 0) { Log(LOG_LEVEL_WARNING, "Cannot implicitly evaluate bundle '%s %s', as this bundle takes arguments.", bp->type, bp->name); continue; } BannerBundle(bp, NULL); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); if ((strcmp(sp->name, "access") != 0) && (strcmp(sp->name, "roles") != 0)) { continue; } BannerPromiseType(bp->name, sp->name, 0); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); } } } static PromiseResult KeepServerPromise(EvalContext *ctx, const Promise *pp, ARG_UNUSED void *param) { assert(!param); if (strcmp(pp->parent_promise_type->name, "classes") == 0) { return VerifyClassPromise(ctx, pp, NULL); } if (strcmp(pp->parent_promise_type->name, "access") == 0) { const char *resource_type = PromiseGetConstraintAsRval(pp, "resource_type", RVAL_TYPE_SCALAR); /* Default resource_type in access_rules is "path" */ if (resource_type == NULL || strcmp(resource_type, "path") == 0) { KeepFileAccessPromise(ctx, pp); return PROMISE_RESULT_NOOP; } else if (strcmp(resource_type, "literal") == 0) { KeepLiteralAccessPromise(ctx, pp, "literal"); return PROMISE_RESULT_NOOP; } else if (strcmp(resource_type, "variable") == 0) { KeepLiteralAccessPromise(ctx, pp, "variable"); return PROMISE_RESULT_NOOP; } else if (strcmp(resource_type, "query") == 0) { KeepQueryAccessPromise(ctx, pp); KeepReportDataSelectAccessPromise(pp); return PROMISE_RESULT_NOOP; } else if (strcmp(resource_type, "context") == 0) { KeepLiteralAccessPromise(ctx, pp, "context"); return PROMISE_RESULT_NOOP; } } else if (strcmp(pp->parent_promise_type->name, "roles") == 0) { KeepServerRolePromise(ctx, pp); return PROMISE_RESULT_NOOP; } return PROMISE_RESULT_NOOP; } /*********************************************************************/ enum admit_type { ADMIT_TYPE_IP, ADMIT_TYPE_HOSTNAME, ADMIT_TYPE_KEY, ADMIT_TYPE_OTHER }; /* Check if the given string is an IP subnet, a hostname, a key, or none of * the above. */ static enum admit_type AdmitType(const char *s) { if (strncmp(s, "SHA=", strlen("SHA=")) == 0 || strncmp(s, "MD5=", strlen("MD5=")) == 0) { return ADMIT_TYPE_KEY; } /* IPv4 or IPv6 subnet mask or regex. */ /* TODO change this to "0123456789abcdef.:/", no regex allowed. */ else if (s[strspn(s, "0123456789abcdef.:/[-]*()\\")] == '\0') { return ADMIT_TYPE_IP; } else { return ADMIT_TYPE_HOSTNAME; } } /* Map old-style regex-or-hostname to new-style host-or-domain. * * Old-style ACLs could include regexes to be matched against host * names; but new-style ones only support sub-domain matching. If the * old-style host regex looks like ".*\.sub\.domain\.tld" we can take * it in as ".sub.domain.tld"; otherwise, we can only really map exact * match hostnames. However, we know some old policy (including our * own masterfiles) had cases of .*sub.domain.tld and it's possible * that someone might include a new-style .sub.domain.tld by mistake * in an (old-style) accept list; so cope with these cases, too. * * @param sl The string-list to which to add entries. * @param host The name-or-regex to add to the ACL. * @return An index at which an entry was added to the list (there may * be another), or -1 if nothing added. */ static size_t DeRegexify(StrList **sl, const char *host) { if (IsRegex(host)) { if (host[strcspn(host, "({[|+?]})")] != '\0') { return -1; /* Not a regex we can sensibly massage; discard. */ } bool skip[2] = { false, false }; /* { domain, host } passes below */ const char *name = host; if (name[0] == '^') /* Was always implicit; but read as hint to intent. */ { /* Default to skipping domain-form if anchored explicitly: */ skip[0] = true; /* Over-ridden below if followed by .* of course. */ name++; } if (StringStartsWith(name, ".*")) { skip[0] = false; /* Domain-form should match */ name += 2; } if (StringStartsWith(name, "\\.")) { /* Skip host-form, as the regex definitely wants something * before the given name. */ skip[1] = true; name += 2; } if (strchr(name, '*') != NULL) { /* Can't handle a * later than the preamble. */ return (size_t) -1; } if (name > host || NULL != strchr(host, '\\')) { /* 2: leading '.' and final '\0' */ char copy[2 + strlen(name)], *c = copy; c++[0] = '.'; /* For domain-form; and copy+1 gives host-form. */ /* Now copy the rest of the name, de-regex-ifying as we go: */ for (const char *p = name; p[0] != '\0'; p++) { if (p[0] == '\\') { p++; if (p[0] != '.') { /* Regex includes a non-dot escape */ return (size_t) -1; } } #if 0 else if (p[0] == '.') { /* In principle, this is a special character; but * it may just be an unescaped dot, so let it be. */ } #endif c++[0] = p[0]; } assert(c < copy + sizeof(copy)); c[0] = '\0'; /* Now, for host then domain, add entry if suitable */ int pass = 2; size_t ret = -1; while (pass > 0) { pass--; if (!skip[pass]) /* pass 0 is domain, pass 1 is host */ { ret = StrList_Append(sl, copy + pass); } } return ret; } /* IsRegex() but is actually so boring it's just a name ! */ } /* Just a simple host name. */ return StrList_Append(sl, host); } bool NEED_REVERSE_LOOKUP = false; static void TurnOnReverseLookups() { if (!NEED_REVERSE_LOOKUP) { Log(LOG_LEVEL_INFO, "Found hostname admit/deny in access_rules, " "turning on reverse DNS lookups for every connection"); NEED_REVERSE_LOOKUP = true; } } static size_t racl_SmartAppend(struct admitdeny_acl *ad, const char *entry) { size_t ret; switch (AdmitType(entry)) { case ADMIT_TYPE_IP: /* TODO convert IP string to binary representation. */ ret = StrList_Append(&ad->ips, entry); break; case ADMIT_TYPE_KEY: ret = StrList_Append(&ad->keys, entry); break; case ADMIT_TYPE_HOSTNAME: ret = DeRegexify(&ad->hostnames, entry); /* If any hostname rule got added, * turn on reverse DNS lookup in the new protocol. */ if (ret != (size_t) -1) { TurnOnReverseLookups(); } break; default: Log(LOG_LEVEL_WARNING, "Access rule 'admit: %s' is not IP, hostname or key, ignoring", entry); ret = (size_t) -1; } return ret; } /* Package hostname as regex, if needed. * * @param old The old Auth structure to which to add. * @param host The new acl_hostnames entry to add to it. */ static void NewHostToOldACL(Auth *old, const char *host) { if (host[0] == '.') /* Domain - transform to regex: */ { int extra = 2; /* For leading ".*" */ const char *dot = host; do { do { dot++; /* Step over prior dot. */ } while (dot[0] == '.'); /* Treat many dots as one. */ extra++; /* For a backslash before the dot */ dot = strchr(dot, '.'); } while (dot); char regex[strlen(host) + extra], *dst = regex; dst++[0] = '.'; dst++[0] = '*'; dot = host; do { /* Insert literal dot. */ assert(dot[0] == '.'); dst++[0] = '\\'; dst++[0] = '.'; do /* Step over prior dot(s), as before. */ { dot++; } while (dot[0] == '.'); /* Identify next fragment: */ const char *d = strchr(dot, '.'); size_t len = d ? d - dot : strlen(dot); /* Copy fragment: */ memcpy(dst, dot, len); dst += len; /* Advance: */ dot = d; } while (dot); /* Terminate: */ assert(dst < regex + sizeof(regex)); dst[0] = '\0'; /* Add to list: */ PrependItem(&(old->accesslist), regex, NULL); } else { /* Simple host-name; just add it: */ PrependItem(&(old->accesslist), host, NULL); } } /** * Add access rules to the given ACL #acl according to the constraints in the * particular access promise. * * For legacy reasons (non-TLS connections), build also the #ap (access Auth) * and #dp (deny Auth). */ static void AccessPromise_AddAccessConstraints(const EvalContext *ctx, const Promise *pp, struct resource_acl *racl, Auth *ap, Auth *dp) { Rlist *rp; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); size_t ret = -2; if (!IsDefinedClass(ctx, cp->classes)) { continue; } switch (cp->rval.type) { case RVAL_TYPE_SCALAR: if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_IFENCRYPTED].lval) == 0) { ap->encrypt = BooleanFromString(cp->rval.item); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_SHORTCUT].lval) == 0) { const char *shortcut = cp->rval.item; if (strchr(shortcut, FILE_SEPARATOR) != NULL) { Log(LOG_LEVEL_ERR, "slashes are forbidden in ACL shortcut: %s", shortcut); continue; } bool bret = StringMapHasKey(SV.path_shortcuts, shortcut); if (bret) { Log(LOG_LEVEL_WARNING, "Already existing shortcut for path '%s' was replaced", pp->promiser); continue; } StringMapInsert(SV.path_shortcuts, xstrdup(shortcut), xstrdup(pp->promiser)); Log(LOG_LEVEL_DEBUG, "Added shortcut '%s' for path: %s", shortcut, pp->promiser); continue; } break; case RVAL_TYPE_LIST: for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { /* TODO keys, ips, hostnames are valid such strings. */ if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_ADMITIPS].lval) == 0) { ret = StrList_Append(&racl->admit.ips, RlistScalarValue(rp)); PrependItem(&(ap->accesslist), RlistScalarValue(rp), NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_DENYIPS].lval) == 0) { ret = StrList_Append(&racl->deny.ips, RlistScalarValue(rp)); PrependItem(&(dp->accesslist), RlistScalarValue(rp), NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_ADMITHOSTNAMES].lval) == 0) { ret = StrList_Append(&racl->admit.hostnames, RlistScalarValue(rp)); /* If any hostname rule got added, * turn on reverse DNS lookup in the new protocol. */ if (ret != (size_t) -1) { TurnOnReverseLookups(); } NewHostToOldACL(ap, RlistScalarValue(rp)); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_DENYHOSTNAMES].lval) == 0) { ret = StrList_Append(&racl->deny.hostnames, RlistScalarValue(rp)); /* If any hostname rule got added, * turn on reverse DNS lookup in the new protocol. */ if (ret != (size_t) -1) { TurnOnReverseLookups(); } NewHostToOldACL(dp, RlistScalarValue(rp)); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_ADMITKEYS].lval) == 0) { ret = StrList_Append(&racl->admit.keys, RlistScalarValue(rp)); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_DENYKEYS].lval) == 0) { ret = StrList_Append(&racl->deny.keys, RlistScalarValue(rp)); continue; } /* Legacy stuff */ if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_ADMIT].lval) == 0) { ret = racl_SmartAppend(&racl->admit, RlistScalarValue(rp)); PrependItem(&(ap->accesslist), RlistScalarValue(rp), NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_DENY].lval) == 0) { ret = racl_SmartAppend(&racl->deny, RlistScalarValue(rp)); PrependItem(&(dp->accesslist), RlistScalarValue(rp), NULL); continue; } if (strcmp(cp->lval, CF_REMACCESS_BODIES[REMOTE_ACCESS_MAPROOT].lval) == 0) { PrependItem(&(ap->maproot), RlistScalarValue(rp), NULL); continue; } } if (ret == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "StrList_Append: %s", GetErrorStr()); exit(255); } break; default: UnexpectedError("Unknown constraint type!"); break; } } StrList_Finalise(&racl->admit.ips); StrList_Sort(racl->admit.ips, string_Compare); StrList_Finalise(&racl->admit.hostnames); StrList_Sort(racl->admit.hostnames, string_CompareFromEnd); StrList_Finalise(&racl->admit.keys); StrList_Sort(racl->admit.keys, string_Compare); StrList_Finalise(&racl->deny.ips); StrList_Sort(racl->deny.ips, string_Compare); StrList_Finalise(&racl->deny.hostnames); StrList_Sort(racl->deny.hostnames, string_CompareFromEnd); StrList_Finalise(&racl->deny.keys); StrList_Sort(racl->deny.keys, string_Compare); } /* It is allowed to have duplicate handles (paths or class names or variables * etc) in bundle server access_rules in policy files, but the lists here * should have unique entries. This, we make sure here. */ static Auth *GetOrCreateAuth(const char *handle, Auth **authchain, Auth **authchain_tail) { Auth *a = GetAuthPath(handle, *authchain); if (!a) { InstallServerAuthPath(handle, authchain, authchain_tail); a = GetAuthPath(handle, *authchain); } return a; } static void KeepFileAccessPromise(const EvalContext *ctx, const Promise *pp) { char path[PATH_MAX]; size_t path_len = strlen(pp->promiser); if (path_len > sizeof(path) - 1) { goto err_too_long; } memcpy(path, pp->promiser, path_len + 1); /* Resolve symlinks and canonicalise access_rules path. */ size_t ret2 = PreprocessRequestPath(path, sizeof(path)); if (ret2 == (size_t) -1) { if (errno != ENOENT) /* something went wrong */ { goto err_unknown; } else /* file does not exist, it doesn't matter */ { Log(LOG_LEVEL_INFO, "Path does not exist, it's added as-is in access rules: %s", path); Log(LOG_LEVEL_INFO, "WARNING: this means that (not) having a trailing slash defines if it's (not) a directory!"); /* Legacy: convert trailing "/." to "/" */ if (path_len >= 2 && path[path_len - 1] == '.' && path[path_len - 2] == '/') { path[path_len - 1] = '\0'; path_len--; } } } else /* file exists, path canonicalised */ { /* If it's a directory append trailing '/' */ path_len = ret2; int is_dir = IsDirReal(path); if (is_dir == 1 && path[path_len - 1] != FILE_SEPARATOR) { if (path_len + 2 > sizeof(path)) { goto err_too_long; } PathAppendTrailingSlash(path, path_len); path_len++; } } size_t pos = acl_SortedInsert(&paths_acl, path); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } /* Legacy code */ if (path_len != 1) { DeleteSlash(path); } Auth *ap = GetOrCreateAuth(path, &SV.admit, &SV.admittail); Auth *dp = GetOrCreateAuth(path, &SV.deny, &SV.denytail); AccessPromise_AddAccessConstraints(ctx, pp, &paths_acl->acls[pos], ap, dp); return; err_too_long: Log(LOG_LEVEL_ERR, "Path '%s' in access_rules is too long (%zu > %d), ignoring!", pp->promiser, strlen(pp->promiser), PATH_MAX); return; err_unknown: Log(LOG_LEVEL_ERR, "Failed to canonicalize path '%s' in access_rules, ignoring!", pp->promiser); return; } /*********************************************************************/ void KeepLiteralAccessPromise(EvalContext *ctx, const Promise *pp, const char *type) { Auth *ap, *dp; const char *handle = PromiseGetHandle(pp); if ((handle == NULL) && (strcmp(type,"literal") == 0)) { Log(LOG_LEVEL_ERR, "Access to literal server data requires you to define a promise handle for reference"); return; } if (strcmp(type, "literal") == 0) { Log(LOG_LEVEL_VERBOSE,"Looking at literal access promise '%s', type '%s'", pp->promiser, type); ap = GetOrCreateAuth(handle, &SV.varadmit, &SV.varadmittail); dp = GetOrCreateAuth(handle, &SV.vardeny, &SV.vardenytail); RegisterLiteralServerData(ctx, handle, pp); ap->literal = true; size_t pos = acl_SortedInsert(&literals_acl, handle); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &literals_acl->acls[pos], ap, dp); } else { Log(LOG_LEVEL_VERBOSE,"Looking at context/var access promise '%s', type '%s'", pp->promiser, type); ap = GetOrCreateAuth(pp->promiser, &SV.varadmit, &SV.varadmittail); dp = GetOrCreateAuth(pp->promiser, &SV.vardeny, &SV.vardenytail); if (strcmp(type, "context") == 0) { ap->classpattern = true; size_t pos = acl_SortedInsert(&classes_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &classes_acl->acls[pos], ap, dp); } else if (strcmp(type, "variable") == 0) { ap->variable = true; size_t pos = acl_SortedInsert(&vars_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &vars_acl->acls[pos], ap, dp); } } } /*********************************************************************/ static void KeepQueryAccessPromise(EvalContext *ctx, const Promise *pp) { Auth *ap, *dp; ap = GetOrCreateAuth(pp->promiser, &SV.varadmit, &SV.varadmittail); dp = GetOrCreateAuth(pp->promiser, &SV.vardeny, &SV.vardenytail); RegisterLiteralServerData(ctx, pp->promiser, pp); ap->literal = true; size_t pos = acl_SortedInsert(&query_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } AccessPromise_AddAccessConstraints(ctx, pp, &query_acl->acls[pos], ap, dp); } /*********************************************************************/ static void KeepServerRolePromise(EvalContext *ctx, const Promise *pp) { Rlist *rp; Auth *ap; ap = GetOrCreateAuth(pp->promiser, &SV.roles, &SV.rolestail); for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } switch (cp->rval.type) { case RVAL_TYPE_LIST: for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { /* This is for remote class activation by means of cf-runagent.*/ if (strcmp(cp->lval, CF_REMROLE_BODIES[REMOTE_ROLE_AUTHORIZE].lval) == 0) { PrependItem(&(ap->accesslist), RlistScalarValue(rp), NULL); continue; } } break; case RVAL_TYPE_FNCALL: UnexpectedError("Constraint of type FNCALL is invalid in this context!"); break; default: if ((strcmp(cp->lval, "comment") == 0) || (strcmp(cp->lval, "handle") == 0)) { } else { Log(LOG_LEVEL_ERR, "Right-hand side of authorize promise for '%s' should be a list", pp->promiser); } break; } } } static void InstallServerAuthPath(const char *path, Auth **list, Auth **listtail) { Auth *ptr; ptr = xcalloc(1, sizeof(Auth)); if (*listtail == NULL) /* Last element in the list */ { assert(*list == NULL); *list = ptr; } else { (*listtail)->next = ptr; } char *path_dup = xstrdup(path); #ifdef __MINGW32__ int i; for (i = 0; path_dup[i] != '\0'; i++) { path_dup[i] = ToLower(path_dup[i]); } #endif /* __MINGW32__ */ ptr->path = path_dup; *listtail = ptr; } static Auth *GetAuthPath(const char *path, Auth *list) { Auth *ap; size_t path_len = strlen(path); char unslashed_path[path_len + 1]; memcpy(unslashed_path, path, path_len + 1); #ifdef __MINGW32__ ToLowerStrInplace(unslashed_path); #endif if (path_len != 1) { DeleteSlash(unslashed_path); } for (ap = list; ap != NULL; ap = ap->next) { if (strcmp(ap->path, unslashed_path) == 0) { return ap; } } return NULL; } cfengine-3.6.2/cf-serverd/server_tls.h0000664000175100017510000000304512400110676017416 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SERVER_TLS_H #define CFENGINE_SERVER_TLS_H #include #include /* EvalContext */ #include /* ConnectionInfo */ #include /* ServerConnectionState */ bool ServerTLSInitialize(); void ServerTLSDeInitialize(); int ServerTLSPeek(ConnectionInfo *conn_info); int ServerTLSSessionEstablish(ServerConnectionState *conn); bool BusyWithNewProtocol(EvalContext *ctx, ServerConnectionState *conn); #endif /* CFENGINE_SERVER_TLS_H */ cfengine-3.6.2/cf-serverd/server.c0000664000175100017510000003612612411001073016525 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include /* SendTransaction,ReceiveTransaction */ #include /* TLSVerifyPeer */ #include #include #include #include #include #include /* ServerTLS* */ #include #include #include #include /* LoggingPrivSetContext */ #include #include "server_classic.h" /* BusyWithClassicConnection */ /* The only exported function in this file is the following, used only in cf-serverd-functions.c. void ServerEntryPoint(EvalContext *ctx, const char *ipaddr, ConnectionInfo *info); TODO move this file to cf-serverd-functions.c or most probably server_common.c. */ //****************************************************************** // GLOBAL STATE //****************************************************************** int ACTIVE_THREADS = 0; /* GLOBAL_X */ int CFD_MAXPROCESSES = 0; /* GLOBAL_P */ bool DENYBADCLOCKS = true; /* GLOBAL_P */ int MAXTRIES = 5; /* GLOBAL_P */ bool LOGENCRYPT = false; /* GLOBAL_P */ int COLLECT_INTERVAL = 0; /* GLOBAL_P */ int COLLECT_WINDOW = 10; /* GLOBAL_P */ bool SERVER_LISTEN = true; /* GLOBAL_P */ ServerAccess SV = { 0 }; /* GLOBAL_P */ char CFRUNCOMMAND[CF_MAXVARSIZE] = { 0 }; /* GLOBAL_P */ /******************************************************************/ static void SpawnConnection(EvalContext *ctx, const char *ipaddr, ConnectionInfo *info); static void PurgeOldConnections(Item **list, time_t now); static void *HandleConnection(void *conn); static ServerConnectionState *NewConn(EvalContext *ctx, ConnectionInfo *info); static void DeleteConn(ServerConnectionState *conn); /****************************************************************************/ void ServerEntryPoint(EvalContext *ctx, const char *ipaddr, ConnectionInfo *info) { Log(LOG_LEVEL_VERBOSE, "Obtained IP address of '%s' on socket %d from accept", ipaddr, ConnectionInfoSocket(info)); /* TODO change nonattackerlist, attackerlist and especially connectionlist * to binary searched lists, or remove them from the main thread! */ if (SV.nonattackerlist && !IsMatchItemIn(SV.nonattackerlist, ipaddr)) { Log(LOG_LEVEL_ERR, "Remote host '%s' not in allowconnects, denying connection", ipaddr); } else if (IsMatchItemIn(SV.attackerlist, ipaddr)) { Log(LOG_LEVEL_ERR, "Remote host '%s' is in denyconnects, denying connection", ipaddr); } else { time_t now = time(NULL); if (now == -1) { now = 0; } PurgeOldConnections(&SV.connectionlist, now); bool allow = IsMatchItemIn(SV.multiconnlist, ipaddr); if (!allow && ThreadLock(cft_count)) { /* At most one connection allowed for this host: */ allow = !IsItemIn(SV.connectionlist, ipaddr); ThreadUnlock(cft_count); if (!allow) /* Duplicate. */ { Log(LOG_LEVEL_ERR, "Remote host '%s' is not in allowallconnects, denying second simultaneous connection", ipaddr); } } if (allow) { char intime[PRINTSIZE(now)]; xsnprintf(intime, sizeof(intime), "%jd", (intmax_t) now); if (ThreadLock(cft_count)) { PrependItem(&SV.connectionlist, ipaddr, intime); ThreadUnlock(cft_count); SpawnConnection(ctx, ipaddr, info); return; /* Success */ } } } /* Tidy up on failure: */ if (info->is_call_collect) { CollectCallMarkProcessed(); } cf_closesocket(ConnectionInfoSocket(info)); ConnectionInfoDestroy(&info); } /**********************************************************************/ static void PurgeOldConnections(Item **list, time_t now) /* Some connections might not terminate properly. These should be cleaned every couple of hours. That should be enough to prevent spamming. */ { assert(list != NULL); Log(LOG_LEVEL_DEBUG, "Purging Old Connections..."); if (ThreadLock(cft_count)) { Item *ip, *next; for (ip = *list; ip != NULL; ip = next) { int then = 0; sscanf(ip->classes, "%d", &then); next = ip->next; if (now > then + 7200) { Log(LOG_LEVEL_VERBOSE, "IP address '%s' has been more than two hours in connection list, purging", ip->name); DeleteItem(list, ip); } } ThreadUnlock(cft_count); } Log(LOG_LEVEL_DEBUG, "Done purging old connections"); } /*********************************************************************/ static void SpawnConnection(EvalContext *ctx, const char *ipaddr, ConnectionInfo *info) { ServerConnectionState *conn = NULL; int ret; pthread_t tid; pthread_attr_t threadattrs; conn = NewConn(ctx, info); /* freed in HandleConnection */ int sd_accepted = ConnectionInfoSocket(info); strlcpy(conn->ipaddr, ipaddr, CF_MAX_IP_LEN ); Log(LOG_LEVEL_VERBOSE, "New connection (from %s, sd %d), spawning new thread...", conn->ipaddr, sd_accepted); ret = pthread_attr_init(&threadattrs); if (ret != 0) { Log(LOG_LEVEL_ERR, "SpawnConnection: Unable to initialize thread attributes (%s)", GetErrorStr()); goto err; } ret = pthread_attr_setdetachstate(&threadattrs, PTHREAD_CREATE_DETACHED); if (ret != 0) { Log(LOG_LEVEL_ERR, "SpawnConnection: Unable to set thread to detached state (%s).", GetErrorStr()); goto cleanup; } ret = pthread_attr_setstacksize(&threadattrs, 1024 * 1024); if (ret != 0) { Log(LOG_LEVEL_WARNING, "SpawnConnection: Unable to set thread stack size (%s).", GetErrorStr()); /* Continue with default thread stack size. */ } ret = pthread_create(&tid, &threadattrs, HandleConnection, conn); if (ret != 0) { errno = ret; Log(LOG_LEVEL_ERR, "Unable to spawn worker thread. (pthread_create: %s)", GetErrorStr()); goto cleanup; } cleanup: pthread_attr_destroy(&threadattrs); err: if (ret != 0) { Log(LOG_LEVEL_WARNING, "Thread is being handled from main loop!"); HandleConnection(conn); } } /*********************************************************************/ static void DisableSendDelays(int sockfd) { int yes = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *) &yes, sizeof(yes)) == -1) { Log(LOG_LEVEL_INFO, "Unable to disable Nagle algorithm, expect performance problems. (setsockopt(TCP_NODELAY): %s)", GetErrorStr()); } } /*********************************************************************/ static char *LogHook(LoggingPrivContext *log_ctx, ARG_UNUSED LogLevel level, const char *message) { const char *ipaddr = log_ctx->param; return StringConcatenate(3, ipaddr, "> ", message); } /* TRIES: counts the number of consecutive connections dropped. */ static int TRIES = 0; static void *HandleConnection(void *c) { ServerConnectionState *conn = c; int ret; /* Set logging prefix to be the IP address for all of thread's lifetime. */ /* This stack-allocated struct should be valid for all the lifetime of the * thread. Just make sure that after calling DeleteConn() (which frees * ipaddr), you exit the thread right away. */ LoggingPrivContext log_ctx = { .log_hook = LogHook, .param = conn->ipaddr }; LoggingPrivSetContext(&log_ctx); Log(LOG_LEVEL_INFO, "Accepting connection"); /* We test if number of active threads is greater than max, if so we deny connection, if it happened too many times within a short timeframe then we kill ourself.TODO this test should be done *before* spawning the thread. */ ret = ThreadLock(cft_server_children); if (!ret) { Log(LOG_LEVEL_ERR, "Unable to thread-lock, closing connection!"); goto ret2; } else if (ACTIVE_THREADS > CFD_MAXPROCESSES) { if (TRIES > MAXTRIES) { /* This happens when no thread was freed while we had to drop 5 * (or maxconnections/3) consecutive connections, because none of * the existing threads finished. */ Log(LOG_LEVEL_CRIT, "Server seems to be paralyzed. DOS attack? " "Committing apoptosis..."); ThreadUnlock(cft_server_children); FatalError(conn->ctx, "Terminating"); } TRIES++; Log(LOG_LEVEL_ERR, "Too many threads (%d > %d), dropping connection! " "Increase server maxconnections?", ACTIVE_THREADS, CFD_MAXPROCESSES); ThreadUnlock(cft_server_children); goto ret2; } ACTIVE_THREADS++; TRIES = 0; ThreadUnlock(cft_server_children); DisableSendDelays(ConnectionInfoSocket(conn->conn_info)); /* 20 times the connect() timeout should be enough to avoid MD5 * computation timeouts on big files on old slow Solaris 8 machines. */ SetReceiveTimeout(ConnectionInfoSocket(conn->conn_info), CONNTIMEOUT * 20 * 1000); if (ConnectionInfoConnectionStatus(conn->conn_info) != CF_CONNECTION_ESTABLISHED) { /* Decide the protocol used. */ ret = ServerTLSPeek(conn->conn_info); if (ret == -1) { goto ret1; } } ProtocolVersion protocol_version = ConnectionInfoProtocolVersion(conn->conn_info); if (protocol_version == CF_PROTOCOL_LATEST) { ret = ServerTLSSessionEstablish(conn); if (ret == -1) { goto ret1; } } else if (protocol_version < CF_PROTOCOL_LATEST && protocol_version > CF_PROTOCOL_UNDEFINED) { /* This connection is legacy protocol. Do we allow it? */ if (SV.allowlegacyconnects != NULL && /* By default we do */ !IsMatchItemIn(SV.allowlegacyconnects, conn->ipaddr)) { Log(LOG_LEVEL_INFO, "Connection is not using latest protocol, denying"); goto ret1; } } else { UnexpectedError("HandleConnection: ProtocolVersion %d!", ConnectionInfoProtocolVersion(conn->conn_info)); goto ret1; } /* ========================= MAIN LOOPS ========================= */ if (protocol_version >= CF_PROTOCOL_TLS) { /* New protocol does DNS reverse look up of the connected * IP address, to check hostname access_rules. */ if (NEED_REVERSE_LOOKUP) { ret = getnameinfo((const struct sockaddr *) &conn->conn_info->ss, conn->conn_info->ss_len, conn->revdns, sizeof(conn->revdns), NULL, 0, NI_NAMEREQD); if (ret != 0) { Log(LOG_LEVEL_INFO, "Reverse lookup failed (getnameinfo: %s)!", gai_strerror(ret)); } else { Log(LOG_LEVEL_INFO, "Hostname (reverse looked up): %s", conn->revdns); } } while (BusyWithNewProtocol(conn->ctx, conn)) { } } else if (protocol_version == CF_PROTOCOL_CLASSIC) { while (BusyWithClassicConnection(conn->ctx, conn)) { } } else { assert(!"Bogus protocol version - but we checked that already !"); } /* ============================================================ */ Log(LOG_LEVEL_INFO, "Closed connection, terminating thread"); ret1: ThreadLock(cft_server_children); ACTIVE_THREADS--; ThreadUnlock(cft_server_children); ret2: if (conn->conn_info->is_call_collect) { CollectCallMarkProcessed(); } DeleteConn(conn); return NULL; } /***************************************************************/ /* Toolkit/Class: conn */ /***************************************************************/ static ServerConnectionState *NewConn(EvalContext *ctx, ConnectionInfo *info) { ServerConnectionState *conn = NULL; struct sockaddr_storage addr; socklen_t size = sizeof(addr); if (getsockname(ConnectionInfoSocket(info), (struct sockaddr *)&addr, &size) == -1) { Log(LOG_LEVEL_ERR, "Could not obtain socket address. (getsockname: '%s')", GetErrorStr()); return NULL; } conn = xcalloc(1, sizeof(*conn)); conn->ctx = ctx; conn->conn_info = info; conn->user_data_set = false; conn->rsa_auth = false; conn->hostname[0] = '\0'; conn->ipaddr[0] = '\0'; conn->username[0] = '\0'; conn->revdns[0] = '\0'; conn->session_key = NULL; conn->encryption_type = 'c'; /* Only public files (chmod o+r) accessible to non-root */ conn->maproot = false; conn->uid = CF_UNKNOWN_OWNER; /* Careful, 0 is root! */ return conn; } /** * @note This function is thread-safe. Do NOT wrap it with mutex! */ static void DeleteConn(ServerConnectionState *conn) { int sd = ConnectionInfoSocket(conn->conn_info); if (sd >= 0) { cf_closesocket(sd); } ConnectionInfoDestroy(&conn->conn_info); free(conn->session_key); if (conn->ipaddr != NULL) { if (ThreadLock(cft_count)) { DeleteItemMatching(&SV.connectionlist, conn->ipaddr); ThreadUnlock(cft_count); } } *conn = (ServerConnectionState) {0}; free(conn); } cfengine-3.6.2/cf-serverd/strlist.c0000664000175100017510000004741112411001073016722 0ustar00a10038a1003800000000000000#include "strlist.h" #include #include int memrcmp(const void *p1, const void *p2, size_t n) { const char *s1 = p1; const char *s2 = p2; while (n > 0) { if (*s1 != *s2) { return *s1 - *s2; } s1--; s2--; n--; } return 0; } /***************************** STRING ***************************************/ struct string *string_New(const char *s) { size_t s_len = strlen(s); struct string *p = malloc(sizeof(*p) + s_len + 1); if (p != NULL) { p->len = s_len; /* p->size = s_len + 1; */ memcpy(p->str, s, s_len + 1); } return p; } /* Compare without ordering, returning only true or false. */ bool string_BoolCompare(const struct string *s1, const struct string *s2) { int result = false; if (s1->len == s2->len) { result = (memcmp(s1->str, s2->str, s1->len) == 0); } return result; } /* Compare and return -1, 0, 1 according to alphabetical order. */ int string_Compare(const struct string **sp1, const struct string **sp2) { const struct string *s1 = *sp1; const struct string *s2 = *sp2; int result; if (s1->len < s2->len) { if (s1->len == 0) { return -1; } else { result = memcmp(s1->str, s2->str, s1->len); return result == 0 ? -1 : result; } } else if (s1->len > s2->len) { if (s2->len == 0) { return 1; } else { result = memcmp(s1->str, s2->str, s2->len); return result == 0 ? 1 : result; } } else /* s1->len == s2->len */ { if (s1->len == 0) /* both are zero length strings */ { return 0; } else { return memcmp(s1->str, s2->str, s1->len); } } } /** * Compare two strings starting from their end. */ int string_CompareFromEnd(const struct string **sp1, const struct string **sp2) { const struct string *s1 = *sp1; const struct string *s2 = *sp2; int result; /* Pointer to last char of s1 and s2. */ const char *last1 = &s1->str[s1->len - 1]; const char *last2 = &s2->str[s2->len - 1]; if (s1->len < s2->len) { result = memrcmp(last1, last2, s1->len); return result == 0 ? -1 : result; } else if (s1->len > s2->len) { result = memrcmp(last1, last2, s2->len); return result == 0 ? 1 : result; } else /* s1->len == s2->len */ { return memrcmp(last1, last2, s1->len); } } /** * Compare two strings. * * @return the length of the substring that matches. To find out if the two * strings match exactly you must also check if * s1->len == s2->len == return_value. */ size_t string_MatchCount(const struct string *s1, const struct string *s2) { size_t len = MIN(s1->len, s2->len); size_t i = 0; while (i < len && s1->str[i] == s2->str[i]) { i++; } return i; } /** * Compare two strings starting from their end. * * @return the length of the substring that matches. To find out if the two * strings match exactly you must also check if * s1->len == s2->len == return_value. */ size_t string_ReverseMatchCount(const struct string *s1, const struct string *s2) { size_t len = MIN(s1->len, s2->len); const char *last1 = &s1->str[s1->len - 1]; const char *last2 = &s2->str[s2->len - 1]; size_t i = 0; while (i < len && *last1 == *last2) { i++; } return i; } /***************************** STRLIST **************************************/ size_t StrList_Len(const StrList *sl) { return (sl == NULL) ? 0 : sl->len; } char *StrList_At(const StrList *sl, size_t idx) { assert(sl != NULL); assert(idx < sl->len); return sl->list[idx]->str; } /** * Insert s at the given index, reallocating if necessary. * * @return index of the newly inserted string. If -1 (i.e. MAXINT) is returned * then something went horribly wrong. */ size_t StrList_Insert(StrList **sl, const char *s, size_t idx) { assert(s != NULL); StrList *slp = *sl; /* for clarity only */ size_t new_alloc_len = 0; /* 0 means no reallocation is needed */ if ((slp == NULL && idx > 0) || (slp != NULL && idx > slp->len)) { ProgrammingError("StrList_Insert: Out of bounds index %zu", idx); } if (slp == NULL) { slp = calloc(1, sizeof(*slp) + sizeof(*slp->list) * 1); if (slp == NULL) { return (size_t) -1; } slp->alloc_len = 1; *sl = slp; } else if (slp->alloc_len == 0) { assert (slp->len == 0); new_alloc_len = 1; } else if (slp->len == slp->alloc_len) /* need more space */ { new_alloc_len = slp->alloc_len * 2; } if (new_alloc_len > 0) /* reallocation is needed */ { StrList *p = realloc(slp, sizeof(*p) + sizeof (*p->list) * new_alloc_len); if (p == NULL) { return (size_t) -1; } slp = p; slp->alloc_len = new_alloc_len; *sl = slp; /* Change the caller's variable */ } struct string *str = string_New(s); if (str == NULL) { /* Our list has grown but contents are the same, we can exit clean. */ return (size_t) -1; } assert(slp->len < slp->alloc_len); memmove(&slp->list[idx + 1], &slp->list[idx], /* Make room */ (slp->len - idx) * sizeof(slp->list[idx])); slp->list[idx] = str; /* Insert element */ slp->len++; return idx; } /** * Appends a string to strlist sl, reallocating if necessary. It returns NULL * if reallocation failed, in which case the initial strlist is still valid. * Else it returns a pointer to the newly appended string. * * @note It is valid for sl to be NULL, which is equivalent to being empty. */ size_t StrList_Append(StrList **sl, const char *s) { assert(s != NULL); size_t ret; if (*sl == NULL) { ret = StrList_Insert(sl, s, 0); } else { ret = StrList_Insert(sl, s, (*sl)->len); } return ret; } /** * Trim allocated memory to the minimum needed. Free the whole struct if * deemed necessary. This function will never fail. In the unlikely event that * realloc() fails to reduce the allocated amount, then we just keep the same * memory and log an UnexpectedError. * * @param **sl in-out param, might become NULL if the struct was freed. */ void StrList_Finalise(StrList **sl) { StrList *slp = *sl; /* for clarity only */ if (slp == NULL) { return; } assert(slp->len <= slp->alloc_len); if (slp->len == 0) { free(slp); slp = NULL; } else if (slp->len < slp->alloc_len) { StrList *p = realloc(slp, sizeof(*p) + sizeof (*p->list) * slp->len); if (p == NULL) { UnexpectedError("realloc() returned error even though we asked to *reduce* allocated amount: %s", GetErrorStr()); } else { slp = p; slp->alloc_len = slp->len; } } *sl = slp; } /** * Frees everything and sets the strlist back to NULL, i.e. empty. */ void StrList_Free(StrList **sl) { StrList *slp = *sl; /* for clarity */ if (slp == NULL) { return; } size_t i; for (i = 0; i < slp->len; i++) { free(slp->list[i]); } free(slp); *sl = NULL; } void StrList_Sort(StrList *sl, StringComparatorF comparator) { if (sl != NULL && sl->len > 0) { qsort(sl->list, sl->len, sizeof(sl->list[0]), (int (*)(const void *, const void *)) comparator); } } /** * A different binary search, calls libc's bsearch which also means it's also * limited by it: if element is not found only failure can be returned. * * @return index of match or (size_t) -1 if not found */ size_t StrList_bsearch(const StrList *sl, const struct string *s, StringComparatorF comparator) { if (sl != NULL && sl->len > 0) { struct string **ret = bsearch(&s, sl->list, sl->len, sizeof(sl->list[0]), (int (*)(const void *, const void *)) comparator); struct string * const *base = &sl->list[0]; return (ret == NULL) ? (size_t) -1 : (ret - base); } else { return (size_t) -1; } } /** * Binary search for the string. Obviously the list must be sorted. * If element not found return the position it should be inserted in. * * @param position returns either the index where it was found, or * the index where it should be inserted in to keep it sorted. */ bool StrList_BinarySearchString(const StrList *slp, const struct string *s, size_t *position) { if (slp == NULL) { *position = 0; return false; } size_t min = 0; size_t max = slp->len; /* -1 produces "Not found" if we don't iterate at all (empty list). */ int ret = -1; size_t mid = 0; while (min < max) { mid = min + (max - min) / 2; const struct string *s_mid = slp->list[mid]; ret = string_Compare(&s, &s_mid); if (ret == -1) /* s < list[mid] */ { max = mid; } else if (ret == 1) /* s > list[mid] */ { min = mid + 1; } else /* s == list[mid] */ { break; } } *position = mid; return (ret == 0); } /** * Same as previous, but accepts a raw char* pointer rather than a struct * string. */ bool StrList_BinarySearch(const StrList *slp, const char *s, size_t *position) { if (slp == NULL) { *position = 0; return false; } size_t min = 0; size_t max = slp->len; /* -1 produces "Not found" if we don't iterate at all (empty list). */ int ret = -1; size_t mid = 0; while (min < max) { mid = min + (max - min) / 2; ret = strcmp(s, slp->list[mid]->str); if (ret < 0) /* s < list[mid] */ { max = mid; } else if (ret > 0) /* s > list[mid] */ { min = mid + 1; /* insert *after* the comparison point, if we exit. */ mid++; } else /* s == list[mid] */ { break; } } *position = mid; return (ret == 0); } /* Search a sorted strlist for string s, of s_len, in forward or backward * direction (for the latter the strlist must be sorted with * string_CompareFromEnd()). */ static size_t StrList_BinarySearchExtended(const StrList *sl, const char *s, size_t s_len, bool direction_forward, size_t *min, size_t *max) { size_t found = -1; size_t priv_min = *min; size_t priv_max = *max; assert(s_len > 0); assert(priv_min < priv_max); assert(priv_max <= sl->len); while (priv_min < priv_max) { size_t pos = (priv_max - priv_min) / 2 + priv_min; const char *s2 = sl->list[pos]->str; size_t s2_len = sl->list[pos]->len; size_t min_len = MIN(s_len, s2_len); int match; if (direction_forward) { match = memcmp(s, sl->list[pos]->str, min_len); } else { match = memrcmp(s, &s2[s2_len - 1], min_len); } if (match == 0) { if (sl->list[pos]->len == s_len) { /* Exact match, we know the list has no duplicates so it's * the first match. */ found = pos; /* We might as well not search here later, when s_len is * longer, because longer means it won't match this. */ *min = pos + 1; break; } else { /* Prefix match, sl[pos] is superstring of s. That means * that the exact match may be before. */ priv_max = pos; /* However we keep this as a different case because we must * not change *max, since that position might match a search * later, with bigger s_len. */ } } else if (match < 0) /* s < sl[pos] */ { priv_max = pos; /* This position will never match, no matter how big s_len grows * in later searches. Thus we change *max to avoid searching * here. */ *max = priv_max; } else /* s > sl[pos] */ { priv_min = pos + 1; /* Same here, this position will never match even for longer s. */ *min = priv_min; } } return found; } /** * Find the longest string in #sl that is a prefix of #s (of length #s_len and * not necessarily '\0'-terminated), delimited by #separator. * * @param #s_len can be the length of #s, since #s is not necessarily * '\0'-terminated. Is #s_len is 0, then #s is assumed to be * '\0'-terminated and length is computed with strlen(). * @note this means that #s can't be 0 bytes... * * @example if #sl is { "/a/", "/a/b/", "/a/c/" } and we are searching for * #s="/a/d/f" with #separator='/' then this function returns 0, which * is the index of "/a/". * * @example if #sl is { ".com", ".net", ".cfengine.com" } and we are searching * for #s="cfengine.com" with #separator='.' and * #direction_forward=false, then this function returns 0, which is * the index of ".com". * if we searched for #s="www.cfengine.com" then it would return 2, * which is the index of "www.cfengine.com". */ size_t StrList_SearchLongestPrefix(const StrList *sl, const char *s, size_t s_len, char separator, bool direction_forward) { /* Remember, NULL strlist is equivalent to empty strlist. */ if (sl == NULL) { return (size_t) -1; } if (s_len == 0) { s_len = strlen(s); } size_t found = -1; size_t old_found = -1; size_t s_prefix_len = 0; size_t min = 0; size_t max = sl->len; bool longer_match_possible = true; /* Keep searching until we've searched the whole length, or until there is * no reason to keep going. */ while (longer_match_possible && (s_prefix_len < s_len)) { char *separator_at; if (direction_forward) { /* Find next separator, skipping the previous one. */ separator_at = memchr(&s[s_prefix_len], separator, s_len - s_prefix_len); s_prefix_len = separator_at - &s[0] + 1; } else { /* In this case, SearchLongestPrefix should be SearchLongestSuffix. * Find next separator from the end, skipping the previous one. */ separator_at = memrchr(s, separator, s_len - s_prefix_len); s_prefix_len = &s[s_len - 1] - separator_at + 1; } if (separator_at == NULL) { s_prefix_len = s_len; /* No separator found, use all string */ } /* printf("StrList_SearchLongestPrefix %s: " */ /* "'%s' len:%zu prefix_len:%zu\n", */ /* direction_forward == true ? "forward" : "backward", */ /* s, s_len, s_prefix_len); */ assert(s_prefix_len <= s_len); if (found != (size_t) -1) { /* Keep the smaller string match in case we don't match again. */ old_found = found; } found = StrList_BinarySearchExtended(sl, direction_forward == true ? s : &s[s_len - 1], s_prefix_len, direction_forward, &min, &max); /* If not even a superstring was found then don't keep trying. */ longer_match_possible = (min < max); } found = (found == (size_t) -1) ? old_found : found; /* printf("StrList_SearchLongestPrefix s:'%s' len:%zu found:'%s'\n", */ /* s, s_len, (found == -1) ? "NONE" : sl->list[found]->str); */ return found; } /** * Search within the given strlist for any prefix of the string #s (or exact * match). Not guaranteed it will return the shortest or longest prefix, just * that it will return *fast* once a prefix or exact match is found. * * @param #direction_forward if set to false then search is done for suffix, * not prefix. * @return the index of the found string, (size_t) -1 if not found. */ size_t StrList_SearchForPrefix(const StrList *sl, const char *s, size_t s_len, bool direction_forward) { /* Remember, NULL strlist is equivalent to empty strlist. */ if (sl == NULL) { return (size_t) -1; } if (s_len == 0) { s_len = strlen(s); } size_t min = 0; size_t max = sl->len; size_t chr_idx = 0; size_t prev_chr_idx = chr_idx; while (min < max) { size_t mid = min + (max - min) / 2; const char *s2 = sl->list[mid]->str; size_t s2_len = sl->list[mid]->len; size_t min_len = MIN(s_len, s2_len); /* We didn't find a string in last iteration so now we are at a * different position (mid) in strlist. Nobody guarantees that the * first bytes still match, so we'll have to reset * chr_idx. Nevertheless, we are sure that the first prev_chr_index * bytes match, because they have already matched twice. */ size_t min_chr_idx = MIN(prev_chr_idx, chr_idx); prev_chr_idx = chr_idx; /* Count the matching characters. */ chr_idx = min_chr_idx; if (direction_forward) { while (chr_idx < min_len && s[chr_idx] == s2[chr_idx]) { chr_idx++; } } else { while (chr_idx < min_len && s[s_len - 1 - chr_idx] == s2[s2_len - 1 - chr_idx]) { chr_idx++; } } if (chr_idx == s_len) { if (s_len == s2_len) { /* We found an exact match. */ return mid; } else { assert(s_len < s2_len); /* We found a superstring of s (i.e. s is a prefix). Don't do * anything, need to keep searching for smaller strings. */ } } else if (chr_idx == s2_len) { /* We found a prefix of s. */ return mid; } /* No match, need to keep searching... */ int compar = s[chr_idx] - sl->list[mid]->str[chr_idx]; if (compar < 0) { max = mid; } else { assert(compar > 0); min = mid + 1; } } return (size_t) -1; } cfengine-3.6.2/cf-serverd/cf-serverd.c0000664000175100017510000000443412400110676017264 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include /* CleanReportBookFilterSet() */ #include #include #include static void ThisAgentInit(void) { umask(077); } int main(int argc, char *argv[]) { GenericAgentConfig *config = CheckOpts(argc, argv); EvalContext *ctx = EvalContextNew(); GenericAgentConfigApply(ctx, config); GenericAgentDiscoverContext(ctx, config); Policy *policy = NULL; if (GenericAgentCheckPolicy(config, false, false)) { policy = LoadPolicy(ctx, config); } else if (config->tty_interactive) { exit(EXIT_FAILURE); } else { Log(LOG_LEVEL_ERR, "CFEngine was not able to get confirmation of promises from cf-promises, so going to failsafe"); EvalContextClassPutHard(ctx, "failsafe_fallback", "attribute_name=Errors,source=agent"); GenericAgentConfigSetInputFile(config, GetInputDir(), "failsafe.cf"); policy = LoadPolicy(ctx, config); } ThisAgentInit(); KeepPromises(ctx, policy, config); Summarize(); int threads_left = StartServer(ctx, &policy, config); if (threads_left <= 0) { PolicyDestroy(policy); GenericAgentFinalize(ctx, config); CleanReportBookFilterSet(); } return 0; } cfengine-3.6.2/cf-serverd/server_access.h0000664000175100017510000000667412411001073020060 0ustar00a10038a1003800000000000000 #ifndef CFENGINE_ACCESS_H #define CFENGINE_ACCESS_H #include #include /* StringMap */ #include /* StringMatchFull */ #include "strlist.h" /* StrList */ /** * Access control list referring to one resource, e.g. path, class, variable, * literal. * * @note: Each strlist might be NULL, which is equivalent to having 0 * elements. * * @note: Currently these lists are binary searched, so after filling them up * make sure you call StrList_Sort() to sort them. */ struct admitdeny_acl { StrList *ips; /* admit_ips, deny_ips */ StrList *hostnames; /* admit_hostnames, deny_hostnames */ StrList *keys; /* admit_keys, deny_keys */ }; enum acl_type { ACL_TYPE_PATH, ACL_TYPE_CONTEXT, ACL_TYPE_VARIABLE, ACL_TYPE_LITERAL, ACL_TYPE_QUERY // ACL_TYPE_ROLES }; /** * This is a list of all resorce ACLs for one resource. E.g. for resource_type * == path, this should contain a list of all paths together with a list of * ACLs (struct resource_acl) referring to the relevant path. * * @note Currently this list of resource_names may be binary searched so it * must be sorted once populated. * * @WARNING Remember to store directories *always* with traling '/', else they * won't match for children dirs (on purpose, and this functionality * was built into StrList_SearchLongestPrefix()). */ struct acl { //TODO enum acl_type resource_type; size_t len; /* Length of the following arrays */ size_t alloc_len; /* Used for realloc() economy */ StrList *resource_names; /* paths, class names, variables etc */ struct resource_acl { struct admitdeny_acl admit; struct admitdeny_acl deny; } acls[]; }; /* These acls are set on server startup or when promises change, and are * read-only for the rest of their life, thus are thread-safe. */ /* The paths_acl should be populated with directories having a trailing '/' * to be able to tell apart from files. */ extern struct acl *paths_acl; /* TODO we need the following for optimal ACL lookups in all cases. But first * we need to stop accepting regexes as allowed/denied mathes. */ extern struct acl *classes_acl, *vars_acl, *literals_acl; extern struct acl *query_acl; /* reporting */ //extern struct acl *roles_acl; /* cf-runagent */ size_t ReplaceSpecialVariables(char *buf, size_t buf_size, const char *find1, const char *repl1, const char *find2, const char *repl2, const char *find3, const char *repl3); bool access_CheckResource(const struct resource_acl *acl, const char *ipaddr, const char *hostname, const char *key); size_t acl_SortedInsert(struct acl **a, const char *handle); void acl_Free(struct acl *a); bool acl_CheckExact(const struct acl *acl, const char *req_string, const char *ipaddr, const char *hostname, const char *key); bool acl_CheckPath(const struct acl *acl, const char *reqpath, const char *ipaddr, const char *hostname, const char *key); #endif cfengine-3.6.2/cf-serverd/server_classic.c0000664000175100017510000014064712411001073020232 0ustar00a10038a1003800000000000000#include #include /* BN_* */ #include #include /* IsMatchItemIn */ #include /* IsRegexItemIn */ #include /* ReceiveTransaction,SendTransaction */ #include #include /* ToLowerStrInplace */ #include /* StringMatchFull */ #include /* LastSaw1 */ #include /* HashString */ #include /* HavePublicKey */ #include /* ReceiveCollectCall */ #include "server.h" /* ServerConnectionState */ #include "server_common.h" /* ListPersistentClasses */ /* Functionality needed exclusively for the classic protocol. */ //******************************************************************* // COMMANDS //******************************************************************* typedef enum { PROTOCOL_COMMAND_EXEC, PROTOCOL_COMMAND_AUTH, PROTOCOL_COMMAND_GET, PROTOCOL_COMMAND_OPENDIR, PROTOCOL_COMMAND_SYNC, PROTOCOL_COMMAND_CONTEXTS, PROTOCOL_COMMAND_MD5, PROTOCOL_COMMAND_MD5_SECURE, PROTOCOL_COMMAND_AUTH_PLAIN, PROTOCOL_COMMAND_AUTH_SECURE, PROTOCOL_COMMAND_SYNC_SECURE, PROTOCOL_COMMAND_GET_SECURE, PROTOCOL_COMMAND_VERSION, PROTOCOL_COMMAND_OPENDIR_SECURE, PROTOCOL_COMMAND_VAR, PROTOCOL_COMMAND_VAR_SECURE, PROTOCOL_COMMAND_CONTEXT, PROTOCOL_COMMAND_CONTEXT_SECURE, PROTOCOL_COMMAND_QUERY_SECURE, PROTOCOL_COMMAND_CALL_ME_BACK, PROTOCOL_COMMAND_BAD } ProtocolCommandClassic; static const char *PROTOCOL_CLASSIC[] = { "EXEC", "AUTH", /* old protocol */ "GET", "OPENDIR", "SYNCH", "CLASSES", "MD5", "SMD5", "CAUTH", "SAUTH", "SSYNCH", "SGET", "VERSION", "SOPENDIR", "VAR", "SVAR", "CONTEXT", "SCONTEXT", "SQUERY", "SCALLBACK", NULL }; static ProtocolCommandClassic GetCommandClassic(char *str) { int i; for (i = 0; PROTOCOL_CLASSIC[i] != NULL; i++) { int cmdlen = strlen(PROTOCOL_CLASSIC[i]); if ((strncmp(str, PROTOCOL_CLASSIC[i], cmdlen) == 0) && (str[cmdlen] == ' ' || str[cmdlen] == '\0')) { return i; } } assert (i == PROTOCOL_COMMAND_BAD); return i; } /* 'resolved' argument needs to be at least CF_BUFSIZE long */ static bool ResolveFilename(const char *req_path, char *res_path) { #if !defined _WIN32 if (realpath(req_path, res_path) == NULL) { return false; } #else memset(res_path, 0, CF_BUFSIZE); CompressPath(res_path, req_path); #endif /* Adjust for forward slashes */ MapName(res_path); /* NT has case-insensitive path names */ #ifdef __MINGW32__ int i; for (i = 0; i < strlen(res_path); i++) { res_path[i] = ToLower(res_path[i]); } #endif /* __MINGW32__ */ return true; } static int AccessControl(EvalContext *ctx, const char *req_path, ServerConnectionState *conn, int encrypt) { int access = false; char transrequest[CF_BUFSIZE]; struct stat statbuf; char translated_req_path[CF_BUFSIZE]; char transpath[CF_BUFSIZE]; /* * /var/cfengine -> $workdir translation. */ TranslatePath(translated_req_path, req_path); if (ResolveFilename(translated_req_path, transrequest)) { Log(LOG_LEVEL_VERBOSE, "Filename %s is resolved to %s", translated_req_path, transrequest); } else if ((lstat(translated_req_path, &statbuf) == -1) && !S_ISLNK(statbuf.st_mode)) { Log(LOG_LEVEL_INFO, "Couldn't resolve (realpath: %s) filename: %s", GetErrorStr(), translated_req_path); return false; /* can't continue without transrequest */ } else { Log(LOG_LEVEL_VERBOSE, "Requested file is a dead symbolic link (filename: %s)", translated_req_path); strlcpy(transrequest, translated_req_path, CF_BUFSIZE); } if (lstat(transrequest, &statbuf) == -1) { Log(LOG_LEVEL_INFO, "Couldn't stat (lstat: %s) filename: %s", GetErrorStr(), transrequest); return false; } Log(LOG_LEVEL_DEBUG, "AccessControl, match (%s,%s) encrypt request = %d", transrequest, conn->hostname, encrypt); if (SV.admit == NULL) { Log(LOG_LEVEL_INFO, "cf-serverd access list is empty, no files are visible"); return false; } conn->maproot = false; for (Auth *ap = SV.admit; ap != NULL; ap = ap->next) { int res = false; Log(LOG_LEVEL_DEBUG, "Examining rule in access list (%s,%s)", transrequest, ap->path); /* TODO MapName when constructing this list. */ strlcpy(transpath, ap->path, CF_BUFSIZE); MapName(transpath); /* If everything is allowed */ if ((strcmp(transpath, FILE_SEPARATOR_STR) == 0) || /* or if transpath is a parent directory of transrequest */ (strlen(transrequest) > strlen(transpath) && strncmp(transpath, transrequest, strlen(transpath)) == 0 && transrequest[strlen(transpath)] == FILE_SEPARATOR) || /* or if it's an exact match */ (strcmp(transpath, transrequest) == 0)) { res = true; } /* Exact match means single file to admit */ if (strcmp(transpath, transrequest) == 0) { res = true; } if (res) { Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", transrequest, transpath); if (stat(transpath, &statbuf) == -1) { Log(LOG_LEVEL_INFO, "Warning cannot stat file object %s in admit/grant, or access list refers to dangling link", transpath); continue; } if ((!encrypt) && (ap->encrypt == true)) { Log(LOG_LEVEL_ERR, "File %s requires encrypt connection...will not serve", transpath); access = false; } else { Log(LOG_LEVEL_DEBUG, "Checking whether to map root privileges.."); if ((IsMatchItemIn(ap->maproot, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->maproot, conn->hostname))) { conn->maproot = true; Log(LOG_LEVEL_VERBOSE, "Mapping root privileges to access non-root files"); } if ((IsMatchItemIn(ap->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname))) { access = true; Log(LOG_LEVEL_DEBUG, "Access granted to host: %s", conn->ipaddr); } } break; } } for (Auth *dp = SV.deny; dp != NULL; dp = dp->next) { strlcpy(transpath, dp->path, CF_BUFSIZE); MapName(transpath); /* If everything is denied */ if ((strcmp(transpath, FILE_SEPARATOR_STR) == 0) || /* or if transpath is a parent directory of transrequest */ (strlen(transrequest) > strlen(transpath) && strncmp(transpath, transrequest, strlen(transpath)) == 0 && transrequest[strlen(transpath)] == FILE_SEPARATOR) || /* or if it's an exact match */ (strcmp(transpath, transrequest) == 0)) { if ((IsMatchItemIn(dp->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, dp->accesslist, conn->hostname))) { access = false; Log(LOG_LEVEL_INFO, "Host '%s' in deny list, explicitly denying access to '%s'", conn->ipaddr, transrequest); break; } } } if (access) { Log(LOG_LEVEL_VERBOSE, "Host %s granted access to %s", conn->hostname, req_path); if (encrypt && LOGENCRYPT) { /* Log files that were marked as requiring encryption */ Log(LOG_LEVEL_INFO, "Host %s granted access to %s", conn->hostname, req_path); } } else { Log(LOG_LEVEL_INFO, "Host %s denied access to %s", conn->hostname, req_path); } return access; } /* Checks the "varadmit" legacy ACL. */ static int LiteralAccessControl(EvalContext *ctx, char *in, ServerConnectionState *conn, int encrypt) { Auth *ap; int access = false; char name[CF_BUFSIZE]; name[0] = '\0'; if (strncmp(in, "VAR", 3) == 0) { sscanf(in, "VAR %255[^\n]", name); } else if (strncmp(in, "CALL_ME_BACK", strlen("CALL_ME_BACK")) == 0) { sscanf(in, "CALL_ME_BACK %255[^\n]", name); } else { sscanf(in, "QUERY %128s", name); } conn->maproot = false; for (ap = SV.varadmit; ap != NULL; ap = ap->next) { Log(LOG_LEVEL_VERBOSE, "Examining rule in access list (%s,%s)?", name, ap->path); if (strcmp(ap->path, name) == 0) /* exact match */ { Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", name, ap->path); if ((!ap->literal) && (!ap->variable)) { Log(LOG_LEVEL_ERR, "Variable/query '%s' requires a literal server item...cannot set variable directly by path", ap->path); access = false; break; } if ((!encrypt) && (ap->encrypt == true)) { Log(LOG_LEVEL_ERR, "Variable %s requires encrypt connection...will not serve", name); access = false; break; } else { Log(LOG_LEVEL_DEBUG, "Checking whether to map root privileges"); if ((IsMatchItemIn(ap->maproot, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->maproot, conn->hostname))) { conn->maproot = true; Log(LOG_LEVEL_VERBOSE, "Mapping root privileges"); } else { Log(LOG_LEVEL_VERBOSE, "No root privileges granted"); } if ((IsMatchItemIn(ap->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname))) { access = true; Log(LOG_LEVEL_DEBUG, "Access privileges - match found"); } } } } for (ap = SV.vardeny; ap != NULL; ap = ap->next) { if (strcmp(ap->path, name) == 0) { if ((IsMatchItemIn(ap->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname))) { access = false; Log(LOG_LEVEL_VERBOSE, "Host %s explicitly denied access to %s", conn->hostname, name); break; } } } if (access) { Log(LOG_LEVEL_VERBOSE, "Host %s granted access to literal '%s'", conn->hostname, name); if (encrypt && LOGENCRYPT) { /* Log files that were marked as requiring encryption */ Log(LOG_LEVEL_INFO, "Host %s granted access to literal '%s'", conn->hostname, name); } } else { Log(LOG_LEVEL_VERBOSE, "Host %s denied access to literal '%s'", conn->hostname, name); } return access; } /* Checks the "varadmit" legacy ACL. */ static Item *ContextAccessControl(EvalContext *ctx, char *in, ServerConnectionState *conn, int encrypt) { Auth *ap; int access = false; char client_regex[CF_BUFSIZE]; Item *ip, *matches = NULL; int ret = sscanf(in, "CONTEXT %255[^\n]", client_regex); Item *persistent_classes = ListPersistentClasses(); if (ret != 1 || persistent_classes == NULL) { return NULL; } for (ip = persistent_classes; ip != NULL; ip = ip->next) { /* Does the class match the regex that the agent requested? */ if (StringMatchFull(client_regex, ip->name)) { for (ap = SV.varadmit; ap != NULL; ap = ap->next) { /* Does the class match any of the regex in ACLs? */ if (StringMatchFull(ap->path, ip->name)) { Log(LOG_LEVEL_VERBOSE, "Found a matching rule in access list (%s in %s)", ip->name, ap->path); if (ap->classpattern == false) { Log(LOG_LEVEL_ERR, "Context %s requires a literal server item... " "cannot set variable directly by path", ap->path); access = false; continue; } if ((!encrypt) && (ap->encrypt == true)) { Log(LOG_LEVEL_ERR, "Context %s requires encrypt connection... " "will not serve", ip->name); access = false; break; } else { Log(LOG_LEVEL_DEBUG, "Checking whether to map root privileges"); if ((IsMatchItemIn(ap->maproot, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->maproot, conn->hostname))) { conn->maproot = true; Log(LOG_LEVEL_VERBOSE, "Mapping root privileges"); } else { Log(LOG_LEVEL_VERBOSE, "No root privileges granted"); } if ((IsMatchItemIn(ap->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname))) { access = true; Log(LOG_LEVEL_DEBUG, "Access privileges - match found"); } } } } for (ap = SV.vardeny; ap != NULL; ap = ap->next) { if (strcmp(ap->path, ip->name) == 0) { if ((IsMatchItemIn(ap->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname))) { access = false; Log(LOG_LEVEL_VERBOSE, "Host %s explicitly denied access to context %s", conn->hostname, ip->name); break; } } } if (access) { Log(LOG_LEVEL_VERBOSE, "Host %s granted access to context '%s'", conn->hostname, ip->name); AppendItem(&matches, ip->name, NULL); if (encrypt && LOGENCRYPT) { /* Log files that were marked as requiring encryption */ Log(LOG_LEVEL_INFO, "Host %s granted access to context '%s'", conn->hostname, ip->name); } } else { Log(LOG_LEVEL_VERBOSE, "Host %s denied access to context '%s'", conn->hostname, ip->name); } } } DeleteItemList(persistent_classes); return matches; } static int cfscanf(char *in, int len1, int len2, char *out1, char *out2, char *out3) { int len3 = 0; char *sp; sp = in; memcpy(out1, sp, len1); out1[len1] = '\0'; sp += len1 + 1; memcpy(out2, sp, len2); sp += len2 + 1; len3 = strlen(sp); memcpy(out3, sp, len3); out3[len3] = '\0'; return (len1 + len2 + len3 + 2); } static void SetConnectionData(ServerConnectionState *conn, char *buf) { char ipstring[CF_MAXVARSIZE], fqname[CF_MAXVARSIZE], username[CF_MAXVARSIZE]; Log(LOG_LEVEL_DEBUG, "Connecting host identifies itself as '%s'", buf); memset(ipstring, 0, CF_MAXVARSIZE); memset(fqname, 0, CF_MAXVARSIZE); memset(username, 0, CF_MAXVARSIZE); sscanf(buf, "%255s %255s %255s", ipstring, fqname, username); /* The "ipstring" that the client sends is currently *ignored* as * conn->ipaddr is always set from the connecting socket address. */ Log(LOG_LEVEL_DEBUG, "(ipstring=[%s],fqname=[%s],username=[%s],socket=[%s])", ipstring, fqname, username, conn->ipaddr); ToLowerStrInplace(fqname); strlcpy(conn->hostname, fqname, CF_MAXVARSIZE); SetConnIdentity(conn, username); } static int CheckStoreKey(ServerConnectionState *conn, RSA *key) { RSA *savedkey; const char *udigest = KeyPrintableHash(ConnectionInfoKey(conn->conn_info)); assert(udigest != NULL); if ((savedkey = HavePublicKey(conn->username, conn->ipaddr, udigest))) { Log(LOG_LEVEL_VERBOSE, "A public key was already known from %s/%s - no trust required", conn->hostname, conn->ipaddr); if ((BN_cmp(savedkey->e, key->e) == 0) && (BN_cmp(savedkey->n, key->n) == 0)) { Log(LOG_LEVEL_VERBOSE, "The public key identity was confirmed as %s@%s", conn->username, conn->hostname); SendTransaction(conn->conn_info, "OK: key accepted", 0, CF_DONE); RSA_free(savedkey); return true; } } /* Finally, if we're still here then the key is new (not in ppkeys * directory): Allow access only if host is listed in "trustkeysfrom" body * server control option. */ if ((SV.trustkeylist != NULL) && (IsMatchItemIn(SV.trustkeylist, conn->ipaddr))) { Log(LOG_LEVEL_VERBOSE, "Host %s/%s was found in the list of hosts to trust", conn->hostname, conn->ipaddr); SendTransaction(conn->conn_info, "OK: unknown key was accepted on trust", 0, CF_DONE); SavePublicKey(conn->username, udigest, key); return true; } else { Log(LOG_LEVEL_VERBOSE, "No previous key found, and unable to accept this one on trust"); SendTransaction(conn->conn_info, "BAD: key could not be accepted on trust", 0, CF_DONE); return false; } } static int AuthenticationDialogue(ServerConnectionState *conn, char *recvbuffer, int recvlen) { unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; if ((PRIVKEY == NULL) || (PUBKEY == NULL)) { Log(LOG_LEVEL_ERR, "No public/private key pair exists, create one with cf-key"); return false; } int PRIVKEY_size = RSA_size(PRIVKEY); int digestLen; HashMethod digestType; if (FIPS_MODE) { digestType = CF_DEFAULT_DIGEST; digestLen = CF_DEFAULT_DIGEST_LEN; } else { digestType = HASH_METHOD_MD5; digestLen = CF_MD5_LEN; } /* parameters received in SAUTH command */ char iscrypt, enterprise_field; /* proposition C1 - SAUTH command */ { char sauth[10] = { 0 }; unsigned int crypt_len; /* received encrypted challenge length */ unsigned int challenge_len; /* challenge length after decryption */ int nparam = sscanf(recvbuffer, "%9s %c %u %u %c", sauth, &iscrypt, &crypt_len, &challenge_len, &enterprise_field); if (nparam >= 1 && strcmp(sauth, "SAUTH") != 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "was expecting SAUTH command but got '%s'", sauth); return false; } if (nparam != 5 && nparam != 4) { Log(LOG_LEVEL_ERR, "Authentication failure: " "peer sent only %d arguments to SAUTH command", nparam - 1); return false; } /* CFEngine 2 had no enterprise/community differentiation. */ if (nparam == 4) { Log(LOG_LEVEL_VERBOSE, "Peer sent only 4 parameters, " "assuming it is a legacy community client"); enterprise_field = 'c'; } if ((challenge_len == 0) || (crypt_len == 0)) { Log(LOG_LEVEL_ERR, "Authentication failure: received unexpected challenge length " "(%u that decrypts to %u bytes)", challenge_len, crypt_len); return false; } if (crypt_len > CF_NONCELEN * 2) { Log(LOG_LEVEL_ERR, "Authentication failure: " "received encrypted challenge is too long " "(%d bytes)", crypt_len); return false; } if (challenge_len > CF_NONCELEN * 2) { Log(LOG_LEVEL_ERR, "Authentication failure: " "received challenge is too long (%u bytes)", challenge_len); return false; } Log(LOG_LEVEL_DEBUG, "Challenge encryption = %c, challenge_len = %u, crypt_len = %u", iscrypt, challenge_len, crypt_len); char *challenge; char decrypted_challenge[PRIVKEY_size]; if (iscrypt == 'y') /* challenge came encrypted */ { if (recvlen < CF_RSA_PROTO_OFFSET + crypt_len) { Log(LOG_LEVEL_ERR, "Authentication failure: peer sent only %d " "bytes as encrypted challenge but claims to have sent %u bytes", recvlen - CF_RSA_PROTO_OFFSET, crypt_len); } int ret = RSA_private_decrypt(crypt_len, recvbuffer + CF_RSA_PROTO_OFFSET, decrypted_challenge, PRIVKEY, RSA_PKCS1_PADDING); if (ret < 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "private decrypt of received challenge failed (%s)", CryptoLastErrorString()); Log(LOG_LEVEL_ERR, "Probably the client has wrong public key for this server"); return false; } if (ret != challenge_len) { Log(LOG_LEVEL_ERR, "Authentication failure: " "private decrypt of received challenge (%u bytes) " "resulted in %d bytes instead of promised %u bytes", crypt_len, ret, challenge_len); return false; } challenge = decrypted_challenge; } else /* challenge came unencrypted */ { if (challenge_len != crypt_len) { Log(LOG_LEVEL_ERR, "Authentication failure: peer sent illegal challenge " "(challenge_len %u != crypt_len %u)", challenge_len, crypt_len); return false; } if (recvlen < CF_RSA_PROTO_OFFSET + challenge_len) { Log(LOG_LEVEL_ERR, "Authentication failure: peer sent only %d " "bytes as challenge but claims to have sent %u bytes", recvlen - CF_RSA_PROTO_OFFSET, challenge_len); return false; } challenge = &recvbuffer[CF_RSA_PROTO_OFFSET]; } /* Client's ID is now established by key or trusted, reply with digest */ HashString(challenge, challenge_len, digest, digestType); } /* proposition C2 - Receive client's public key modulus */ RSA *newkey = RSA_new(); { int len_n = ReceiveTransaction(conn->conn_info, recvbuffer, NULL); if (len_n == -1) { Log(LOG_LEVEL_ERR, "Authentication failure: " "error while receiving public key modulus"); RSA_free(newkey); return false; } if (len_n == 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "connection was closed while receiving public key modulus"); RSA_free(newkey); return false; } if ((newkey->n = BN_mpi2bn(recvbuffer, len_n, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Authentication failure: " "private decrypt of received public key modulus failed " "(%s)", CryptoLastErrorString()); RSA_free(newkey); return false; } } /* proposition C3 - Receive client's public key exponent. */ { int len_e = ReceiveTransaction(conn->conn_info, recvbuffer, NULL); if (len_e == -1) { Log(LOG_LEVEL_ERR, "Authentication failure: " "error while receiving public key exponent"); RSA_free(newkey); return false; } if (len_e == 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "connection was closed while receiving public key exponent"); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(recvbuffer, len_e, NULL)) == NULL) { Log(LOG_LEVEL_ERR, "Authentication failure: " "private decrypt of received public key exponent failed " "(%s)", CryptoLastErrorString()); RSA_free(newkey); return false; } } /* Compute and store hash of the client's public key. */ { Key *key = KeyNew(newkey, CF_DEFAULT_DIGEST); conn->conn_info->remote_key = key; Log(LOG_LEVEL_VERBOSE, "Peer's identity is: %s", KeyPrintableHash(key)); LastSaw1(conn->ipaddr, KeyPrintableHash(key), LAST_SEEN_ROLE_ACCEPT); /* Do we want to trust the received key? */ if (!CheckStoreKey(conn, newkey)) /* conceals proposition S1 */ { return false; } } /* proposition S2 - reply with digest of challenge. */ { Log(LOG_LEVEL_DEBUG, "Sending challenge response"); SendTransaction(conn->conn_info, digest, digestLen, CF_DONE); } /* proposition S3 - send counter-challenge */ { BIGNUM *counter_challenge_BN = BN_new(); if (counter_challenge_BN == NULL) { Log(LOG_LEVEL_ERR, "Authentication failure: " "cannot allocate BIGNUM structure for counter-challenge"); return false; } BN_rand(counter_challenge_BN, CF_NONCELEN, 0, 0); char counter_challenge[CF_BUFSIZE]; int counter_challenge_len = BN_bn2mpi(counter_challenge_BN, counter_challenge); BN_free(counter_challenge_BN); /* Compute counter-challenge digest. */ HashString(counter_challenge, counter_challenge_len, digest, digestType); /* Encryption buffer is always RSA_size(key) and buffer needs 11 bytes, * see RSA_public_encrypt manual. */ int encrypted_len = RSA_size(newkey); char encrypted_counter_challenge[encrypted_len]; assert(counter_challenge_len < encrypted_len - 11); int ret = RSA_public_encrypt(counter_challenge_len, counter_challenge, encrypted_counter_challenge, newkey, RSA_PKCS1_PADDING); if (ret != encrypted_len) { if (ret == -1) { Log(LOG_LEVEL_ERR, "Authentication failure: " "public encryption of counter-challenge failed " "(%s)", CryptoLastErrorString()); } else { Log(LOG_LEVEL_ERR, "Authentication failure: " "public encryption of counter-challenge failed " "(result length %d but should be %d)", ret, encrypted_len); } return false; } Log(LOG_LEVEL_DEBUG, "Sending counter-challenge"); SendTransaction(conn->conn_info, encrypted_counter_challenge, encrypted_len, CF_DONE); } /* proposition S4, S5 - If the client doesn't have our public key, send it. */ { if (iscrypt != 'y') { Log(LOG_LEVEL_DEBUG, "Sending server's public key"); char bignum_buf[CF_BUFSIZE] = { 0 }; /* proposition S4 - conditional */ int len_n = BN_bn2mpi(PUBKEY->n, bignum_buf); SendTransaction(conn->conn_info, bignum_buf, len_n, CF_DONE); /* proposition S5 - conditional */ int len_e = BN_bn2mpi(PUBKEY->e, bignum_buf); SendTransaction(conn->conn_info, bignum_buf, len_e, CF_DONE); } } /* proposition C4 - Receive counter-challenge response. */ { char recv_buf[CF_BUFSIZE] = { 0 }; int recv_len = ReceiveTransaction(conn->conn_info, recv_buf, NULL); if (recv_len < digestLen) { if (recv_len < 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "error receiving counter-challenge response"); } else if (recv_len == 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "connection was closed while receiving counter-challenge response"); } else /* 0 < recv_len < expected_len */ { Log(LOG_LEVEL_ERR, "Authentication failure: " "error receiving counter-challenge response, " "only got %d out of %d bytes", recv_len, digestLen); } return false; } if (HashesMatch(digest, recv_buf, digestType)) { Log(LOG_LEVEL_VERBOSE, "Authentication of client %s/%s achieved", conn->hostname, conn->ipaddr); } else { Log(LOG_LEVEL_ERR, "Authentication failure: " "counter-challenge response was incorrect"); return false; } } /* proposition C5 - Receive session key */ { Log(LOG_LEVEL_DEBUG, "Receiving session key from client..."); char session_key[CF_BUFSIZE] = { 0 }; int session_key_size = CfSessionKeySize(enterprise_field); int keylen = ReceiveTransaction(conn->conn_info, session_key, NULL); Log(LOG_LEVEL_DEBUG, "Received encrypted session key of %d bytes, " "should decrypt to %d bytes", keylen, session_key_size); if ((keylen <= 0) || (keylen > CF_BUFSIZE / 2)) { if (keylen == 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "connection was closed while receiving session key"); } else if (keylen > CF_BUFSIZE / 2) { Log(LOG_LEVEL_ERR, "Authentication failure: " "session key received is too long (%d bytes)", keylen); } else /* keylen < 0 */ { Log(LOG_LEVEL_ERR, "Authentication failure: " "error receiving session key"); } return false; } conn->session_key = xmalloc(session_key_size); conn->encryption_type = enterprise_field; if (keylen == CF_BLOWFISHSIZE) /* Support the old non-ecnrypted for upgrade */ { memcpy(conn->session_key, session_key, session_key_size); } else { char decrypted_session_key[PRIVKEY_size]; int ret = RSA_private_decrypt(keylen, session_key, decrypted_session_key, PRIVKEY, RSA_PKCS1_PADDING); if (ret != session_key_size) { if (ret < 0) { Log(LOG_LEVEL_ERR, "Authentication failure: " "private decrypt of session key failed " "(%s)", CryptoLastErrorString()); } else { Log(LOG_LEVEL_ERR, "Authentication failure: " "session key decrypts to invalid size, " "expected %d but got %d bytes", session_key_size, ret); } return false; } memcpy(conn->session_key, decrypted_session_key, session_key_size); } } return true; } int BusyWithClassicConnection(EvalContext *ctx, ServerConnectionState *conn) { time_t tloc, trem = 0; char recvbuffer[CF_BUFSIZE + CF_BUFEXT], check[CF_BUFSIZE]; char sendbuffer[CF_BUFSIZE] = { 0 }; char filename[CF_BUFSIZE], buffer[CF_BUFSIZE], args[CF_BUFSIZE], out[CF_BUFSIZE]; long time_no_see = 0; unsigned int len = 0; int drift, plainlen, received, encrypted = 0; ServerFileGetState get_args; Item *classes; memset(recvbuffer, 0, CF_BUFSIZE + CF_BUFEXT); memset(&get_args, 0, sizeof(get_args)); received = ReceiveTransaction(conn->conn_info, recvbuffer, NULL); if (received == -1 || received == 0) { return false; } if (strlen(recvbuffer) == 0) { Log(LOG_LEVEL_WARNING, "Got NULL transmission, skipping!"); return true; } /* Don't process request if we're signalled to exit. */ if (IsPendingTermination()) { Log(LOG_LEVEL_VERBOSE, "Server must exit, closing connection"); return false; } ProtocolCommandClassic command = GetCommandClassic(recvbuffer); switch (command) { /* Plain text authentication; this MUST be the first command client using classic protocol is sending. */ case PROTOCOL_COMMAND_AUTH_PLAIN: SetConnectionData(conn, (char *) (recvbuffer + strlen("CAUTH "))); if (conn->username == NULL || !IsUserNameValid(conn->username)) { Log(LOG_LEVEL_INFO, "Client is sending wrong username: %s", conn->username); RefuseAccess(conn, recvbuffer); return false; } /* This is used only for forcing correct state of state machine while connecting and authenticating user using classic protocol. */ conn->user_data_set = true; return true; /* This MUST be exactly second command client using classic protocol is sending. This is where key agreement takes place. */ case PROTOCOL_COMMAND_AUTH_SECURE: /* First command was omitted by client; this is protocol violation. */ if (!conn->user_data_set) { Log(LOG_LEVEL_INFO, "Client is not verified; rejecting connection"); RefuseAccess(conn, recvbuffer); return false; } conn->rsa_auth = AuthenticationDialogue(conn, recvbuffer, received); if (!conn->rsa_auth) { Log(LOG_LEVEL_INFO, "Auth dialogue error"); RefuseAccess(conn, recvbuffer); return false; } return true; default: break; } /* At this point we should have both user_data_set and rsa_auth set to perform any operation. We can check only for second one as without first it won't be set up. */ if (!conn->rsa_auth) { Log(LOG_LEVEL_INFO, "REFUSAL due to no RSA authentication (command: %d)", command); RefuseAccess(conn, recvbuffer); return false; } /* We have to have key at this point. */ assert(conn->session_key); /* At this point we can safely do next switch and make sure user is * authenticated. */ switch (command) { case PROTOCOL_COMMAND_EXEC: memset(args, 0, CF_BUFSIZE); sscanf(recvbuffer, "EXEC %255[^\n]", args); if (!AllowedUser(conn->username)) { Log(LOG_LEVEL_INFO, "REFUSAL due to non-allowed user"); RefuseAccess(conn, recvbuffer); return false; } if (!AccessControl(ctx, CommandArg0(CFRUNCOMMAND), conn, false)) { Log(LOG_LEVEL_INFO, "REFUSAL due to denied access to requested object"); RefuseAccess(conn, recvbuffer); return false; } if (!MatchClasses(ctx, conn)) { Log(LOG_LEVEL_INFO, "REFUSAL due to failed class/context match"); Terminate(conn->conn_info); return false; } DoExec(ctx, conn, args); Terminate(conn->conn_info); return false; case PROTOCOL_COMMAND_VERSION: snprintf(sendbuffer, sizeof(sendbuffer), "OK: %s", Version()); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return conn->user_data_set; case PROTOCOL_COMMAND_GET: memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "GET %d %[^\n]", &(get_args.buf_size), filename); if ((get_args.buf_size < 0) || (get_args.buf_size > CF_BUFSIZE)) { Log(LOG_LEVEL_INFO, "GET buffer out of bounds"); RefuseAccess(conn, recvbuffer); return false; } if (!AccessControl(ctx, filename, conn, false)) { Log(LOG_LEVEL_INFO, "Access denied to get object"); RefuseAccess(conn, recvbuffer); return true; } memset(sendbuffer, 0, sizeof(sendbuffer)); if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } get_args.conn = conn; get_args.encrypt = false; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfGetFile(&get_args); return true; case PROTOCOL_COMMAND_GET_SECURE: memset(buffer, 0, CF_BUFSIZE); sscanf(recvbuffer, "SGET %u %d", &len, &(get_args.buf_size)); if (received != len + CF_PROTO_OFFSET) { Log(LOG_LEVEL_VERBOSE, "Protocol error SGET"); RefuseAccess(conn, recvbuffer); return false; } plainlen = DecryptString(conn->encryption_type, recvbuffer + CF_PROTO_OFFSET, buffer, conn->session_key, len); cfscanf(buffer, strlen("GET"), strlen("dummykey"), check, sendbuffer, filename); if (strcmp(check, "GET") != 0) { Log(LOG_LEVEL_INFO, "SGET/GET problem"); RefuseAccess(conn, recvbuffer); return true; } if ((get_args.buf_size < 0) || (get_args.buf_size > 8192)) { Log(LOG_LEVEL_INFO, "SGET bounding error"); RefuseAccess(conn, recvbuffer); return false; } if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } Log(LOG_LEVEL_DEBUG, "Confirm decryption, and thus validity of caller"); Log(LOG_LEVEL_DEBUG, "SGET '%s' with blocksize %d", filename, get_args.buf_size); if (!AccessControl(ctx, filename, conn, true)) { Log(LOG_LEVEL_INFO, "Access control error"); RefuseAccess(conn, recvbuffer); return false; } memset(sendbuffer, 0, sizeof(sendbuffer)); get_args.conn = conn; get_args.encrypt = true; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfEncryptGetFile(&get_args); return true; case PROTOCOL_COMMAND_OPENDIR_SECURE: memset(buffer, 0, CF_BUFSIZE); sscanf(recvbuffer, "SOPENDIR %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_VERBOSE, "Protocol error OPENDIR: %d", len); RefuseAccess(conn, recvbuffer); return false; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "OPENDIR", 7) != 0) { Log(LOG_LEVEL_INFO, "Opendir failed to decrypt"); RefuseAccess(conn, recvbuffer); return true; } memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "OPENDIR %[^\n]", filename); if (!AccessControl(ctx, filename, conn, true)) /* opendir don't care about privacy */ { Log(LOG_LEVEL_INFO, "Access error"); RefuseAccess(conn, recvbuffer); return false; } CfSecOpenDirectory(conn, sendbuffer, filename); return true; case PROTOCOL_COMMAND_OPENDIR: memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "OPENDIR %[^\n]", filename); if (!AccessControl(ctx, filename, conn, true)) /* opendir don't care about privacy */ { Log(LOG_LEVEL_INFO, "DIR access error"); RefuseAccess(conn, recvbuffer); return false; } CfOpenDirectory(conn, sendbuffer, filename); return true; case PROTOCOL_COMMAND_SYNC_SECURE: memset(buffer, 0, CF_BUFSIZE); sscanf(recvbuffer, "SSYNCH %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_VERBOSE, "Protocol error SSYNCH: %d", len); RefuseAccess(conn, recvbuffer); return false; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (plainlen < 0) { DebugBinOut((char *) conn->session_key, 32, "Session key"); Log(LOG_LEVEL_ERR, "Bad decrypt (%d)", len); } if (strncmp(recvbuffer, "SYNCH", 5) != 0) { Log(LOG_LEVEL_INFO, "No synch"); RefuseAccess(conn, recvbuffer); return true; } /* roll through, no break */ case PROTOCOL_COMMAND_SYNC: memset(filename, 0, CF_BUFSIZE); sscanf(recvbuffer, "SYNCH %ld STAT %[^\n]", &time_no_see, filename); trem = (time_t) time_no_see; if ((time_no_see == 0) || (filename[0] == '\0')) { break; } if ((tloc = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_INFO, "Couldn't read system clock. (time: %s)", GetErrorStr()); SendTransaction(conn->conn_info, "BAD: clocks out of synch", 0, CF_DONE); return true; } drift = (int) (tloc - trem); if (!AccessControl(ctx, filename, conn, true)) { Log(LOG_LEVEL_INFO, "Access control in sync"); RefuseAccess(conn, recvbuffer); return true; } if (DENYBADCLOCKS && (drift * drift > CLOCK_DRIFT * CLOCK_DRIFT)) { snprintf(sendbuffer, sizeof(sendbuffer), "BAD: Clocks are too far unsynchronized %ld/%ld", (long) tloc, (long) trem); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return true; } else { Log(LOG_LEVEL_DEBUG, "Clocks were off by %ld", (long) tloc - (long) trem); StatFile(conn, sendbuffer, filename); } return true; case PROTOCOL_COMMAND_MD5_SECURE: sscanf(recvbuffer, "SMD5 %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decryption error"); RefuseAccess(conn, recvbuffer); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "MD5", 3) != 0) { Log(LOG_LEVEL_INFO, "MD5 protocol error"); RefuseAccess(conn, recvbuffer); return false; } encrypted = true; /* roll through, no break */ case PROTOCOL_COMMAND_MD5: memset(filename, 0, sizeof(filename)); sscanf(recvbuffer, "MD5 %[^\n]", filename); if (!AccessControl(ctx, filename, conn, encrypted)) { Log(LOG_LEVEL_INFO, "Access denied to get object"); RefuseAccess(conn, recvbuffer); return true; } assert(CF_DEFAULT_DIGEST_LEN <= EVP_MAX_MD_SIZE); unsigned char digest[EVP_MAX_MD_SIZE + 1]; assert(CF_BUFSIZE + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN <= sizeof(recvbuffer)); memcpy(digest, recvbuffer + strlen(recvbuffer) + CF_SMALL_OFFSET, CF_DEFAULT_DIGEST_LEN); CompareLocalHash(filename, digest, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return true; case PROTOCOL_COMMAND_VAR_SECURE: sscanf(recvbuffer, "SVAR %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error SVAR"); RefuseAccess(conn, "decrypt error SVAR"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); encrypted = true; if (strncmp(recvbuffer, "VAR", 3) != 0) { Log(LOG_LEVEL_INFO, "VAR protocol defect"); RefuseAccess(conn, "decryption failure"); return false; } /* roll through, no break */ case PROTOCOL_COMMAND_VAR: if (!LiteralAccessControl(ctx, recvbuffer, conn, encrypted)) { Log(LOG_LEVEL_INFO, "Literal access failure"); RefuseAccess(conn, recvbuffer); return false; } GetServerLiteral(ctx, conn, sendbuffer, recvbuffer, encrypted); return true; case PROTOCOL_COMMAND_CONTEXT_SECURE: sscanf(recvbuffer, "SCONTEXT %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error SCONTEXT, len,received = %d,%d", len, received); RefuseAccess(conn, "decrypt error SCONTEXT"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); encrypted = true; if (strncmp(recvbuffer, "CONTEXT", 7) != 0) { Log(LOG_LEVEL_INFO, "CONTEXT protocol defect..."); RefuseAccess(conn, "Decryption failed?"); return false; } /* roll through, no break */ case PROTOCOL_COMMAND_CONTEXT: if ((classes = ContextAccessControl(ctx, recvbuffer, conn, encrypted)) == NULL) { Log(LOG_LEVEL_INFO, "Context access failure on %s", recvbuffer); RefuseAccess(conn, recvbuffer); return false; } ReplyServerContext(conn, encrypted, classes); return true; case PROTOCOL_COMMAND_QUERY_SECURE: sscanf(recvbuffer, "SQUERY %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error SQUERY"); RefuseAccess(conn, "decrypt error SQUERY"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "QUERY", 5) != 0) { Log(LOG_LEVEL_INFO, "QUERY protocol defect"); RefuseAccess(conn, "decryption failure"); return false; } if (!LiteralAccessControl(ctx, recvbuffer, conn, true)) { Log(LOG_LEVEL_INFO, "Query access failure"); RefuseAccess(conn, recvbuffer); return false; } if (GetServerQuery(conn, recvbuffer, true)) /* always encrypt */ { return true; } break; case PROTOCOL_COMMAND_CALL_ME_BACK: sscanf(recvbuffer, "SCALLBACK %u", &len); if ((len >= sizeof(out)) || (received != (len + CF_PROTO_OFFSET))) { Log(LOG_LEVEL_INFO, "Decrypt error CALL_ME_BACK"); return true; } memcpy(out, recvbuffer + CF_PROTO_OFFSET, len); plainlen = DecryptString(conn->encryption_type, out, recvbuffer, conn->session_key, len); if (strncmp(recvbuffer, "CALL_ME_BACK collect_calls", strlen("CALL_ME_BACK collect_calls")) != 0) { Log(LOG_LEVEL_INFO, "CALL_ME_BACK protocol defect"); return false; } if (!LiteralAccessControl(ctx, recvbuffer, conn, true)) { Log(LOG_LEVEL_INFO, "Query access failure"); return false; } ReceiveCollectCall(conn); /* On success that returned true; otherwise, it did all * relevant Log()ging. Either way, it closed the connection, * so we're no longer busy with it: */ return false; case PROTOCOL_COMMAND_AUTH_PLAIN: case PROTOCOL_COMMAND_AUTH_SECURE: case PROTOCOL_COMMAND_AUTH: case PROTOCOL_COMMAND_CONTEXTS: case PROTOCOL_COMMAND_BAD: Log(LOG_LEVEL_WARNING, "Unexpected protocol command"); } strcpy(sendbuffer, "BAD: Request denied"); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); Log(LOG_LEVEL_INFO, "Closing connection due to request: %s", recvbuffer); return false; } cfengine-3.6.2/cf-serverd/server_transform.h0000644000175100017510000000230712316547775020651 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SERVER_TRANSFORM_H #define CFENGINE_SERVER_TRANSFORM_H #include #include void Summarize(void); void KeepPromises(EvalContext *ctx, const Policy *policy, GenericAgentConfig *config); #endif cfengine-3.6.2/cf-serverd/server_common.h0000664000175100017510000000622512400110676020107 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SERVER_COMMON_H #define CFENGINE_SERVER_COMMON_H #define CF_BUFEXT 128 #include #include /* EvalContext */ #include /* ServerConnectionState */ void RefuseAccess(ServerConnectionState *conn, char *errmesg); int AllowedUser(char *user); /* Checks whatever user name contains characters we are considering to be invalid */ bool IsUserNameValid(const char *username); int MatchClasses(EvalContext *ctx, ServerConnectionState *conn); void Terminate(ConnectionInfo *connection); void DoExec(EvalContext *ctx, ServerConnectionState *conn, char *args); void CfGetFile(ServerFileGetState *args); void CfEncryptGetFile(ServerFileGetState *args); int StatFile(ServerConnectionState *conn, char *sendbuffer, char *ofilename); void ReplyServerContext(ServerConnectionState *conn, int encrypted, Item *classes); int CfOpenDirectory(ServerConnectionState *conn, char *sendbuffer, char *oldDirname); int CfSecOpenDirectory(ServerConnectionState *conn, char *sendbuffer, char *dirname); void GetServerLiteral(EvalContext *ctx, ServerConnectionState *conn, char *sendbuffer, char *recvbuffer, int encrypted); int GetServerQuery(ServerConnectionState *conn, char *recvbuffer, int encrypted); bool CompareLocalHash(const char *filename, const char digest[EVP_MAX_MD_SIZE + 1], char sendbuffer[CF_BUFSIZE]); Item *ListPersistentClasses(void); bool PathRemoveTrailingSlash(char *s, size_t s_len); bool PathAppendTrailingSlash(char *s, size_t s_len); size_t ReplaceSpecialVariables(char *buf, size_t buf_size, const char *find1, const char *repl1, const char *find2, const char *repl2, const char *find3, const char *repl3); size_t ShortcutsExpand(char *path, size_t path_size, const StringMap *shortcuts, const char *ipaddr, const char *hostname, const char *key); size_t PreprocessRequestPath(char *reqpath, size_t reqpath_size); void SetConnIdentity(ServerConnectionState *conn, const char *username); #endif /* CFENGINE_SERVER_COMMON_H */ cfengine-3.6.2/cf-serverd/server_access.c0000664000175100017510000003103612411001073020041 0ustar00a10038a1003800000000000000#include "server_access.h" #include "strlist.h" #include "server.h" #include /* FuzzySetMatch */ #include /* StringMatchFull TODO REMOVE */ #include #include struct acl *paths_acl; struct acl *classes_acl, *vars_acl, *literals_acl; struct acl *query_acl; /** * Run this function on every resource (file, class, var etc) access to * grant/deny rights. Currently it checks if: * 1. #ipaddr matches the subnet expression in {admit,deny}_ips * 2. #hostname matches the subdomain expression in {admit,deny}_hostnames * 3. #key is found exactly as it is in {admit,deny}_keys * * @return Default is false, i.e. deny. If a match is found in #acl->admit.* * then return true, unless a match is also found in #acl->deny.* in * which case return false. * * @TODO preprocess our global ACL the moment a client connects, and store in * ServerConnectionState a list of objects that he can access. That way * only his relevant resources will be stored in e.g. {admit,deny}_paths * lists, and running through these two lists on every file request will * be much faster. */ bool access_CheckResource(const struct resource_acl *acl, const char *ipaddr, const char *hostname, const char *key) { /* Only hostname may be NULL in case of resolution failure. */ assert(ipaddr != NULL); assert(key != NULL); bool access = false; /* DENY by default */ /* First we check for admission, secondly for denial, so that denial takes * precedence. */ if (acl->admit.ips) { /* Still using legacy code here, doing linear search over all IPs in * textual representation... too CPU intensive! TODO store the ACL as * one list of struct sockaddr_storage, together with CIDR notation * subnet length. */ const char *rule = NULL; for (int i = 0; i < StrList_Len(acl->admit.ips); i++) { if (FuzzySetMatch(StrList_At(acl->admit.ips, i), ipaddr) == 0 || /* Legacy regex matching, TODO DEPRECATE */ StringMatchFull(StrList_At(acl->admit.ips, i), ipaddr)) { rule = StrList_At(acl->admit.ips, i); break; } } if (rule != NULL) { Log(LOG_LEVEL_DEBUG, "Admit IP due to rule: %s", rule); access = true; } } if (!access && acl->admit.hostnames != NULL && hostname != NULL && *hostname != '\0') { size_t pos = StrList_SearchLongestPrefix(acl->admit.hostnames, hostname, 0, '.', false); /* === Legacy regex matching, slow, TODO DEPRECATE === */ if (pos == (size_t) -1) { for (int i = 0; i < StrList_Len(acl->admit.hostnames); i++) { if (StringMatchFull(StrList_At(acl->admit.hostnames, i), hostname)) { pos = i; break; } } } /* =================================================== */ if (pos != (size_t) -1) { Log(LOG_LEVEL_DEBUG, "Admit hostname due to rule: %s", StrList_At(acl->admit.hostnames, pos)); access = true; } } if (!access && acl->admit.keys != NULL) { size_t pos; bool ret = StrList_BinarySearch(acl->admit.keys, key, &pos); if (ret) { Log(LOG_LEVEL_DEBUG, "Admit key due to rule: %s", StrList_At(acl->admit.keys, pos)); access = true; } } /* If access has been granted, we might need to deny it based on ACL. */ if (access && acl->deny.ips != NULL) { const char *rule = NULL; for (int i = 0; i < StrList_Len(acl->deny.ips); i++) { if (FuzzySetMatch(StrList_At(acl->deny.ips, i), ipaddr) == 0 || /* Legacy regex matching, TODO DEPRECATE */ StringMatchFull(StrList_At(acl->deny.ips, i), ipaddr)) { rule = StrList_At(acl->deny.ips, i); break; } } if (rule != NULL) { Log(LOG_LEVEL_DEBUG, "Deny IP due to rule: %s", rule); access = false; } } if (access && acl->deny.hostnames != NULL && hostname != NULL && *hostname != '\0') { size_t pos = StrList_SearchLongestPrefix(acl->deny.hostnames, hostname, 0, '.', false); /* === Legacy regex matching, slow, TODO DEPRECATE === */ if (pos == (size_t) -1) { for (int i = 0; i < StrList_Len(acl->deny.hostnames); i++) { if (StringMatchFull(StrList_At(acl->deny.hostnames, i), hostname)) { pos = i; break; } } } /* =================================================== */ if (pos != (size_t) -1) { Log(LOG_LEVEL_DEBUG, "Deny hostname due to rule: %s", StrList_At(acl->deny.hostnames, pos)); access = false; } } if (access && acl->deny.keys != NULL) { size_t pos; bool ret = StrList_BinarySearch(acl->deny.keys, key, &pos); if (ret) { Log(LOG_LEVEL_DEBUG, "Deny key due to rule: %s", StrList_At(acl->deny.keys, pos)); access = false; } } return access; } /** * Search #req_path in #acl, if found check its rules. The longest parent * directory of #req_path is searched, or an exact match. Directories *must* * end with FILE_SEPARATOR in the ACL list. * * @return If ACL entry is found, and host is listed in there return * true. Else return false. */ bool acl_CheckPath(const struct acl *acl, const char *reqpath, const char *ipaddr, const char *hostname, const char *key) { bool access = false; /* Deny access by default */ size_t reqpath_len = strlen(reqpath); /* CHECK 1: Search for parent directory or exact entry in ACL. */ size_t pos = StrList_SearchLongestPrefix(acl->resource_names, reqpath, reqpath_len, FILE_SEPARATOR, true); if (pos != (size_t) -1) /* acl entry was found */ { const struct resource_acl *racl = &acl->acls[pos]; bool ret = access_CheckResource(racl, ipaddr, hostname, key); if (ret == true) /* entry found that grants access */ { access = true; } Log(LOG_LEVEL_DEBUG, "acl_CheckPath: '%s' found in ACL entry '%s', admit=%s", reqpath, acl->resource_names->list[pos]->str, ret == true ? "true" : "false"); } /* CHECK 2: replace ACL entry parts with special variables (if applicable), * e.g. turn "/path/to/192.168.1.1.json" * to "/path/to/$(connection.ip).json" */ char mangled_path[PATH_MAX]; memcpy(mangled_path, reqpath, reqpath_len + 1); size_t mangled_path_len = ReplaceSpecialVariables(mangled_path, sizeof(mangled_path), ipaddr, "$(connection.ip)", hostname, "$(connection.hostname)", key, "$(connection.key)"); /* If there were special variables replaced */ if (mangled_path_len != 0 && mangled_path_len != (size_t) -1) /* Overflow, TODO handle separately. */ { size_t pos2 = StrList_SearchLongestPrefix(acl->resource_names, mangled_path, mangled_path_len, FILE_SEPARATOR, true); if (pos2 != (size_t) -1) /* acl entry was found */ { /* TODO make sure this match is more specific than the other one. */ const struct resource_acl *racl = &acl->acls[pos2]; /* Check if the magic strings are allowed or denied. */ bool ret = access_CheckResource(racl, "$(connection.ip)", "$(connection.hostname)", "$(connection.key)"); if (ret == true) /* entry found that grants access */ { access = true; } Log(LOG_LEVEL_DEBUG, "acl_CheckPath: '%s' found in ACL entry '%s', admit=%s", mangled_path, acl->resource_names->list[pos2]->str, ret == true ? "true" : "false"); } } return access; } bool acl_CheckExact(const struct acl *acl, const char *req_string, const char *ipaddr, const char *hostname, const char *key) { bool access = false; size_t pos = -1; bool found = StrList_BinarySearch(acl->resource_names, req_string, &pos); if (found) { const struct resource_acl *racl = &acl->acls[pos]; bool ret = access_CheckResource(racl, ipaddr, hostname, key); if (ret == true) /* entry found that grants access */ { access = true; } } return access; } /** * Search the list of resources for the handle. If found return the index of * the resource ACL that corresponds to that handle, else add the handle with * empty ACL, reallocating if necessary. The new handle is inserted in the * proper position to keep the acl->resource_names list sorted. * * @note acl->resource_names list should already be sorted, no problem if all * inserts are done with this function. * * @return the index of the resource_acl corresponding to handle. -1 means * reallocation failed, but existing values are still valid. */ size_t acl_SortedInsert(struct acl **a, const char *handle) { assert(handle != NULL); struct acl *acl = *a; /* for clarity */ size_t position = (size_t) -1; bool found = StrList_BinarySearch(acl->resource_names, handle, &position); if (found) { /* Found it, return existing entry. */ assert(position < acl->len); return position; } /* handle is not in acl, we must insert at the position returned. */ assert(position <= acl->len); /* 1. Check if reallocation is needed. */ if (acl->len == acl->alloc_len) { size_t new_alloc_len = acl->alloc_len * 2; if (new_alloc_len == 0) { new_alloc_len = 1; } struct acl *p = realloc(acl, sizeof(*p) + sizeof(*p->acls) * new_alloc_len); if (p == NULL) { return (size_t) -1; } acl = p; acl->alloc_len = new_alloc_len; *a = acl; /* Change the caller's variable */ } /* 2. We now have enough space, so insert the resource at the proper index. */ size_t ret = StrList_Insert(&acl->resource_names, handle, position); if (ret == (size_t) -1) { /* realloc() failed but the data structure is still valid. */ return (size_t) -1; } /* 3. Make room. */ memmove(&acl->acls[position + 1], &acl->acls[position], (acl->len - position) * sizeof(acl->acls[position])); acl->len++; /* 4. Initialise all ACLs for the resource as empty. */ acl->acls[position] = (struct resource_acl) { {0}, {0} }; /* NULL acls <=> empty */ Log(LOG_LEVEL_DEBUG, "Inserted in ACL position %zu: %s", position, handle); return position; } void acl_Free(struct acl *a) { StrList_Free(&a->resource_names); size_t i; for (i = 0; i < a->len; i++) { StrList_Free(&a->acls[i].admit.ips); StrList_Free(&a->acls[i].admit.hostnames); StrList_Free(&a->acls[i].admit.keys); StrList_Free(&a->acls[i].deny.ips); StrList_Free(&a->acls[i].deny.hostnames); StrList_Free(&a->acls[i].deny.keys); } free(a); } cfengine-3.6.2/cf-serverd/cf-serverd-functions.h0000664000175100017510000000310412400110676021270 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF_SERVERD_FUNCTIONS_H #define CFENGINE_CF_SERVERD_FUNCTIONS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef int (*InitServerFunction)(size_t queue_size); GenericAgentConfig *CheckOpts(int argc, char **argv); int StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config); #endif cfengine-3.6.2/cf-serverd/Makefile.in0000664000175100017510000006537712412324463017146 0ustar00a10038a1003800000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @BUILTIN_EXTENSIONS_FALSE@sbin_PROGRAMS = cf-serverd$(EXEEXT) subdir = cf-serverd DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/adl_recursive_eval.m4 \ $(top_srcdir)/m4/cf3_check_proper_func.m4 \ $(top_srcdir)/m4/cf3_path_root_prog.m4 \ $(top_srcdir)/m4/cf3_with_library.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/old-autoconf.m4 $(top_srcdir)/m4/snprintf.m4 \ $(top_srcdir)/m4/strndup.m4 $(top_srcdir)/m4/cf3_gcc_flags.m4 \ $(top_srcdir)/m4/cf3_platforms.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/libutils/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libcf_serverd_la_DEPENDENCIES = ../libpromises/libpromises.la am_libcf_serverd_la_OBJECTS = cf-serverd.lo \ cf-serverd-enterprise-stubs.lo cf-serverd-functions.lo \ server_common.lo server.lo server_transform.lo \ server_classic.lo server_tls.lo server_access.lo strlist.lo libcf_serverd_la_OBJECTS = $(am_libcf_serverd_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) cf_serverd_SOURCES = cf-serverd.c cf_serverd_OBJECTS = cf_serverd-cf-serverd.$(OBJEXT) @BUILTIN_EXTENSIONS_FALSE@cf_serverd_DEPENDENCIES = libcf-serverd.la cf_serverd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(cf_serverd_CFLAGS) \ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libutils 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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libcf_serverd_la_SOURCES) cf-serverd.c DIST_SOURCES = $(libcf_serverd_la_SOURCES) cf-serverd.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_CFLAGS = @CORE_CFLAGS@ CORE_CPPFLAGS = @CORE_CPPFLAGS@ CORE_LDFLAGS = @CORE_LDFLAGS@ CORE_LIBS = @CORE_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LCOV = @LCOV@ LCOV_GENHTML = @LCOV_GENHTML@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBACL_CFLAGS = @LIBACL_CFLAGS@ LIBACL_CPPFLAGS = @LIBACL_CPPFLAGS@ LIBACL_LDFLAGS = @LIBACL_LDFLAGS@ LIBACL_LIBS = @LIBACL_LIBS@ LIBACL_PATH = @LIBACL_PATH@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIBVIRT_CFLAGS = @LIBVIRT_CFLAGS@ LIBVIRT_CPPFLAGS = @LIBVIRT_CPPFLAGS@ LIBVIRT_LDFLAGS = @LIBVIRT_LDFLAGS@ LIBVIRT_LIBS = @LIBVIRT_LIBS@ LIBVIRT_PATH = @LIBVIRT_PATH@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_CPPFLAGS = @LIBXML2_CPPFLAGS@ LIBXML2_LDFLAGS = @LIBXML2_LDFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIBXML2_PATH = @LIBXML2_PATH@ LIPO = @LIPO@ LMDB_CFLAGS = @LMDB_CFLAGS@ LMDB_CPPFLAGS = @LMDB_CPPFLAGS@ LMDB_LDFLAGS = @LMDB_LDFLAGS@ LMDB_LIBS = @LMDB_LIBS@ LMDB_PATH = @LMDB_PATH@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ MYSQL_LIBS = @MYSQL_LIBS@ MYSQL_PATH = @MYSQL_PATH@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_CPPFLAGS = @OPENSSL_CPPFLAGS@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_PATH = @OPENSSL_PATH@ 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@ PAM_CFLAGS = @PAM_CFLAGS@ PAM_CPPFLAGS = @PAM_CPPFLAGS@ PAM_LDFLAGS = @PAM_LDFLAGS@ PAM_LIBS = @PAM_LIBS@ PAM_PATH = @PAM_PATH@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LDFLAGS = @PCRE_LDFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PCRE_PATH = @PCRE_PATH@ POSTGRESQL_CFLAGS = @POSTGRESQL_CFLAGS@ POSTGRESQL_CPPFLAGS = @POSTGRESQL_CPPFLAGS@ POSTGRESQL_LDFLAGS = @POSTGRESQL_LDFLAGS@ POSTGRESQL_LIBS = @POSTGRESQL_LIBS@ POSTGRESQL_PATH = @POSTGRESQL_PATH@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QDBM_CFLAGS = @QDBM_CFLAGS@ QDBM_CPPFLAGS = @QDBM_CPPFLAGS@ QDBM_LDFLAGS = @QDBM_LDFLAGS@ QDBM_LIBS = @QDBM_LIBS@ QDBM_PATH = @QDBM_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TOKYOCABINET_CFLAGS = @TOKYOCABINET_CFLAGS@ TOKYOCABINET_CPPFLAGS = @TOKYOCABINET_CPPFLAGS@ TOKYOCABINET_LDFLAGS = @TOKYOCABINET_LDFLAGS@ TOKYOCABINET_LIBS = @TOKYOCABINET_LIBS@ TOKYOCABINET_PATH = @TOKYOCABINET_PATH@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ acx_pthread_config = @acx_pthread_config@ 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@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ enable_builtin_extensions = @enable_builtin_extensions@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ hw_cv_func_ctime_proper = @hw_cv_func_ctime_proper@ hw_cv_func_mkdir_proper = @hw_cv_func_mkdir_proper@ hw_cv_func_rename_proper = @hw_cv_func_rename_proper@ hw_cv_func_stat_proper = @hw_cv_func_stat_proper@ includedir = @includedir@ infodir = @infodir@ inputdir = @inputdir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ logdir = @logdir@ mandir = @mandir@ masterdir = @masterdir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ piddir = @piddir@ prefix = @prefix@ program_transform_name = @program_transform_name@ projlibdir = @projlibdir@ 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@ workdir = @workdir@ noinst_LTLIBRARIES = libcf-serverd.la AM_CPPFLAGS = -I$(srcdir)/../libpromises -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_serverd_la_LIBADD = ../libpromises/libpromises.la libcf_serverd_la_SOURCES = \ cf-serverd.c \ cf-serverd-enterprise-stubs.c cf-serverd-enterprise-stubs.h \ cf-serverd-functions.c cf-serverd-functions.h \ server_common.c server_common.h \ server.c server.h \ server_transform.c server_transform.h \ server_classic.c server_classic.h \ server_tls.c server_tls.h \ server_access.c server_access.h \ strlist.c strlist.h @BUILTIN_EXTENSIONS_FALSE@cf_serverd_CFLAGS = $(AM_CFLAGS) @BUILTIN_EXTENSIONS_FALSE@cf_serverd_LDADD = libcf-serverd.la CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej 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) --foreign cf-serverd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign cf-serverd/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-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } libcf-serverd.la: $(libcf_serverd_la_OBJECTS) $(libcf_serverd_la_DEPENDENCIES) $(EXTRA_libcf_serverd_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libcf_serverd_la_OBJECTS) $(libcf_serverd_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list cf-serverd$(EXEEXT): $(cf_serverd_OBJECTS) $(cf_serverd_DEPENDENCIES) $(EXTRA_cf_serverd_DEPENDENCIES) @rm -f cf-serverd$(EXEEXT) $(AM_V_CCLD)$(cf_serverd_LINK) $(cf_serverd_OBJECTS) $(cf_serverd_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-serverd-enterprise-stubs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-serverd-functions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf-serverd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cf_serverd-cf-serverd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_access.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_classic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_tls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_transform.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlist.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< cf_serverd-cf-serverd.o: cf-serverd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_serverd_CFLAGS) $(CFLAGS) -MT cf_serverd-cf-serverd.o -MD -MP -MF $(DEPDIR)/cf_serverd-cf-serverd.Tpo -c -o cf_serverd-cf-serverd.o `test -f 'cf-serverd.c' || echo '$(srcdir)/'`cf-serverd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_serverd-cf-serverd.Tpo $(DEPDIR)/cf_serverd-cf-serverd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-serverd.c' object='cf_serverd-cf-serverd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_serverd_CFLAGS) $(CFLAGS) -c -o cf_serverd-cf-serverd.o `test -f 'cf-serverd.c' || echo '$(srcdir)/'`cf-serverd.c cf_serverd-cf-serverd.obj: cf-serverd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_serverd_CFLAGS) $(CFLAGS) -MT cf_serverd-cf-serverd.obj -MD -MP -MF $(DEPDIR)/cf_serverd-cf-serverd.Tpo -c -o cf_serverd-cf-serverd.obj `if test -f 'cf-serverd.c'; then $(CYGPATH_W) 'cf-serverd.c'; else $(CYGPATH_W) '$(srcdir)/cf-serverd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cf_serverd-cf-serverd.Tpo $(DEPDIR)/cf_serverd-cf-serverd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cf-serverd.c' object='cf_serverd-cf-serverd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cf_serverd_CFLAGS) $(CFLAGS) -c -o cf_serverd-cf-serverd.obj `if test -f 'cf-serverd.c'; then $(CYGPATH_W) 'cf-serverd.c'; else $(CYGPATH_W) '$(srcdir)/cf-serverd.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-noinstLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES clean-sbinPROGRAMS \ cscopelist-am ctags ctags-am 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-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-sbinPROGRAMS @BUILTIN_EXTENSIONS_FALSE@ # Workaround for automake madness (try removing it if you want to know why). # 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: cfengine-3.6.2/cf-serverd/server_classic.h0000664000175100017510000000034512411001073020225 0ustar00a10038a1003800000000000000#ifndef CFENGINE_SERVER_CLASSIC_H #define CFENGINE_SERVER_CLASSIC_H #include #include #include "server.h" extern int BusyWithClassicConnection(EvalContext *ctx, ServerConnectionState *conn); #endif cfengine-3.6.2/cf-serverd/cf-serverd-functions.c0000664000175100017510000006457212411001073021273 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ServerTLSInitialize */ #include #include #include #include #include #include #include #include #include #include "server_access.h" static const size_t QUEUESIZE = 50; int NO_FORK = false; /* GLOBAL_A */ /*******************************************************************/ /* Command line option parsing */ /*******************************************************************/ static const char *const CF_SERVERD_SHORT_DESCRIPTION = "CFEngine file server daemon"; static const char *const CF_SERVERD_MANPAGE_LONG_DESCRIPTION = "cf-serverd is a socket listening daemon providing two services: it acts as a file server for remote file copying " "and it allows an authorized cf-runagent to start a cf-agent run. cf-agent typically connects to a " "cf-serverd instance to request updated policy code, but may also request additional files for download. " "cf-serverd employs role based access control (defined in policy code) to authorize requests."; static const struct option OPTIONS[] = { {"help", no_argument, 0, 'h'}, {"debug", no_argument, 0, 'd'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {"file", required_argument, 0, 'f'}, {"define", required_argument, 0, 'D'}, {"negate", required_argument, 0, 'N'}, {"no-lock", no_argument, 0, 'K'}, {"inform", no_argument, 0, 'I'}, {"diagnostic", no_argument, 0, 'x'}, {"no-fork", no_argument, 0, 'F'}, {"ld-library-path", required_argument, 0, 'L'}, {"generate-avahi-conf", no_argument, 0, 'A'}, {"legacy-output", no_argument, 0, 'l'}, {"color", optional_argument, 0, 'C'}, {NULL, 0, 0, '\0'} }; static const char *const HINTS[] = { "Print the help message", "Enable debugging output", "Output verbose information about the behaviour of the agent", "Output the version of the software", "Specify an alternative input file than the default", "Define a list of comma separated classes to be defined at the start of execution", "Define a list of comma separated classes to be undefined at the start of execution", "Ignore locking constraints during execution (ifelapsed/expireafter) if \"too soon\" to run", "Print basic information about changes made to the system, i.e. promises repaired", "Activate internal diagnostics (developers only)", "Run as a foreground processes (do not fork)", "Set the internal value of LD_LIBRARY_PATH for child processes", "Generates avahi configuration file to enable policy server to be discovered in the network", "Use legacy output format", "Enable colorized output. Possible values: 'always', 'auto', 'never'. If option is used, the default value is 'auto'", NULL }; #ifdef HAVE_AVAHI_CLIENT_CLIENT_H #ifdef HAVE_AVAHI_COMMON_ADDRESS_H static int GenerateAvahiConfig(const char *path) { FILE *fout; Writer *writer = NULL; fout = safe_fopen(path, "w+"); if (fout == NULL) { Log(LOG_LEVEL_ERR, "Unable to open '%s'", path); return -1; } writer = FileWriter(fout); fprintf(fout, "\n"); fprintf(fout, "\n"); XmlComment(writer, "This file has been automatically generated by cf-serverd."); XmlStartTag(writer, "service-group", 0); FprintAvahiCfengineTag(fout); XmlStartTag(writer, "service", 0); XmlTag(writer, "type", "_cfenginehub._tcp",0); DetermineCfenginePort(); XmlStartTag(writer, "port", 0); WriterWriteF(writer, "%d", CFENGINE_PORT); XmlEndTag(writer, "port"); XmlEndTag(writer, "service"); XmlEndTag(writer, "service-group"); fclose(fout); return 0; } #define SUPPORT_AVAHI_CONFIG #endif #endif GenericAgentConfig *CheckOpts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; GenericAgentConfig *config = GenericAgentConfigNewDefault(AGENT_TYPE_SERVER); while ((c = getopt_long(argc, argv, "dvIKf:D:N:VSxLFMhAlC::", OPTIONS, &optindex)) != EOF) { switch ((char) c) { case 'l': LEGACY_OUTPUT = true; break; case 'f': GenericAgentConfigSetInputFile(config, GetInputDir(), optarg); MINUSF = true; break; case 'd': LogSetGlobalLevel(LOG_LEVEL_DEBUG); NO_FORK = true; break; case 'K': config->ignore_locks = true; break; case 'D': config->heap_soft = StringSetFromString(optarg, ','); break; case 'N': config->heap_negated = StringSetFromString(optarg, ','); break; case 'I': LogSetGlobalLevel(LOG_LEVEL_INFO); break; case 'v': LogSetGlobalLevel(LOG_LEVEL_VERBOSE); NO_FORK = true; break; case 'F': NO_FORK = true; break; case 'L': { static char ld_library_path[CF_BUFSIZE]; /* GLOBAL_A */ Log(LOG_LEVEL_VERBOSE, "Setting LD_LIBRARY_PATH to '%s'", optarg); snprintf(ld_library_path, CF_BUFSIZE - 1, "LD_LIBRARY_PATH=%s", optarg); putenv(ld_library_path); break; } case 'V': { Writer *w = FileWriter(stdout); GenericAgentWriteVersion(w); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'h': { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-serverd", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_SUCCESS); case 'M': { Writer *out = FileWriter(stdout); ManPageWrite(out, "cf-serverd", time(NULL), CF_SERVERD_SHORT_DESCRIPTION, CF_SERVERD_MANPAGE_LONG_DESCRIPTION, OPTIONS, HINTS, true); FileWriterDetach(out); exit(EXIT_SUCCESS); } case 'x': Log(LOG_LEVEL_ERR, "Self-diagnostic functionality is retired."); exit(EXIT_SUCCESS); case 'A': #ifdef SUPPORT_AVAHI_CONFIG Log(LOG_LEVEL_NOTICE, "Generating Avahi configuration file."); if (GenerateAvahiConfig("/etc/avahi/services/cfengine-hub.service") != 0) { exit(EXIT_FAILURE); } cf_popen("/etc/init.d/avahi-daemon restart", "r", true); Log(LOG_LEVEL_NOTICE, "Avahi configuration file generated successfuly."); #else Log(LOG_LEVEL_ERR, "Generating avahi configuration can only be done when avahi-daemon and libavahi are installed on the machine."); #endif exit(EXIT_SUCCESS); case 'C': if (!GenericAgentConfigParseColor(config, optarg)) { exit(EXIT_FAILURE); } break; default: { Writer *w = FileWriter(stdout); GenericAgentWriteHelp(w, "cf-serverd", OPTIONS, HINTS, true); FileWriterDetach(w); } exit(EXIT_FAILURE); } } if (!GenericAgentConfigParseArguments(config, argc - optind, argv + optind)) { Log(LOG_LEVEL_ERR, "Too many arguments"); exit(EXIT_FAILURE); } return config; } /*********************************************************************/ /* Policy Reloading */ /*********************************************************************/ static void DeleteAuthList(Auth **list, Auth **list_tail) { Auth *ap = *list; while (ap != NULL) { Auth *ap_next = ap->next; DeleteItemList(ap->accesslist); DeleteItemList(ap->maproot); free(ap->path); free(ap); /* Just make sure the tail was consistent. */ if (ap_next == NULL) assert(ap == *list_tail); ap = ap_next; } *list = NULL; *list_tail = NULL; } static void KeepHardClasses(EvalContext *ctx) { char name[CF_BUFSIZE]; if (name != NULL) { char *existing_policy_server = ReadPolicyServerFile(CFWORKDIR); if (existing_policy_server) { free(existing_policy_server); if (GetAmPolicyHub(CFWORKDIR)) { MarkAsPolicyServer(ctx); } } } /* FIXME: why is it not in generic_agent?! */ GenericAgentAddEditionClasses(ctx); } /* Must not be called unless ACTIVE_THREADS is zero: */ static void ClearAuthAndACLs(void) { /* Old ACLs */ DeleteAuthList(&SV.admit, &SV.admittail); DeleteAuthList(&SV.deny, &SV.denytail); DeleteAuthList(&SV.varadmit, &SV.varadmittail); DeleteAuthList(&SV.vardeny, &SV.vardenytail); DeleteAuthList(&SV.roles, &SV.rolestail); /* Should be no currently open connections */ assert(SV.connectionlist == NULL); /* body server control ACLs */ DeleteItemList(SV.trustkeylist); SV.trustkeylist = NULL; DeleteItemList(SV.attackerlist); SV.attackerlist = NULL; DeleteItemList(SV.nonattackerlist); SV.nonattackerlist = NULL; DeleteItemList(SV.allowuserlist); SV.allowuserlist = NULL; DeleteItemList(SV.multiconnlist); SV.multiconnlist = NULL; DeleteItemList(SV.allowuserlist); SV.allowuserlist = NULL; DeleteItemList(SV.allowlegacyconnects); SV.allowlegacyconnects = NULL; StringMapDestroy(SV.path_shortcuts); SV.path_shortcuts = NULL; free(SV.allowciphers); SV.allowciphers = NULL; /* New ACLs */ NEED_REVERSE_LOOKUP = false; acl_Free(paths_acl); paths_acl = NULL; acl_Free(classes_acl); classes_acl = NULL; acl_Free(vars_acl); vars_acl = NULL; acl_Free(literals_acl); literals_acl = NULL; acl_Free(query_acl); query_acl = NULL; } static void CheckFileChanges(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { Log(LOG_LEVEL_DEBUG, "Checking file updates for input file '%s'", config->input_file); time_t validated_at = ReadTimestampFromPolicyValidatedFile(config, NULL); if (config->agent_specific.daemon.last_validated_at < validated_at) { /* Rereading policies now, so update timestamp. */ config->agent_specific.daemon.last_validated_at = validated_at; Log(LOG_LEVEL_VERBOSE, "New promises detected..."); if (GenericAgentArePromisesValid(config)) { Log(LOG_LEVEL_NOTICE, "Rereading policy file '%s'", config->input_file); /* STEP 1: Free everything */ EvalContextClear(ctx); strcpy(VDOMAIN, "undefined.domain"); ClearAuthAndACLs(); PolicyDestroy(*policy); *policy = NULL; /* STEP 2: Set Environment, Parse and Evaluate policy */ /* * TODO why is this done separately here? What's the difference to * calling the same steps as in cf-serverd.c:main()? Those are: * GenericAgentConfigApply(); // not here! * GenericAgentDiscoverContext(); // not here! * if (GenericAgentCheckPolicy()) // not here! * policy=GenericAgentLoadPolicy(); * KeepPromises(); * Summarize(); */ char *existing_policy_server = ReadPolicyServerFile(GetWorkDir()); SetPolicyServer(ctx, existing_policy_server); free(existing_policy_server); UpdateLastPolicyUpdateTime(ctx); DetectEnvironment(ctx); KeepHardClasses(ctx); EvalContextClassPutHard(ctx, CF_AGENTTYPES[AGENT_TYPE_SERVER], "cfe_internal,source=agent"); time_t t = SetReferenceTime(); UpdateTimeClasses(ctx, t); *policy = LoadPolicy(ctx, config); /* Reload HA related configuration */ ReloadHAConfig(); KeepPromises(ctx, *policy, config); Summarize(); } else { Log(LOG_LEVEL_INFO, "File changes contain errors -- ignoring"); } } else { Log(LOG_LEVEL_DEBUG, "No new promises found"); } } /*********************************************************************/ /* Setup listening channel */ /*********************************************************************/ static int OpenReceiverChannel(void) { struct addrinfo *response = NULL, *ap; struct addrinfo query = { .ai_flags = AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; /* Listen to INADDR(6)_ANY if BINDINTERFACE unset. */ char *ptr = NULL; if (BINDINTERFACE[0] != '\0') { ptr = BINDINTERFACE; } char servname[PRINTSIZE(CFENGINE_PORT)]; xsnprintf(servname, sizeof(servname), "%d", CFENGINE_PORT); /* Resolve listening interface. */ int gres; if ((gres = getaddrinfo(ptr, servname, &query, &response)) != 0) { Log(LOG_LEVEL_ERR, "DNS/service lookup failure. (getaddrinfo: %s)", gai_strerror(gres)); if (response) { freeaddrinfo(response); } return -1; } int sd = -1; for (ap = response; ap != NULL; ap = ap->ai_next) { if ((sd = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol)) == -1) { continue; } #ifdef IPV6_V6ONLY /* Properly implemented getaddrinfo(AI_PASSIVE) should return the IPV6 loopback address first. Some platforms (Windows) don't listen to both address families when binding to it and need this flag. Some other platforms won't even honour this flag (openbsd). */ if (BINDINTERFACE[0] == '\0' && ap->ai_family == AF_INET6) { int no = 0; if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)) == -1) { Log(LOG_LEVEL_VERBOSE, "Failed to clear IPv6-only flag on listening socket" " (setsockopt: %s)", GetErrorStr()); } } #endif int yes = 1; if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { Log(LOG_LEVEL_VERBOSE, "Socket option SO_REUSEADDR was not accepted. (setsockopt: %s)", GetErrorStr()); } struct linger cflinger = { .l_onoff = 1, .l_linger = 60 }; if (setsockopt(sd, SOL_SOCKET, SO_LINGER, &cflinger, sizeof(cflinger)) == -1) { Log(LOG_LEVEL_INFO, "Socket option SO_LINGER was not accepted. (setsockopt: %s)", GetErrorStr()); } if (bind(sd, ap->ai_addr, ap->ai_addrlen) != -1) { if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG) { /* Convert IP address to string, no DNS lookup performed. */ char txtaddr[CF_MAX_IP_LEN] = ""; getnameinfo(ap->ai_addr, ap->ai_addrlen, txtaddr, sizeof(txtaddr), NULL, 0, NI_NUMERICHOST); Log(LOG_LEVEL_DEBUG, "Bound to address '%s' on '%s' = %d", txtaddr, CLASSTEXT[VSYSTEMHARDCLASS], VSYSTEMHARDCLASS); } break; } else { Log(LOG_LEVEL_INFO, "Could not bind server address. (bind: %s)", GetErrorStr()); cf_closesocket(sd); sd = -1; } } assert(response != NULL); /* getaddrinfo() was successful */ freeaddrinfo(response); return sd; } static int InitServer(size_t queue_size) { int sd = -1; if ((sd = OpenReceiverChannel()) == -1) { Log(LOG_LEVEL_ERR, "Unable to start server"); exit(EXIT_FAILURE); } if (listen(sd, queue_size) == -1) { Log(LOG_LEVEL_ERR, "listen failed. (listen: %s)", GetErrorStr()); cf_closesocket(sd); exit(EXIT_FAILURE); } return sd; } /* Set up standard signal-handling. */ static void InitSignals() { MakeSignalPipe(); signal(SIGINT, HandleSignalsForDaemon); signal(SIGTERM, HandleSignalsForDaemon); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGUSR1, HandleSignalsForDaemon); signal(SIGUSR2, HandleSignalsForDaemon); } /* Prepare synthetic agent promise and lock it. */ static CfLock AcquireServerLock(EvalContext *ctx, GenericAgentConfig *config, Policy *server_policy) { Promise *pp = NULL; { Bundle *bp = PolicyAppendBundle(server_policy, NamespaceDefault(), "server_cfengine_bundle", "agent", NULL, NULL); PromiseType *tp = BundleAppendPromiseType(bp, "server_cfengine"); pp = PromiseTypeAppendPromise(tp, config->input_file, (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, NULL); } assert(pp); TransactionContext tc = { .ifelapsed = 0, .expireafter = 1, }; return AcquireLock(ctx, pp->promiser, VUQNAME, CFSTARTTIME, tc, pp, false); } /* Final preparations for running as server */ static void PrepareServer(int sd) { if (sd != -1) { Log(LOG_LEVEL_VERBOSE, "Listening for connections ..."); } if (!NO_FORK) #ifdef __MINGW32__ { Log(LOG_LEVEL_VERBOSE, "Windows does not support starting processes in the background - running in foreground"); } #else { if (fork() != 0) { _exit(EXIT_SUCCESS); } ActAsDaemon(); } /* Close sd on exec, needed for not passing the socket to cf-runagent * spawned commands. */ fcntl(sd, F_SETFD, FD_CLOEXEC); #endif Log(LOG_LEVEL_NOTICE, "Server is starting..."); WritePID("cf-serverd.pid"); /* Arranges for atexit() to tidy it away */ } /* Wait for connection-handler threads to finish their work. * * @return Number of live threads remaining after waiting. */ static int WaitOnThreads() { int result = 1; for (int i = 2; i > 0; i--) { if (ThreadLock(cft_server_children)) { result = ACTIVE_THREADS; ThreadUnlock(cft_server_children); } if (result == 0) { break; } Log(LOG_LEVEL_VERBOSE, "Waiting %ds for %d connection threads to finish", i, result); sleep(1); } if (result > 0) { Log(LOG_LEVEL_VERBOSE, "There are %d connection threads left, exiting anyway", result); } else { assert(result == 0); Log(LOG_LEVEL_VERBOSE, "All threads are done, cleaning up allocations"); ClearAuthAndACLs(); ServerTLSDeInitialize(); } return result; } static void CollectCallIfDue(EvalContext *ctx) { /* Check whether we have established peering with a hub */ if (CollectCallHasPending()) { extern int COLLECT_WINDOW; int waiting_queue = 0; int new_client = CollectCallGetPending(&waiting_queue); assert(new_client >= 0); if (waiting_queue > COLLECT_WINDOW) { Log(LOG_LEVEL_INFO, "Closing collect call with queue longer than the allocated window [%d > %d]", waiting_queue, COLLECT_WINDOW); cf_closesocket(new_client); } else { ConnectionInfo *info = ConnectionInfoNew(); assert(info); ConnectionInfoSetSocket(info, new_client); info->is_call_collect = true; /* Mark processed when done. */ ServerEntryPoint(ctx, POLICY_SERVER, info); } } } /* Wait up to a minute for an in-coming connection. * * @param sd The listening socket or -1. * @retval > 0 In-coming connection. * @retval 0 No in-coming connection. * @retval -1 Error (other than interrupt). * @retval < -1 Interrupted while waiting. */ static int WaitForIncoming(int sd) { Log(LOG_LEVEL_DEBUG, "Waiting at incoming select..."); struct timeval timeout = { .tv_sec = 60 }; int signal_pipe = GetSignalPipe(); fd_set rset; FD_ZERO(&rset); FD_SET(signal_pipe, &rset); /* sd might be -1 if "listen" attribute in body server control is set * to off (enterprise feature for call-collected clients). */ if (sd != -1) { FD_SET(sd, &rset); } int result = select(MAX(sd, signal_pipe) + 1, &rset, NULL, NULL, &timeout); if (result == -1) { return (errno == EINTR) ? -2 : -1; } assert(result >= 0); /* Empty the signal pipe, it is there to only detect missed * signals in-between checking IsPendingTermination() and calling * select(). */ unsigned char buf; while (recv(signal_pipe, &buf, 1, 0) > 0) { /* skip */ } /* If we had data on the signal pipe but not the listening socket, * report no in-coming sockets. */ if (result > 0 && (sd < 0 || !FD_ISSET(sd, &rset))) { return 0; } /* Return 0 in case of timeout, or the valid socket descriptor. */ return result; } /* Check for new policy just before spawning a thread. * * Server reconfiguration can only happen when no threads are active, * so this is a good time to do it; but we do still have to check for * running threads. */ static void PolicyUpdateIfSafe(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { if (ThreadLock(cft_server_children)) { int prior = COLLECT_INTERVAL; if (ACTIVE_THREADS == 0) { CheckFileChanges(ctx, policy, config); } ThreadUnlock(cft_server_children); /* Check for change in call-collect interval: */ if (prior != COLLECT_INTERVAL) { /* Start, stop or change schedule, as appropriate. */ CollectCallStart(COLLECT_INTERVAL); } } } /* Try to accept a connection; handle if we get one. */ static void AcceptAndHandle(EvalContext *ctx, int sd) { /* TODO embed ConnectionInfo into ServerConnectionState. */ ConnectionInfo *info = ConnectionInfoNew(); if (info == NULL) { return; } info->ss_len = sizeof(info->ss); info->sd = accept(sd, (struct sockaddr *) &info->ss, &info->ss_len); if (info->sd == -1) { ConnectionInfoDestroy(&info); return; } /* Just convert IP address to string, no DNS lookup. */ char ipaddr[CF_MAX_IP_LEN] = ""; getnameinfo((const struct sockaddr *) &info->ss, info->ss_len, ipaddr, sizeof(ipaddr), NULL, 0, NI_NUMERICHOST); /* IPv4 mapped addresses (e.g. "::ffff:192.168.1.2") are * hereby represented with their IPv4 counterpart. */ ServerEntryPoint(ctx, MapAddress(ipaddr), info); } /** * @retval >0 Number of threads still working * @retval 0 All threads are done * @retval -1 Server didn't run */ int StartServer(EvalContext *ctx, Policy **policy, GenericAgentConfig *config) { InitSignals(); ServerTLSInitialize(); int sd = SetServerListenState(ctx, QUEUESIZE, SERVER_LISTEN, &InitServer); Policy *server_cfengine_policy = PolicyNew(); CfLock thislock = AcquireServerLock(ctx, config, server_cfengine_policy); if (thislock.lock == NULL) { PolicyDestroy(server_cfengine_policy); if (sd >= 0) { cf_closesocket(sd); } return -1; } PrepareServer(sd); CollectCallStart(COLLECT_INTERVAL); while (!IsPendingTermination()) { CollectCallIfDue(ctx); int selected = WaitForIncoming(sd); if (selected == -1) { Log(LOG_LEVEL_ERR, "Error while waiting for connections. (select: %s)", GetErrorStr()); break; } else if (selected >= 0) /* timeout or success */ { PolicyUpdateIfSafe(ctx, policy, config); /* Is there a new connection pending at our listening socket? */ if (selected > 0) { AcceptAndHandle(ctx, sd); } } /* else: interrupted, maybe pending termination. */ } Log(LOG_LEVEL_NOTICE, "Cleaning up and exiting..."); CollectCallStop(); if (sd != -1) { Log(LOG_LEVEL_VERBOSE, "Closing listening socket"); cf_closesocket(sd); /* Close listening socket */ } /* This is a graceful exit, give 2 seconds chance to threads. */ int threads_left = WaitOnThreads(); YieldCurrentLock(thislock); PolicyDestroy(server_cfengine_policy); return threads_left; } cfengine-3.6.2/cf-serverd/Makefile.am0000664000175100017510000000176712411001073017112 0ustar00a10038a1003800000000000000noinst_LTLIBRARIES = libcf-serverd.la AM_CPPFLAGS = -I$(srcdir)/../libpromises -I$(srcdir)/../libutils \ -I$(srcdir)/../libcfnet \ -I$(srcdir)/../libenv \ $(OPENSSL_CPPFLAGS) \ $(PCRE_CPPFLAGS) \ $(ENTERPRISE_CPPFLAGS) AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(ENTERPRISE_CFLAGS) libcf_serverd_la_LIBADD = ../libpromises/libpromises.la libcf_serverd_la_SOURCES = \ cf-serverd.c \ cf-serverd-enterprise-stubs.c cf-serverd-enterprise-stubs.h \ cf-serverd-functions.c cf-serverd-functions.h \ server_common.c server_common.h \ server.c server.h \ server_transform.c server_transform.h \ server_classic.c server_classic.h \ server_tls.c server_tls.h \ server_access.c server_access.h \ strlist.c strlist.h if !BUILTIN_EXTENSIONS sbin_PROGRAMS = cf-serverd # Workaround for automake madness (try removing it if you want to know why). cf_serverd_CFLAGS = $(AM_CFLAGS) cf_serverd_LDADD = libcf-serverd.la endif CLEANFILES = *.gcno *.gcda # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej cfengine-3.6.2/cf-serverd/cf-serverd-enterprise-stubs.h0000644000175100017510000000474412334106746022620 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_CF_SERVERD_ENTERPRISE_STUBS_H #define CFENGINE_CF_SERVERD_ENTERPRISE_STUBS_H #include #include struct ServerConnectionState; ENTERPRISE_VOID_FUNC_3ARG_DECLARE(void, RegisterLiteralServerData, EvalContext *, ctx, const char *, handle, const Promise *, pp); ENTERPRISE_FUNC_3ARG_DECLARE(int, ReturnLiteralData, EvalContext *, ctx, char *, handle, char *, ret); ENTERPRISE_FUNC_4ARG_DECLARE(int, SetServerListenState, EvalContext *, ctx, size_t, queue_size, bool, server_listen, InitServerFunction, InitServerPtr); typedef void (*ServerEntryPointFunction)(EvalContext *ctx, char *ipaddr, ConnectionInfo *info); ENTERPRISE_FUNC_1ARG_DECLARE(bool, ReceiveCollectCall, ServerConnectionState *, conn); ENTERPRISE_FUNC_3ARG_DECLARE(bool, ReturnQueryData, ServerConnectionState *, conn, char *, menu, int, encrypt); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, KeepReportDataSelectAccessPromise, const Promise *, pp); ENTERPRISE_VOID_FUNC_0ARG_DECLARE(void, CleanReportBookFilterSet); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, FprintAvahiCfengineTag, FILE *, fp); ENTERPRISE_VOID_FUNC_1ARG_DECLARE(void, CollectCallStart, ARG_UNUSED int, interval); ENTERPRISE_VOID_FUNC_0ARG_DECLARE(void, CollectCallStop); ENTERPRISE_FUNC_0ARG_DECLARE(bool, CollectCallHasPending); ENTERPRISE_FUNC_1ARG_DECLARE(int, CollectCallGetPending, ARG_UNUSED int *, queue_length); ENTERPRISE_VOID_FUNC_0ARG_DECLARE(void, CollectCallMarkProcessed); #endif cfengine-3.6.2/cf-serverd/strlist.h0000664000175100017510000000521312411001073016721 0ustar00a10038a1003800000000000000 #ifndef CFENGINE_STRLIST_H #define CFENGINE_STRLIST_H #include /** * Simple length-aware string type. Allocate with string_New. Free * simply with free(). */ struct string { size_t len; /* str length not counting terminating-'\0' */ // size_t size; /* str allocated size */ char str[]; }; struct string *string_New(const char *s); bool string_BoolCompare(const struct string *s1, const struct string *s2); size_t string_MatchCount(const struct string *s1, const struct string *s2); size_t string_ReverseMatchCount(const struct string *s1, const struct string *s2); typedef int (*StringComparatorF)(const struct string **, const struct string **); int string_Compare(const struct string **s1, const struct string **s2); int string_CompareFromEnd(const struct string **s1, const struct string **s2); /** * strlist is a list of #len strings. * * @note strlist can be NULL, which is equivalent to having 0 elements. In * fact, NULL is the properly initialised strlist, it will be * automatically allocated after using StrList_Insert() or * StrList_Append(). * * @note strlist can be a container for *any* kind of data, not only strings, * as long as it is a one-piece memory block, and a struct with first * field being "size_t len". '\0' termination is not needed at any * point, so just insert/append your custom buffers. * To use it like that use the Raw family of functions. */ typedef struct strlist { size_t len; size_t alloc_len; /* for realloc() economy */ struct string *list[]; } StrList; size_t StrList_Len(const StrList *sl); char *StrList_At(const StrList *sl, size_t idx); size_t StrList_Insert(StrList **sl, const char *s, size_t idx); size_t StrList_Append(StrList **sl, const char *s); void StrList_Finalise(StrList **sl); void StrList_Free(StrList **sl); void StrList_Sort(StrList *sl, StringComparatorF f); bool StrList_BinarySearchString(const StrList *slp, const struct string *s, size_t *position); bool StrList_BinarySearch(const StrList *slp, const char *s, size_t *position); size_t StrList_SearchLongestPrefix(const StrList *sl, const char *s, size_t s_len, char separator, bool direction_forward); size_t StrList_SearchForPrefix(const StrList *sl, const char *s, size_t s_len, bool direction_forward); #endif cfengine-3.6.2/cf-serverd/server_common.c0000664000175100017510000015205412411001073020074 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ static const int CF_NOSIZE = -1; #include #include /* ItemList2CSV_bound */ #include /* ToLower */ #include /* StringMatchFull */ #include /* EncryptString */ #include #include #include #include #include #include #include #include /* IsRegexItemIn */ #include #include /* SendSocketStream */ #include /* SendTransaction,ReceiveTransaction */ #include /* TLSSend */ #include #include #include #include /* UnexpectedError */ #include /* NovaWin_UserNameToSid */ #include /* ThreadLock */ void RefuseAccess(ServerConnectionState *conn, char *errmesg) { char *username, *ipaddr; char *def = "?"; if (strlen(conn->username) == 0) { username = def; } else { username = conn->username; } if (strlen(conn->ipaddr) == 0) { ipaddr = def; } else { ipaddr = conn->ipaddr; } char buf[CF_BUFSIZE] = ""; snprintf(buf, sizeof(buf), "%s", CF_FAILEDSTR); SendTransaction(conn->conn_info, buf, 0, CF_DONE); Log(LOG_LEVEL_VERBOSE, "REFUSAL to (user=%s,ip=%s) of request: %s", username, ipaddr, errmesg); } bool IsUserNameValid(const char *username) { /* Add whatever characters are considered invalid in username */ const char *invalid_username_characters = "\\/"; if (strpbrk(username, invalid_username_characters) == NULL) { return true; } return false; } int AllowedUser(char *user) { if (IsItemIn(SV.allowuserlist, user)) { Log(LOG_LEVEL_VERBOSE, "User %s granted connection privileges", user); return true; } Log(LOG_LEVEL_VERBOSE, "User %s is not allowed on this server", user); return false; } Item *ListPersistentClasses() { Log(LOG_LEVEL_VERBOSE, "Scanning for all persistent classes"); CF_DB *dbp; CF_DBC *dbcp; if (!OpenDB(&dbp, dbid_state)) { Log(LOG_LEVEL_ERR, "Unable to open state database"); return NULL; } if (!NewDBCursor(dbp, &dbcp)) { Log(LOG_LEVEL_ERR, "Unable to scan state database"); CloseDB(dbp); return NULL; } const PersistentClassInfo *value; int ksize, vsize; char *key; size_t count = 0; time_t now = time(NULL); Item *persistent_classes = NULL; while (NextDB(dbcp, &key, &ksize, (void **)&value, &vsize)) { if (now > value->expires) { Log(LOG_LEVEL_DEBUG, "Persistent class %s expired, removing from database", key); DBCursorDeleteEntry(dbcp); } else { count++; PrependItem(&persistent_classes, key, NULL); } } DeleteDBCursor(dbcp); CloseDB(dbp); if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { char logbuf[CF_BUFSIZE]; ItemList2CSV_bound(persistent_classes, logbuf, sizeof(logbuf), ' '); Log(LOG_LEVEL_VERBOSE, "Found %zu valid persistent classes in state database: %s", count, logbuf); } return persistent_classes; } static void ReplyNothing(ServerConnectionState *conn) { char buffer[CF_BUFSIZE]; snprintf(buffer, CF_BUFSIZE, "Hello %s (%s), nothing relevant to do here...\n\n", conn->hostname, conn->ipaddr); if (SendTransaction(conn->conn_info, buffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Unable to send transaction. (send: %s)", GetErrorStr()); } } /* Used only in EXEC protocol command, to check if any of the received classes * is defined in the server. */ int MatchClasses(EvalContext *ctx, ServerConnectionState *conn) { char recvbuffer[CF_BUFSIZE]; Item *classlist = NULL, *ip; int count = 0; while (true && (count < 10)) /* arbitrary check to avoid infinite loop, DoS attack */ { count++; if (ReceiveTransaction(conn->conn_info, recvbuffer, NULL) == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to read data from network. (ReceiveTransaction: %s)", GetErrorStr()); return false; } Log(LOG_LEVEL_DEBUG, "Got class buffer '%s'", recvbuffer); if (strncmp(recvbuffer, CFD_TERMINATOR, strlen(CFD_TERMINATOR)) == 0) { if (count == 1) { Log(LOG_LEVEL_DEBUG, "No classes were sent, assuming no restrictions..."); return true; } break; } classlist = SplitStringAsItemList(recvbuffer, ' '); for (ip = classlist; ip != NULL; ip = ip->next) { Log(LOG_LEVEL_VERBOSE, "Checking whether class %s can be identified as me...", ip->name); if (IsDefinedClass(ctx, ip->name)) { Log(LOG_LEVEL_DEBUG, "Class '%s' matched, accepting...", ip->name); DeleteItemList(classlist); return true; } { /* What the heck are we doing here? */ /* Hmmm so we iterate over all classes to see if the regex * received (ip->name) matches (StringMatchFull) to any local * class (expr)... SLOW! Change the spec! Don't accept * regexes! How many will be affected if a specific class has * to be set to run command, instead of matching a pattern? * It's safer anyway... */ ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; while ((cls = ClassTableIteratorNext(iter))) { char *expr = ClassRefToString(cls->ns, cls->name); /* FIXME: review this strcmp. Moved out from StringMatch */ bool match = (strcmp(ip->name, expr) == 0 || StringMatchFull(ip->name, expr)); free(expr); if (match) { Log(LOG_LEVEL_DEBUG, "Class matched regular expression '%s', accepting...", ip->name); DeleteItemList(classlist); return true; } } ClassTableIteratorDestroy(iter); } if (strncmp(ip->name, CFD_TERMINATOR, strlen(CFD_TERMINATOR)) == 0) { Log(LOG_LEVEL_VERBOSE, "No classes matched, rejecting...."); ReplyNothing(conn); DeleteItemList(classlist); return false; } } } ReplyNothing(conn); Log(LOG_LEVEL_VERBOSE, "No classes matched, rejecting...."); DeleteItemList(classlist); return false; } void Terminate(ConnectionInfo *connection) { char buffer[CF_BUFSIZE]; memset(buffer, 0, CF_BUFSIZE); strcpy(buffer, CFD_TERMINATOR); if (SendTransaction(connection, buffer, strlen(buffer) + 1, CF_DONE) == -1) { Log(LOG_LEVEL_VERBOSE, "Unable to reply with terminator. (send: %s)", GetErrorStr()); } } static int AuthorizeRoles(EvalContext *ctx, ServerConnectionState *conn, char *args) { char *sp; Auth *ap; char userid1[CF_MAXVARSIZE], userid2[CF_MAXVARSIZE]; Rlist *rp, *defines = NULL; int permitted = false; snprintf(userid1, CF_MAXVARSIZE, "%s@%s", conn->username, conn->hostname); snprintf(userid2, CF_MAXVARSIZE, "%s@%s", conn->username, conn->ipaddr); Log(LOG_LEVEL_VERBOSE, "Checking authorized roles in %s", args); if (strncmp(args, "--define", strlen("--define")) == 0) { sp = args + strlen("--define"); } else { sp = args + strlen("-D"); } while (*sp == ' ') { sp++; } defines = RlistFromSplitRegex(sp, "[,:;]", 99, false); /* For each user-defined class attempt, check RBAC */ for (rp = defines; rp != NULL; rp = rp->next) { Log(LOG_LEVEL_VERBOSE, "Verifying %s", RlistScalarValue(rp)); for (ap = SV.roles; ap != NULL; ap = ap->next) { if (StringMatchFull(ap->path, RlistScalarValue(rp))) { /* We have a pattern covering this class - so are we allowed to activate it? */ if ((IsMatchItemIn(ap->accesslist, conn->ipaddr)) || (IsRegexItemIn(ctx, ap->accesslist, conn->hostname)) || (IsRegexItemIn(ctx, ap->accesslist, userid1)) || (IsRegexItemIn(ctx, ap->accesslist, userid2)) || (IsRegexItemIn(ctx, ap->accesslist, conn->username))) { Log(LOG_LEVEL_VERBOSE, "Attempt to define role/class %s is permitted", RlistScalarValue(rp)); permitted = true; } else { Log(LOG_LEVEL_VERBOSE, "Attempt to define role/class %s is denied", RlistScalarValue(rp)); RlistDestroy(defines); return false; } } } } if (permitted) { Log(LOG_LEVEL_VERBOSE, "Role activation allowed"); } else { Log(LOG_LEVEL_VERBOSE, "Role activation disallowed - abort execution"); } RlistDestroy(defines); return permitted; } static int OptionFound(char *args, char *pos, char *word) /* * Returns true if the current position 'pos' in buffer * 'args' corresponds to the word 'word'. Words are * separated by spaces. */ { size_t len; if (pos < args) { return false; } /* Single options do not have to have spaces between */ if ((strlen(word) == 2) && (strncmp(pos, word, 2) == 0)) { return true; } len = strlen(word); if (strncmp(pos, word, len) != 0) { return false; } if (pos == args) { return true; } else if ((*(pos - 1) == ' ') && ((pos[len] == ' ') || (pos[len] == '\0'))) { return true; } else { return false; } } void DoExec(EvalContext *ctx, ServerConnectionState *conn, char *args) { char ebuff[CF_EXPANDSIZE], *sp = NULL; int print = false, i; FILE *pp; if ((CFSTARTTIME = time((time_t *) NULL)) == -1) { Log(LOG_LEVEL_ERR, "Couldn't read system clock. (time: %s)", GetErrorStr()); } if (strlen(CFRUNCOMMAND) == 0) { Log(LOG_LEVEL_VERBOSE, "cf-serverd exec request: no cfruncommand defined"); char sendbuffer[CF_BUFSIZE]; strlcpy(sendbuffer, "Exec request: no cfruncommand defined\n", CF_BUFSIZE); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return; } Log(LOG_LEVEL_VERBOSE, "Examining command string '%s'", args); for (sp = args; *sp != '\0'; sp++) /* Blank out -K -f */ { if ((*sp == ';') || (*sp == '&') || (*sp == '|')) { char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "You are not authorized to activate these classes/roles on host %s\n", VFQNAME); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return; } if ((OptionFound(args, sp, "-K")) || (OptionFound(args, sp, "-f"))) { *sp = ' '; *(sp + 1) = ' '; } else if (OptionFound(args, sp, "--no-lock")) { for (i = 0; i < strlen("--no-lock"); i++) { *(sp + i) = ' '; } } else if (OptionFound(args, sp, "--file")) { for (i = 0; i < strlen("--file"); i++) { *(sp + i) = ' '; } } else if ((OptionFound(args, sp, "--define")) || (OptionFound(args, sp, "-D"))) { Log(LOG_LEVEL_VERBOSE, "Attempt to activate a predefined role.."); if (!AuthorizeRoles(ctx, conn, sp)) { char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "You are not authorized to activate these classes/roles on host %s\n", VFQNAME); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return; } } } snprintf(ebuff, CF_BUFSIZE, "%s -Dcfruncommand --inform", CFRUNCOMMAND); if (strlen(ebuff) + strlen(args) + 6 > CF_BUFSIZE) { char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "Command line too long with args: %s\n", ebuff); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return; } else { if ((args != NULL) && (strlen(args) > 0)) { char sendbuffer[CF_BUFSIZE]; strcat(ebuff, " "); strncat(ebuff, args, CF_BUFSIZE - strlen(ebuff)); snprintf(sendbuffer, CF_BUFSIZE, "cf-serverd Executing %s\n", ebuff); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); } } Log(LOG_LEVEL_INFO, "Executing command %s", ebuff); if ((pp = cf_popen_sh(ebuff, "r")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (pipe: %s)", ebuff, GetErrorStr()); char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "Unable to run %s\n", ebuff); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { fflush(pp); /* FIXME: is it necessary? */ } break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (!isspace((int) *sp)) { print = true; break; } } if (print) { char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "%s\n", line); if (SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Sending failed, aborting. (send: %s)", GetErrorStr()); break; } } } free(line); cf_pclose(pp); } static int TransferRights(const ServerConnectionState *conn, const char *filename, const struct stat *sb) { Log(LOG_LEVEL_DEBUG, "Checking ownership of file: %s", filename); /* Don't do any check if connected user claims to be "root" or if * "maproot" in access_rules contains the connecting IP address. */ if ((conn->uid == 0) || (conn->maproot)) { Log(LOG_LEVEL_DEBUG, "Access granted because %s", (conn->uid == 0) ? "remote user is root" : "of maproot"); return true; /* access granted */ } #ifdef __MINGW32__ SECURITY_DESCRIPTOR *secDesc; SID *ownerSid; if (GetNamedSecurityInfo( filename, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, (PSID *) &ownerSid, NULL, NULL, NULL, (void **) &secDesc) != ERROR_SUCCESS) { Log(LOG_LEVEL_ERR, "Could not retrieve owner of file '%s' " "(GetNamedSecurityInfo: %s)", filename, GetErrorStr()); return false; } LocalFree(secDesc); if (!IsValidSid(conn->sid) || !EqualSid(ownerSid, conn->sid)) { /* If "maproot" we've already granted access. */ assert(!conn->maproot); Log(LOG_LEVEL_VERBOSE, "Remote user '%s' is not the owner of the file, access denied, " "consider maproot", conn->username); return false; } Log(LOG_LEVEL_DEBUG, "User '%s' is the owner of the file, access granted", conn->username); #else /* UNIX systems - common path */ if (sb->st_uid != conn->uid) /* does not own the file */ { if (!(sb->st_mode & S_IROTH)) /* file not world readable */ { Log(LOG_LEVEL_VERBOSE, "Remote user '%s' is not owner of the file, access denied, " "consider maproot or making file world-readable", conn->username); return false; } else { Log(LOG_LEVEL_DEBUG, "Remote user '%s' is not the owner of the file, " "but file is world readable, access granted", conn->username); /* access granted */ } } else { Log(LOG_LEVEL_DEBUG, "User '%s' is the owner of the file, access granted", conn->username); /* access granted */ } /* ADMIT ACCESS, to summarise the following condition is now true: */ /* Remote user is root, where "user" is just a string in the protocol, he * might claim whatever he wants but will be able to login only if the * user-key.pub key is found, */ assert((conn->uid == 0) || /* OR remote IP has maproot in the file's access_rules, */ (conn->maproot == true) || /* OR file is owned by the same username the user claimed - useless or * even dangerous outside NIS, KERBEROS or LDAP authenticated domains, */ (sb->st_uid == conn->uid) || /* file is readable by everyone */ (sb->st_mode & S_IROTH)); #endif return true; } static void AbortTransfer(ConnectionInfo *connection, char *filename) { Log(LOG_LEVEL_VERBOSE, "Aborting transfer of file due to source changes"); char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "%s%s: %s", CF_CHANGEDSTR1, CF_CHANGEDSTR2, filename); if (SendTransaction(connection, sendbuffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); } } static void FailedTransfer(ConnectionInfo *connection) { Log(LOG_LEVEL_VERBOSE, "Transfer failure"); char sendbuffer[CF_BUFSIZE]; snprintf(sendbuffer, CF_BUFSIZE, "%s", CF_FAILEDSTR); if (SendTransaction(connection, sendbuffer, 0, CF_DONE) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); } } void CfGetFile(ServerFileGetState *args) { int fd; off_t n_read, total = 0, sendlen = 0, count = 0; char sendbuffer[CF_BUFSIZE + 256], filename[CF_BUFSIZE]; struct stat sb; int blocksize = 2048; ConnectionInfo *conn_info = args->conn->conn_info; TranslatePath(filename, args->replyfile); stat(filename, &sb); Log(LOG_LEVEL_DEBUG, "CfGetFile('%s'), size = %jd", filename, (intmax_t) sb.st_size); /* Now check to see if we have remote permission */ if (!TransferRights(args->conn, filename, &sb)) { RefuseAccess(args->conn, args->replyfile); snprintf(sendbuffer, CF_BUFSIZE, "%s", CF_FAILEDSTR); if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_CLASSIC) { SendSocketStream(ConnectionInfoSocket(conn_info), sendbuffer, args->buf_size); } else if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_TLS) { TLSSend(ConnectionInfoSSL(conn_info), sendbuffer, args->buf_size); } return; } /* File transfer */ if ((fd = safe_open(filename, O_RDONLY)) == -1) { Log(LOG_LEVEL_ERR, "Open error of file '%s'. (open: %s)", filename, GetErrorStr()); snprintf(sendbuffer, CF_BUFSIZE, "%s", CF_FAILEDSTR); if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_CLASSIC) { SendSocketStream(ConnectionInfoSocket(conn_info), sendbuffer, args->buf_size); } else if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_TLS) { TLSSend(ConnectionInfoSSL(conn_info), sendbuffer, args->buf_size); } } else { int div = 3; if (sb.st_size > 10485760L) /* File larger than 10 MB, checks every 64kB */ { div = 32; } while (true) { memset(sendbuffer, 0, CF_BUFSIZE); Log(LOG_LEVEL_DEBUG, "Now reading from disk..."); if ((n_read = read(fd, sendbuffer, blocksize)) == -1) { Log(LOG_LEVEL_ERR, "Read failed in GetFile. (read: %s)", GetErrorStr()); break; } if (n_read == 0) { break; } else { off_t savedlen = sb.st_size; /* check the file is not changing at source */ if (count++ % div == 0) /* Don't do this too often */ { if (stat(filename, &sb)) { Log(LOG_LEVEL_ERR, "Cannot stat file '%s'. (stat: %s)", filename, GetErrorStr()); break; } } if (sb.st_size != savedlen) { snprintf(sendbuffer, CF_BUFSIZE, "%s%s: %s", CF_CHANGEDSTR1, CF_CHANGEDSTR2, filename); if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_CLASSIC) { if (SendSocketStream(ConnectionInfoSocket(conn_info), sendbuffer, blocksize) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); } } else if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_TLS) { if (TLSSend(ConnectionInfoSSL(conn_info), sendbuffer, blocksize) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); } } Log(LOG_LEVEL_DEBUG, "Aborting transfer after %jd: file is changing rapidly at source.", (intmax_t) total); break; } if ((savedlen - total) / blocksize > 0) { sendlen = blocksize; } else if (savedlen != 0) { sendlen = (savedlen - total); } } total += n_read; if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_CLASSIC) { if (SendSocketStream(ConnectionInfoSocket(conn_info), sendbuffer, sendlen) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); break; } } else if (ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_TLS) { if (TLSSend(ConnectionInfoSSL(conn_info), sendbuffer, sendlen) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); break; } } } close(fd); } } void CfEncryptGetFile(ServerFileGetState *args) /* Because the stream doesn't end for each file, we need to know the exact number of bytes transmitted, which might change during encryption, hence we need to handle this with transactions */ { int fd, n_read, cipherlen = 0, finlen = 0; off_t total = 0, count = 0; char sendbuffer[CF_BUFSIZE + 256], out[CF_BUFSIZE], filename[CF_BUFSIZE]; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; int blocksize = CF_BUFSIZE - 4 * CF_INBAND_OFFSET; EVP_CIPHER_CTX ctx; char *key, enctype; struct stat sb; ConnectionInfo *conn_info = args->conn->conn_info; key = args->conn->session_key; enctype = args->conn->encryption_type; TranslatePath(filename, args->replyfile); stat(filename, &sb); Log(LOG_LEVEL_DEBUG, "CfEncryptGetFile('%s'), size = %jd", filename, (intmax_t) sb.st_size); /* Now check to see if we have remote permission */ if (!TransferRights(args->conn, filename, &sb)) { RefuseAccess(args->conn, args->replyfile); FailedTransfer(conn_info); } EVP_CIPHER_CTX_init(&ctx); if ((fd = safe_open(filename, O_RDONLY)) == -1) { Log(LOG_LEVEL_ERR, "Open error of file '%s'. (open: %s)", filename, GetErrorStr()); FailedTransfer(conn_info); } else { int div = 3; if (sb.st_size > 10485760L) /* File larger than 10 MB, checks every 64kB */ { div = 32; } while (true) { memset(sendbuffer, 0, CF_BUFSIZE); if ((n_read = read(fd, sendbuffer, blocksize)) == -1) { Log(LOG_LEVEL_ERR, "Read failed in EncryptGetFile. (read: %s)", GetErrorStr()); break; } off_t savedlen = sb.st_size; if (count++ % div == 0) /* Don't do this too often */ { Log(LOG_LEVEL_DEBUG, "Restatting '%s' - size %d", filename, n_read); if (stat(filename, &sb)) { Log(LOG_LEVEL_ERR, "Cannot stat file '%s' (stat: %s)", filename, GetErrorStr()); break; } } if (sb.st_size != savedlen) { AbortTransfer(conn_info, filename); break; } total += n_read; if (n_read > 0) { EVP_EncryptInit_ex(&ctx, CfengineCipher(enctype), NULL, key, iv); if (!EVP_EncryptUpdate(&ctx, out, &cipherlen, sendbuffer, n_read)) { FailedTransfer(conn_info); EVP_CIPHER_CTX_cleanup(&ctx); close(fd); return; } if (!EVP_EncryptFinal_ex(&ctx, out + cipherlen, &finlen)) { FailedTransfer(conn_info); EVP_CIPHER_CTX_cleanup(&ctx); close(fd); return; } } if (total >= savedlen) { if (SendTransaction(conn_info, out, cipherlen + finlen, CF_DONE) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); EVP_CIPHER_CTX_cleanup(&ctx); close(fd); return; } break; } else { if (SendTransaction(conn_info, out, cipherlen + finlen, CF_MORE) == -1) { Log(LOG_LEVEL_VERBOSE, "Send failed in GetFile. (send: %s)", GetErrorStr()); close(fd); EVP_CIPHER_CTX_cleanup(&ctx); return; } } } } EVP_CIPHER_CTX_cleanup(&ctx); close(fd); } int StatFile(ServerConnectionState *conn, char *sendbuffer, char *ofilename) /* Because we do not know the size or structure of remote datatypes,*/ /* the simplest way to transfer the data is to convert them into */ /* plain text and interpret them on the other side. */ { Stat cfst; struct stat statbuf, statlinkbuf; char linkbuf[CF_BUFSIZE], filename[CF_BUFSIZE]; int islink = false; TranslatePath(filename, ofilename); memset(&cfst, 0, sizeof(Stat)); if (strlen(ReadLastNode(filename)) > CF_MAXLINKSIZE) { snprintf(sendbuffer, CF_BUFSIZE, "BAD: Filename suspiciously long [%s]", filename); Log(LOG_LEVEL_ERR, "%s", sendbuffer); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } if (lstat(filename, &statbuf) == -1) { snprintf(sendbuffer, CF_BUFSIZE, "BAD: unable to stat file %s", filename); Log(LOG_LEVEL_VERBOSE, "%s. (lstat: %s)", sendbuffer, GetErrorStr()); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } cfst.cf_readlink = NULL; cfst.cf_lmode = 0; cfst.cf_nlink = CF_NOSIZE; memset(linkbuf, 0, CF_BUFSIZE); #ifndef __MINGW32__ // windows doesn't support symbolic links if (S_ISLNK(statbuf.st_mode)) { islink = true; cfst.cf_type = FILE_TYPE_LINK; /* pointless - overwritten */ cfst.cf_lmode = statbuf.st_mode & 07777; cfst.cf_nlink = statbuf.st_nlink; if (readlink(filename, linkbuf, CF_BUFSIZE - 1) == -1) { strcpy(sendbuffer, "BAD: unable to read link"); Log(LOG_LEVEL_ERR, "%s. (readlink: %s)", sendbuffer, GetErrorStr()); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } Log(LOG_LEVEL_DEBUG, "readlink '%s'", linkbuf); cfst.cf_readlink = linkbuf; } #endif /* !__MINGW32__ */ if ((!islink) && (stat(filename, &statbuf) == -1)) { Log(LOG_LEVEL_VERBOSE, "BAD: unable to stat file '%s'. (stat: %s)", filename, GetErrorStr()); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } Log(LOG_LEVEL_DEBUG, "Getting size of link deref '%s'", linkbuf); if (islink && (stat(filename, &statlinkbuf) != -1)) /* linktype=copy used by agent */ { statbuf.st_size = statlinkbuf.st_size; statbuf.st_mode = statlinkbuf.st_mode; statbuf.st_uid = statlinkbuf.st_uid; statbuf.st_gid = statlinkbuf.st_gid; statbuf.st_mtime = statlinkbuf.st_mtime; statbuf.st_ctime = statlinkbuf.st_ctime; } if (S_ISDIR(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_DIR; } if (S_ISREG(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_REGULAR; } if (S_ISSOCK(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_SOCK; } if (S_ISCHR(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_CHAR_; } if (S_ISBLK(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_BLOCK; } if (S_ISFIFO(statbuf.st_mode)) { cfst.cf_type = FILE_TYPE_FIFO; } cfst.cf_mode = statbuf.st_mode & 07777; cfst.cf_uid = statbuf.st_uid & 0xFFFFFFFF; cfst.cf_gid = statbuf.st_gid & 0xFFFFFFFF; cfst.cf_size = statbuf.st_size; cfst.cf_atime = statbuf.st_atime; cfst.cf_mtime = statbuf.st_mtime; cfst.cf_ctime = statbuf.st_ctime; cfst.cf_ino = statbuf.st_ino; cfst.cf_dev = statbuf.st_dev; cfst.cf_readlink = linkbuf; if (cfst.cf_nlink == CF_NOSIZE) { cfst.cf_nlink = statbuf.st_nlink; } #if !defined(__MINGW32__) if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE) #else # ifdef HAVE_ST_BLOCKS if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE) # else if (statbuf.st_size > ST_NBLOCKS(statbuf) * DEV_BSIZE) # endif #endif { cfst.cf_makeholes = 1; /* must have a hole to get checksum right */ } else { cfst.cf_makeholes = 0; } memset(sendbuffer, 0, CF_BUFSIZE); /* send as plain text */ Log(LOG_LEVEL_DEBUG, "OK: type = %d, mode = %jo, lmode = %jo, " "uid = %ju, gid = %ju, size = %jd, atime=%jd, mtime = %jd", cfst.cf_type, (uintmax_t) cfst.cf_mode, (uintmax_t) cfst.cf_lmode, (uintmax_t) cfst.cf_uid, (uintmax_t) cfst.cf_gid, (intmax_t) cfst.cf_size, (intmax_t) cfst.cf_atime, (intmax_t) cfst.cf_mtime); snprintf(sendbuffer, CF_BUFSIZE, "OK: %d %ju %ju %ju %ju %jd %jd %jd %jd %d %d %d %jd", cfst.cf_type, (uintmax_t) cfst.cf_mode, (uintmax_t) cfst.cf_lmode, (uintmax_t) cfst.cf_uid, (uintmax_t) cfst.cf_gid, (intmax_t) cfst.cf_size, (intmax_t) cfst.cf_atime, (intmax_t) cfst.cf_mtime, (intmax_t) cfst.cf_ctime, cfst.cf_makeholes, cfst.cf_ino, cfst.cf_nlink, (intmax_t) cfst.cf_dev); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); memset(sendbuffer, 0, CF_BUFSIZE); if (cfst.cf_readlink != NULL) { strcpy(sendbuffer, "OK:"); strcat(sendbuffer, cfst.cf_readlink); } else { strcpy(sendbuffer, "OK:"); } SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return 0; } bool CompareLocalHash(const char *filename, const char digest[EVP_MAX_MD_SIZE + 1], char sendbuffer[CF_BUFSIZE]) { char translated_filename[CF_BUFSIZE] = { 0 }; TranslatePath(translated_filename, filename); unsigned char file_digest[EVP_MAX_MD_SIZE + 1] = { 0 }; /* TODO connection might timeout if this takes long! */ HashFile(translated_filename, file_digest, CF_DEFAULT_DIGEST); if (HashesMatch(digest, file_digest, CF_DEFAULT_DIGEST)) { assert(strlen(CFD_FALSE) < CF_BUFSIZE); strcpy(sendbuffer, CFD_FALSE); Log(LOG_LEVEL_DEBUG, "Hashes matched ok"); return true; } else { assert(strlen(CFD_TRUE) < CF_BUFSIZE); strcpy(sendbuffer, CFD_TRUE); Log(LOG_LEVEL_DEBUG, "Hashes didn't match"); return false; } } void GetServerLiteral(EvalContext *ctx, ServerConnectionState *conn, char *sendbuffer, char *recvbuffer, int encrypted) { char handle[CF_BUFSIZE], out[CF_BUFSIZE]; int cipherlen; sscanf(recvbuffer, "VAR %255[^\n]", handle); if (ReturnLiteralData(ctx, handle, out)) { memset(sendbuffer, 0, CF_BUFSIZE); snprintf(sendbuffer, CF_BUFSIZE - 1, "%s", out); } else { memset(sendbuffer, 0, CF_BUFSIZE); snprintf(sendbuffer, CF_BUFSIZE - 1, "BAD: Not found"); } if (encrypted) { cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, strlen(sendbuffer) + 1); SendTransaction(conn->conn_info, out, cipherlen, CF_DONE); } else { SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); } } int GetServerQuery(ServerConnectionState *conn, char *recvbuffer, int encrypt) { char query[CF_BUFSIZE]; query[0] = '\0'; sscanf(recvbuffer, "QUERY %255[^\n]", query); if (strlen(query) == 0) { return false; } return ReturnQueryData(conn, query, encrypt); } void ReplyServerContext(ServerConnectionState *conn, int encrypted, Item *classes) { char sendbuffer[CF_BUFSIZE]; size_t ret = ItemList2CSV_bound(classes, sendbuffer, sizeof(sendbuffer), ','); if (ret >= sizeof(sendbuffer)) { Log(LOG_LEVEL_ERR, "Overflow: classes don't fit in send buffer"); } DeleteItemList(classes); if (encrypted) { char out[CF_BUFSIZE]; int cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, strlen(sendbuffer) + 1); SendTransaction(conn->conn_info, out, cipherlen, CF_DONE); } else { SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); } } int CfOpenDirectory(ServerConnectionState *conn, char *sendbuffer, char *oldDirname) { Dir *dirh; const struct dirent *dirp; int offset; char dirname[CF_BUFSIZE]; TranslatePath(dirname, oldDirname); if (!IsAbsoluteFileName(dirname)) { strcpy(sendbuffer, "BAD: request to access a non-absolute filename"); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } if ((dirh = DirOpen(dirname)) == NULL) { Log(LOG_LEVEL_INFO, "Couldn't open directory '%s' (DirOpen:%s)", dirname, GetErrorStr()); snprintf(sendbuffer, CF_BUFSIZE, "BAD: cfengine, couldn't open dir %s", dirname); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return -1; } /* Pack names for transmission */ memset(sendbuffer, 0, CF_BUFSIZE); offset = 0; for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (strlen(dirp->d_name) + 1 + offset >= CF_BUFSIZE - CF_MAXLINKSIZE) { SendTransaction(conn->conn_info, sendbuffer, offset + 1, CF_MORE); offset = 0; memset(sendbuffer, 0, CF_BUFSIZE); } strlcpy(sendbuffer + offset, dirp->d_name, CF_MAXLINKSIZE); offset += strlen(dirp->d_name) + 1; /* + zero byte separator */ } strcpy(sendbuffer + offset, CFD_TERMINATOR); SendTransaction(conn->conn_info, sendbuffer, offset + 2 + strlen(CFD_TERMINATOR), CF_DONE); DirClose(dirh); return 0; } /**************************************************************/ int CfSecOpenDirectory(ServerConnectionState *conn, char *sendbuffer, char *dirname) { Dir *dirh; const struct dirent *dirp; int offset, cipherlen; char out[CF_BUFSIZE]; if (!IsAbsoluteFileName(dirname)) { strcpy(sendbuffer, "BAD: request to access a non-absolute filename"); cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, strlen(sendbuffer) + 1); SendTransaction(conn->conn_info, out, cipherlen, CF_DONE); return -1; } if ((dirh = DirOpen(dirname)) == NULL) { Log(LOG_LEVEL_VERBOSE, "Couldn't open dir %s", dirname); snprintf(sendbuffer, CF_BUFSIZE, "BAD: cfengine, couldn't open dir %s", dirname); cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, strlen(sendbuffer) + 1); SendTransaction(conn->conn_info, out, cipherlen, CF_DONE); return -1; } /* Pack names for transmission */ memset(sendbuffer, 0, CF_BUFSIZE); offset = 0; for (dirp = DirRead(dirh); dirp != NULL; dirp = DirRead(dirh)) { if (strlen(dirp->d_name) + 1 + offset >= CF_BUFSIZE - CF_MAXLINKSIZE) { cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, offset + 1); SendTransaction(conn->conn_info, out, cipherlen, CF_MORE); offset = 0; memset(sendbuffer, 0, CF_BUFSIZE); memset(out, 0, CF_BUFSIZE); } strlcpy(sendbuffer + offset, dirp->d_name, CF_MAXLINKSIZE); /* + zero byte separator */ offset += strlen(dirp->d_name) + 1; } strcpy(sendbuffer + offset, CFD_TERMINATOR); cipherlen = EncryptString(conn->encryption_type, sendbuffer, out, conn->session_key, offset + 2 + strlen(CFD_TERMINATOR)); SendTransaction(conn->conn_info, out, cipherlen, CF_DONE); DirClose(dirh); return 0; } /********************* MISC UTILITY FUNCTIONS *************************/ /** * Replace all occurences of #find with #replace. * * @return the length of #buf or (size_t) -1 in case of overflow, or 0 * if no replace took place. */ static size_t StringReplace(char *buf, size_t buf_size, const char *find, const char *replace) { assert(find[0] != '\0'); char *p = strstr(buf, find); if (p == NULL) { return 0; } size_t find_len = strlen(find); size_t replace_len = strlen(replace); size_t buf_len = strlen(buf); size_t buf_idx = 0; char tmp[buf_size]; size_t tmp_len = 0; /* Do all replacements we find. */ do { size_t buf_newidx = p - buf; size_t prefix_len = buf_newidx - buf_idx; if (tmp_len + prefix_len + replace_len >= buf_size) { return (size_t) -1; } memcpy(&tmp[tmp_len], &buf[buf_idx], prefix_len); tmp_len += prefix_len; memcpy(&tmp[tmp_len], replace, replace_len); tmp_len += replace_len; buf_idx = buf_newidx + find_len; p = strstr(&buf[buf_idx], find); } while (p != NULL); /* Copy leftover plus terminating '\0'. */ size_t leftover_len = buf_len - buf_idx; if (tmp_len + leftover_len >= buf_size) { return (size_t) -1; } memcpy(&tmp[tmp_len], &buf[buf_idx], leftover_len + 1); tmp_len += leftover_len; /* And finally copy to source, we are supposed to modify it in place. */ memcpy(buf, tmp, tmp_len + 1); return tmp_len; } /** * Search and replace occurences of #find1, #find2, #find3, with * #repl1, #repl2, #repl3 respectively. * * "$(connection.ip)" from "191.168.0.1" * "$(connection.hostname)" from "blah.cfengine.com", * "$(connection.key)" from "SHA=asdfghjkl" * * @return the output length of #buf, (size_t) -1 if overflow would occur, * or 0 if no replacement happened and #buf was not touched. * * @TODO change the function to more generic interface accepting arbitrary * find/replace pairs. */ size_t ReplaceSpecialVariables(char *buf, size_t buf_size, const char *find1, const char *repl1, const char *find2, const char *repl2, const char *find3, const char *repl3) { size_t ret = 0; if ((find1 != NULL) && (find1[0] != '\0') && (repl1 != NULL) && (repl1[0] != '\0')) { size_t ret2 = StringReplace(buf, buf_size, find1, repl1); ret = MAX(ret, ret2); /* size_t is unsigned, thus -1 wins */ } if ((ret != (size_t) -1) && (find2 != NULL) && (find2[0] != '\0') && (repl2 != NULL) && (repl2[0] != '\0')) { size_t ret2 = StringReplace(buf, buf_size, find2, repl2); ret = MAX(ret, ret2); } if ((ret != (size_t) -1) && (find3 != NULL) && (find3[0] != '\0') && (repl3 != NULL) && (repl3[0] != '\0')) { size_t ret2 = StringReplace(buf, buf_size, find3, repl3); ret = MAX(ret, ret2); } /* Zero is returned only if all of the above were zero. */ return ret; } /** * Remove trailing FILE_SEPARATOR, unless we're referring to root dir: '/' or 'a:\' */ bool PathRemoveTrailingSlash(char *s, size_t s_len) { char *first_separator = strchr(s, FILE_SEPARATOR); if (first_separator != NULL && s[s_len-1] == FILE_SEPARATOR && &s[s_len-1] != first_separator) { s[s_len-1] = '\0'; return true; } return false; } /** * Append a trailing FILE_SEPARATOR if it's not there. */ bool PathAppendTrailingSlash(char *s, size_t s_len) { if (s_len > 0 && s[s_len-1] != FILE_SEPARATOR) { s[s_len] = FILE_SEPARATOR; s[s_len+1] = '\0'; return true; } return false; } /* We use this instead of IsAbsoluteFileName() which also checks for * quotes. There is no meaning in receiving quoted strings over the * network. */ static bool PathIsAbsolute(const char *s) { bool result = false; #if defined(__MINGW32__) if (isalpha(s[0]) && (s[1] == ':') && (s[2] == FILE_SEPARATOR)) { result = true; /* A:\ */ } else /* \\ */ { result = (s[0] == FILE_SEPARATOR && s[1] == FILE_SEPARATOR); } #else if (s[0] == FILE_SEPARATOR) /* / */ { result = true; } #endif return result; } /** * If #path is relative, expand the first part accorting to #shortcuts, doing * any replacements of special variables "$(connection.*)" on the way, with * the provided #ipaddr, #hostname, #key. * * @return the length of the new string or 0 if no replace took place. -1 in * case of overflow. */ size_t ShortcutsExpand(char *path, size_t path_size, const StringMap *shortcuts, const char *ipaddr, const char *hostname, const char *key) { char dst[path_size]; size_t path_len = strlen(path); if (path_len == 0) { UnexpectedError("ShortcutsExpand: 0 length string!"); return (size_t) -1; } if (!PathIsAbsolute(path)) { char *separ = strchr(path, FILE_SEPARATOR); size_t first_part_len; if (separ != NULL) { first_part_len = separ - path; assert(first_part_len < path_len); } else { first_part_len = path_len; } size_t second_part_len = path_len - first_part_len; /* '\0'-terminate first_part, do StringMapGet(), undo '\0'-term */ char separ_char = path[first_part_len]; path[first_part_len] = '\0'; char *replacement = StringMapGet(shortcuts, path); path[first_part_len] = separ_char; /* Either the first_part ends with separator, or its all the string */ assert(separ_char == FILE_SEPARATOR || separ_char == '\0'); if (replacement != NULL) /* we found a shortcut */ { size_t replacement_len = strlen(replacement); if (replacement_len + 1 > path_size) { goto err_too_long; } /* Replacement path for shortcut was found, but it may contain * special variables such as $(connection.ip), that we also need * to expand. */ /* TODO if StrAnyStr(replacement, "$(connection.ip)", "$(connection.hostname)", "$(connection.key)") */ char replacement_expanded[path_size]; memcpy(replacement_expanded, replacement, replacement_len + 1); size_t ret = ReplaceSpecialVariables(replacement_expanded, sizeof(replacement_expanded), "$(connection.ip)", ipaddr, "$(connection.hostname)", hostname, "$(connection.key)", key); size_t replacement_expanded_len; /* (ret == -1) is checked later. */ if (ret == 0) /* No expansion took place */ { replacement_expanded_len = replacement_len; } else { replacement_expanded_len = ret; } size_t dst_len = replacement_expanded_len + second_part_len; if (ret == (size_t) -1 || dst_len + 1 > path_size) { goto err_too_long; } /* Assemble final result. */ memcpy(dst, replacement_expanded, replacement_expanded_len); /* Second part may be empty, then this only copies '\0'. */ memcpy(&dst[replacement_expanded_len], &path[first_part_len], second_part_len + 1); Log(LOG_LEVEL_DEBUG, "ShortcutsExpand: Path '%s' became: %s", path, dst); /* Copy back to path. */ memcpy(path, dst, dst_len + 1); return dst_len; } } /* No expansion took place, either because path was absolute, or because * no shortcut was found. */ return 0; err_too_long: Log(LOG_LEVEL_INFO, "Path too long after shortcut expansion!"); return (size_t) -1; } /** * Canonicalize a path, ensure it is absolute, and resolve all symlinks. * In detail: * * 1. MinGW: Translate to windows-compatible: slashes to FILE_SEPARATOR * and uppercase to lowercase. * 2. Ensure the path is absolute. * 3. Resolve symlinks, resolve '.' and '..' and remove double '/' * WARNING this will currently fail if file does not exist, * returning -1 and setting errno==ENOENT! * * @note trailing slash is left as is if it's there. * @note #reqpath is written in place (if success was returned). It is always * an absolute path. * @note #reqpath is invalid to be of zero length. * @note #reqpath_size must be at least PATH_MAX. * * @return the length of #reqpath after preprocessing. In case of error * return (size_t) -1. */ size_t PreprocessRequestPath(char *reqpath, size_t reqpath_size) { errno = 0; /* on return, errno might be set from realpath() */ char dst[reqpath_size]; size_t reqpath_len = strlen(reqpath); if (reqpath_len == 0) { UnexpectedError("PreprocessRequestPath: 0 length string!"); return (size_t) -1; } /* Translate all slashes to backslashes on Windows so that all the rest * of work is done using FILE_SEPARATOR. THIS HAS TO BE FIRST. */ #if defined(__MINGW32__) { char *p = reqpath; while ((p = strchr(p, '/')) != NULL) { *p = FILE_SEPARATOR; } /* Also convert everything to lowercase. */ ToLowerStrInplace(reqpath); } #endif if (!PathIsAbsolute(reqpath)) { Log(LOG_LEVEL_INFO, "Relative paths are not allowed: %s", reqpath); return (size_t) -1; } /* TODO replace realpath with Solaris' resolvepath(), in all * platforms. That one does not check for existence, just resolves * symlinks and canonicalises. Ideally we would want the following: * * PathResolve(dst, src, dst_size, basedir); * * - It prepends basedir if path relative (could be the shortcut) * - It compresses double '/', '..', '.' * - It follows each component of the path replacing symlinks * - errno = ENOENT if path component does not exist, but keeps * compressing path anyway. * - Leaves trailing slash as it was passed to it. * OR appends it depending on last component ISDIR. */ assert(sizeof(dst) >= PATH_MAX); /* needed for realpath() */ char *p = realpath(reqpath, dst); if (p == NULL) { /* TODO If path does not exist try to canonicalise only directory. INSECURE?*/ /* if (errno == ENOENT) */ /* { */ /* } */ struct stat statbuf; if ((lstat(reqpath, &statbuf) == 0) && S_ISLNK(statbuf.st_mode)) { Log(LOG_LEVEL_VERBOSE, "Requested file is a dead symbolic link (filename: %s)", reqpath); strlcpy(dst, reqpath, CF_BUFSIZE); } else { Log(LOG_LEVEL_INFO, "Failed to canonicalise filename '%s' (realpath: %s)", reqpath, GetErrorStr()); return (size_t) -1; } } size_t dst_len = strlen(dst); /* Some realpath()s remove trailing '/' even for dirs! Put it back if * original request had it. */ if (reqpath[reqpath_len - 1] == FILE_SEPARATOR && dst[dst_len - 1] != FILE_SEPARATOR) { if (dst_len + 2 > sizeof(dst)) { Log(LOG_LEVEL_INFO, "Error, path too long: %s", reqpath); return (size_t) -1; } PathAppendTrailingSlash(dst, dst_len); dst_len++; } memcpy(reqpath, dst, dst_len + 1); reqpath_len = dst_len; return reqpath_len; } /** * Set conn->uid (and conn->sid on Windows). */ void SetConnIdentity(ServerConnectionState *conn, const char *username) { size_t username_len = strlen(username); conn->uid = CF_UNKNOWN_OWNER; conn->username[0] = '\0'; if (username_len < sizeof(conn->username)) { memcpy(conn->username, username, username_len + 1); } #ifdef __MINGW32__ /* NT uses security identifier instead of uid */ bool is_root = strcmp(conn->username, "root") == 0; if (!NovaWin_UserNameToSid(conn->username, (SID *) conn->sid, CF_MAXSIDSIZE, !is_root)) { memset(conn->sid, 0, CF_MAXSIDSIZE); /* is invalid sid - discarded */ } if (is_root) { /* It the remote user identifies himself as root, even on Windows * cf-serverd must grant access to all files. uid==0 is checked later * in TranferRights() for that. */ conn->uid = 0; } #else /* UNIX - common path */ static pthread_mutex_t pwnam_mtx = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; struct passwd *pw = NULL; if (ThreadLock(&pwnam_mtx)) { pw = getpwnam(conn->username); if (pw != NULL) { conn->uid = pw->pw_uid; } ThreadUnlock(&pwnam_mtx); } #endif } cfengine-3.6.2/cf-serverd/cf-serverd-enterprise-stubs.c0000644000175100017510000000647712352022221022601 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include ENTERPRISE_VOID_FUNC_3ARG_DEFINE_STUB(void, RegisterLiteralServerData, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED const char *, handle, ARG_UNUSED const Promise *, pp) { Log(LOG_LEVEL_VERBOSE, "Access to server literals is only available in CFEngine Enterprise"); } ENTERPRISE_FUNC_3ARG_DEFINE_STUB(int, ReturnLiteralData, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED char *, handle, ARG_UNUSED char *, ret) { Log(LOG_LEVEL_VERBOSE, "Access to server literals is only available in CFEngine Enterprise"); return 0; } ENTERPRISE_FUNC_4ARG_DEFINE_STUB(int, SetServerListenState, ARG_UNUSED EvalContext *, ctx, ARG_UNUSED size_t, queue_size, ARG_UNUSED bool, server_listen, InitServerFunction, InitServerPtr) { if (!server_listen) { Log(LOG_LEVEL_VERBOSE, "Disable listening on port is only supported in CFEngine Enterprise"); } return InitServerPtr(queue_size); } ENTERPRISE_FUNC_1ARG_DEFINE_STUB(bool, ReceiveCollectCall, ARG_UNUSED ServerConnectionState *, conn) { return false; } ENTERPRISE_FUNC_3ARG_DEFINE_STUB(bool, ReturnQueryData, ARG_UNUSED ServerConnectionState *, conn, ARG_UNUSED char *, menu, ARG_UNUSED int, encrypt) { return false; } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, KeepReportDataSelectAccessPromise, ARG_UNUSED const Promise *, pp) { Log(LOG_LEVEL_ERR, "Report data select is only available in CFEngine Enterprise"); } ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(void, CleanReportBookFilterSet) { return; } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, CollectCallStart, ARG_UNUSED int, interval) { } ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(void, CollectCallStop) { } ENTERPRISE_FUNC_0ARG_DEFINE_STUB(bool, CollectCallHasPending) { return false; } ENTERPRISE_FUNC_1ARG_DEFINE_STUB(int, CollectCallGetPending, ARG_UNUSED int *, queue_length) { return -1; } ENTERPRISE_VOID_FUNC_0ARG_DEFINE_STUB(void, CollectCallMarkProcessed) { } ENTERPRISE_VOID_FUNC_1ARG_DEFINE_STUB(void, FprintAvahiCfengineTag, FILE *, fp) { fprintf(fp,"CFEngine Community %s Policy Server on %s \n", Version(), "%h"); } cfengine-3.6.2/cf-serverd/server_tls.c0000664000175100017510000010257112411001073017405 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #include #include #include /* ERR_get_error */ #include /* DecryptString */ #include #include #include /* IsMatchItemIn */ #include /* LastSaw1 */ #include /* SendTransaction,ReceiveTransaction */ #include /* TLSSend */ #include #include #include /* StringMatchFull */ #include #include /* IsDirReal */ #include "server_access.h" /* access_CheckResource, acl_CheckExact */ static SSL_CTX *SSLSERVERCONTEXT = NULL; /* GLOBAL_X */ static X509 *SSLSERVERCERT = NULL; /* GLOBAL_X */ /** * @warning Make sure you've called CryptoInitialize() first! */ bool ServerTLSInitialize() { int ret; if (!TLSGenericInitialize()) { return false; } assert(SSLSERVERCONTEXT == NULL); SSLSERVERCONTEXT = SSL_CTX_new(SSLv23_server_method()); if (SSLSERVERCONTEXT == NULL) { Log(LOG_LEVEL_ERR, "SSL_CTX_new: %s", TLSErrorString(ERR_get_error())); goto err1; } TLSSetDefaultOptions(SSLSERVERCONTEXT); /* * CFEngine is not a web server so we don't need many ciphers. We only * allow a safe but very common subset by default, extensible via * "allowciphers" in body server control. By default allow: * AES256-GCM-SHA384: most high-grade RSA-based cipher from TLSv1.2 * AES256-SHA: most backwards compatible but high-grade, from SSLv3 */ const char *cipher_list = SV.allowciphers; if (cipher_list == NULL) { cipher_list ="AES256-GCM-SHA384:AES256-SHA"; } ret = SSL_CTX_set_cipher_list(SSLSERVERCONTEXT, cipher_list); if (ret != 1) { Log(LOG_LEVEL_ERR, "No valid ciphers in cipher list: %s", cipher_list); } if (PRIVKEY == NULL || PUBKEY == NULL) { Log(LOG_LEVEL_ERR, "No public/private key pair is loaded, create one with cf-key"); goto err2; } assert(SSLSERVERCERT == NULL); /* Create cert into memory and load it into SSL context. */ SSLSERVERCERT = TLSGenerateCertFromPrivKey(PRIVKEY); if (SSLSERVERCERT == NULL) { Log(LOG_LEVEL_ERR, "Failed to generate in-memory certificate from private key"); goto err2; } SSL_CTX_use_certificate(SSLSERVERCONTEXT, SSLSERVERCERT); ret = SSL_CTX_use_RSAPrivateKey(SSLSERVERCONTEXT, PRIVKEY); if (ret != 1) { Log(LOG_LEVEL_ERR, "Failed to use RSA private key: %s", TLSErrorString(ERR_get_error())); goto err3; } /* Verify cert consistency. */ ret = SSL_CTX_check_private_key(SSLSERVERCONTEXT); if (ret != 1) { Log(LOG_LEVEL_ERR, "Inconsistent key and TLS cert: %s", TLSErrorString(ERR_get_error())); goto err3; } return true; err3: X509_free(SSLSERVERCERT); SSLSERVERCERT = NULL; err2: SSL_CTX_free(SSLSERVERCONTEXT); SSLSERVERCONTEXT = NULL; err1: return false; } void ServerTLSDeInitialize() { if (PUBKEY) { RSA_free(PUBKEY); PUBKEY = NULL; } if (PRIVKEY) { RSA_free(PRIVKEY); PRIVKEY = NULL; } if (SSLSERVERCERT != NULL) { X509_free(SSLSERVERCERT); SSLSERVERCERT = NULL; } if (SSLSERVERCONTEXT != NULL) { SSL_CTX_free(SSLSERVERCONTEXT); SSLSERVERCONTEXT = NULL; } } /** * @brief Set the connection type to CLASSIC or TLS. * It is performed by peeking into the TLS connection to read the first bytes, * and if it's a CAUTH protocol command use the old protocol loop, else use * the TLS protocol loop. * This must be the first thing we run on an accepted connection. * * @return -1 in case of error, 1 otherwise. */ int ServerTLSPeek(ConnectionInfo *conn_info) { assert(SSLSERVERCONTEXT != NULL && PRIVKEY != NULL && PUBKEY != NULL); assert(ConnectionInfoProtocolVersion(conn_info) == CF_PROTOCOL_UNDEFINED); const int peek_size = CF_INBAND_OFFSET + sizeof("CAUTH"); char buf[peek_size]; ssize_t got = recv(ConnectionInfoSocket(conn_info), buf, sizeof(buf), MSG_PEEK); assert(got <= peek_size); if (got < 0) { assert(got == -1); Log(LOG_LEVEL_ERR, "TCP receive error: %s", GetErrorStr()); return -1; } else if (got == 0) { Log(LOG_LEVEL_INFO, "Peer closed TCP connection without sending data!"); return -1; } else if (got < peek_size) { Log(LOG_LEVEL_INFO, "Peer sent only %zd bytes! Considering the protocol as Classic", got); ConnectionInfoSetProtocolVersion(conn_info, CF_PROTOCOL_CLASSIC); } else if (memcmp(&buf[CF_INBAND_OFFSET], "CAUTH", strlen("CAUTH")) == 0) { Log(LOG_LEVEL_VERBOSE, "Peeked CAUTH in TCP stream, considering the protocol as Classic"); ConnectionInfoSetProtocolVersion(conn_info, CF_PROTOCOL_CLASSIC); } else /* got==peek_size && not "CAUTH" */ { Log(LOG_LEVEL_VERBOSE, "Peeked nothing important in TCP stream, considering the protocol as TLS"); ConnectionInfoSetProtocolVersion(conn_info, CF_PROTOCOL_TLS); } LogRaw(LOG_LEVEL_DEBUG, "Peeked data: ", buf, got); return 1; } /** * 1. Send "CFE_v%d" server hello. * 2. Receive two lines: One "CFE_v%d" with the protocol version the client * wishes to have, and one "IDENTITY USERNAME=blah ..." with identification * information for the client. * * @note For Identification dialog to end successfully, one "OK WELCOME" line * must be sent right after this function, after identity is verified. * * @TODO More protocol identity. E.g. * IDENTITY USERNAME=xxx HOSTNAME=xxx CUSTOMNAME=xxx * * @retval true if protocol version was successfully negotiated and IDENTITY * command was parsed correctly. Identity fields (only #username for * now) have the respective string values, or they are empty if field * was not on IDENTITY line. #conn_info->type has been updated with * the negotiated protocol version. * @retval false in case of error. */ static bool ServerIdentificationDialog(ConnectionInfo *conn_info, char *username, size_t username_size) { int ret; char input[1024] = ""; /* The only protocol version we support inside TLS, for now. */ const int SERVER_PROTOCOL_VERSION = CF_PROTOCOL_LATEST; /* Send "CFE_v%d cf-serverd version". */ char version_string[CF_MAXVARSIZE]; int len = snprintf(version_string, sizeof(version_string), "CFE_v%d cf-serverd %s\n", SERVER_PROTOCOL_VERSION, VERSION); ret = TLSSend(conn_info->ssl, version_string, len); if (ret != len) { Log(LOG_LEVEL_NOTICE, "Connection was hung up!"); return false; } /* Receive CFE_v%d ... \n IDENTITY USERNAME=... */ int input_len = TLSRecvLines(conn_info->ssl, input, sizeof(input)); if (input_len <= 0) { Log(LOG_LEVEL_NOTICE, "Client closed connection early! He probably does not trust our key..."); return false; } int version_received = -1; ret = sscanf(input, "CFE_v%d", &version_received); if (ret != 1) { Log(LOG_LEVEL_NOTICE, "Protocol version negotiation failed! Received: %s", input); return false; } /* For now we support only one version inside TLS. */ /* TODO value should not be hardcoded but compared to enum ProtocolVersion. */ if (version_received != SERVER_PROTOCOL_VERSION) { Log(LOG_LEVEL_NOTICE, "Client advertises disallowed protocol version: %d", version_received); return false; /* TODO send "BAD ..." ? */ } /* Did we receive 2nd line or do we need to receive again? */ const char id_line[] = "\nIDENTITY "; char *line2 = memmem(input, input_len, id_line, strlen(id_line)); if (line2 == NULL) { /* Wait for 2nd line to arrive. */ input_len = TLSRecvLines(conn_info->ssl, input, sizeof(input)); if (input_len <= 0) { Log(LOG_LEVEL_NOTICE, "Client closed connection during identification dialog!"); return false; } line2 = input; } else { line2++; /* skip '\n' */ } /***** Parse all IDENTITY fields from line2 *****/ char word1[1024], word2[1024]; int line2_pos = 0, chars_read = 0; /* Reset all identity variables, we'll set them according to fields * on IDENTITY line. For now only "username" setting exists... */ username[0] = '\0'; /* Assert sscanf() is safe to use. */ assert(sizeof(word1)>=sizeof(input) && sizeof(word2)>=sizeof(input)); ret = sscanf(line2, "IDENTITY %[^=]=%s%n", word1, word2, &chars_read); while (ret >= 2) { /* Found USERNAME identity setting */ if (strcmp(word1, "USERNAME") == 0) { if ((strlen(word2) < username_size) && (IsUserNameValid(word2) == true)) { strcpy(username, word2); } else { Log(LOG_LEVEL_NOTICE, "Received invalid IDENTITY: %s=%s", word1, word2); return false; } Log(LOG_LEVEL_VERBOSE, "Setting IDENTITY: %s=%s", word1, word2); } /* ... else if (strcmp()) for other acceptable IDENTITY parameters. */ else { Log(LOG_LEVEL_VERBOSE, "Received unknown IDENTITY parameter: %s=%s", word1, word2); } line2_pos += chars_read; ret = sscanf(&line2[line2_pos], " %[^=]=%s%n", word1, word2, &chars_read); } /* Version client and server agreed on. */ conn_info->type = version_received; return true; } static int ServerSendWelcome(const ServerConnectionState *conn) { char s[1024] = "OK WELCOME"; size_t len = strlen(s); int ret; /* "OK WELCOME" is the important part. The rest is just extra verbosity. */ if (conn->username[0] != '\0') { ret = snprintf(&s[len], sizeof(s) - len, " %s=%s", "USERNAME", conn->username); if (ret >= sizeof(s) - len) { Log(LOG_LEVEL_NOTICE, "Sending OK WELCOME message truncated: %s", s); return -1; } len += ret; } /* Overwrite the terminating '\0', we don't need it anyway. */ s[len] = '\n'; len++; ret = TLSSend(conn->conn_info->ssl, s, len); if (ret == -1) { return -1; } return 1; } /** * @brief Accept a TLS connection and authenticate and identify. * @note Various fields in #conn are set, like username and keyhash. */ int ServerTLSSessionEstablish(ServerConnectionState *conn) { int ret; if (ConnectionInfoConnectionStatus(conn->conn_info) != CF_CONNECTION_ESTABLISHED) { assert(ConnectionInfoSSL(conn->conn_info) == NULL); SSL *ssl = SSL_new(SSLSERVERCONTEXT); if (ssl == NULL) { Log(LOG_LEVEL_ERR, "SSL_new: %s", TLSErrorString(ERR_get_error())); return -1; } ConnectionInfoSetSSL(conn->conn_info, ssl); /* Pass conn_info inside the ssl struct for TLSVerifyCallback(). */ SSL_set_ex_data(ssl, CONNECTIONINFO_SSL_IDX, conn->conn_info); /* Now we are letting OpenSSL take over the open socket. */ SSL_set_fd(ssl, ConnectionInfoSocket(conn->conn_info)); ret = SSL_accept(ssl); if (ret <= 0) { TLSLogError(ssl, LOG_LEVEL_ERR, "Failed to accept TLS connection", ret); return -1; } Log(LOG_LEVEL_VERBOSE, "TLS cipher negotiated: %s, %s", SSL_get_cipher_name(ssl), SSL_get_cipher_version(ssl)); Log(LOG_LEVEL_VERBOSE, "TLS session established, checking trust..."); /* Send/Receive "CFE_v%d" version string, agree on version, receive identity (username) of peer. */ char username[sizeof(conn->username)] = ""; bool b = ServerIdentificationDialog(conn->conn_info, username, sizeof(username)); if (b != true) { return -1; } /* We *now* (maybe a bit late) verify the key that the client sent us in * the TLS handshake, since we need the username to do so. TODO in the * future store keys irrelevant of username, so that we can match them * before IDENTIFY. */ ret = TLSVerifyPeer(conn->conn_info, conn->ipaddr, username); if (ret == -1) /* error */ { return -1; } if (ret == 1) /* trusted key */ { Log(LOG_LEVEL_VERBOSE, "%s: Client is TRUSTED, public key MATCHES stored one.", KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); } if (ret == 0) /* untrusted key */ { if ((SV.trustkeylist != NULL) && (IsMatchItemIn(SV.trustkeylist, conn->ipaddr))) { Log(LOG_LEVEL_VERBOSE, "Peer was found in \"trustkeysfrom\" list"); Log(LOG_LEVEL_NOTICE, "Trusting new key: %s", KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); SavePublicKey(username, KeyPrintableHash(conn->conn_info->remote_key), KeyRSA(ConnectionInfoKey(conn->conn_info))); } else { Log(LOG_LEVEL_NOTICE, "TRUST FAILED, peer presented an untrusted key, dropping connection!"); Log(LOG_LEVEL_VERBOSE, "Add peer to \"trustkeysfrom\" if you really want to start trusting this new key."); return -1; } } /* All checks succeeded, set conn->uid (conn->sid for Windows) * according to the received USERNAME identity. */ SetConnIdentity(conn, username); /* No CAUTH, SAUTH in non-classic protocol. */ conn->user_data_set = 1; conn->rsa_auth = 1; LastSaw1(conn->ipaddr, KeyPrintableHash(ConnectionInfoKey(conn->conn_info)), LAST_SEEN_ROLE_ACCEPT); ServerSendWelcome(conn); } return 1; } //******************************************************************* // COMMANDS //******************************************************************* typedef enum { PROTOCOL_COMMAND_EXEC = 0, PROTOCOL_COMMAND_GET, PROTOCOL_COMMAND_OPENDIR, PROTOCOL_COMMAND_SYNCH, PROTOCOL_COMMAND_MD5, PROTOCOL_COMMAND_VERSION, PROTOCOL_COMMAND_VAR, PROTOCOL_COMMAND_CONTEXT, PROTOCOL_COMMAND_QUERY, PROTOCOL_COMMAND_CALL_ME_BACK, PROTOCOL_COMMAND_BAD } ProtocolCommandNew; static const char *const PROTOCOL_NEW[PROTOCOL_COMMAND_BAD + 1] = { "EXEC", "GET", "OPENDIR", "SYNCH", "MD5", "VERSION", "VAR", "CONTEXT", "QUERY", "SCALLBACK", NULL }; static ProtocolCommandNew GetCommandNew(char *str) { int i; for (i = 0; PROTOCOL_NEW[i] != NULL; i++) { int cmdlen = strlen(PROTOCOL_NEW[i]); if ((strncmp(str, PROTOCOL_NEW[i], cmdlen) == 0) && (str[cmdlen] == ' ' || str[cmdlen] == '\0')) { return i; } } assert (i == PROTOCOL_COMMAND_BAD); return i; } bool BusyWithNewProtocol(EvalContext *ctx, ServerConnectionState *conn) { /* The CF_BUFEXT extra space is there to ensure we're not reading out of * bounds in commands that carry extra binary arguments, like MD5. */ char recvbuffer[CF_BUFSIZE + CF_BUFEXT] = { 0 }; char sendbuffer[CF_BUFSIZE] = { 0 }; char filename[CF_BUFSIZE + 1]; /* +1 for appending slash sometimes */ int received; ServerFileGetState get_args = { 0 }; /* We already encrypt because of the TLS layer, no need to encrypt more. */ const int encrypted = 0; /* Legacy stuff only for old protocol. */ assert(conn->rsa_auth == 1); assert(conn->user_data_set == 1); /* Receive up to CF_BUFSIZE - 1 bytes. */ received = ReceiveTransaction(conn->conn_info, recvbuffer, NULL); if (received == -1 || received == 0) { return false; } if (strlen(recvbuffer) == 0) { Log(LOG_LEVEL_WARNING, "Got NULL transmission, skipping!"); return true; } /* Don't process request if we're signalled to exit. */ if (IsPendingTermination()) { Log(LOG_LEVEL_VERBOSE, "Server must exit, closing connection"); return false; } /* TODO break recvbuffer here: command, param1, param2 etc. */ switch (GetCommandNew(recvbuffer)) { case PROTOCOL_COMMAND_EXEC: { /* TODO check it is always file, never directory, no end with '/' */ char args[256]; int ret = sscanf(recvbuffer, "EXEC %255[^\n]", args); if (ret != 1) /* No arguments, use default args. */ { args[0] = '\0'; } if (!AllowedUser(conn->username)) { Log(LOG_LEVEL_INFO, "EXEC denied due to not allowed user: %s", conn->username); RefuseAccess(conn, recvbuffer); return true; } char arg0[PATH_MAX]; size_t zret = CommandArg0_bound(arg0, CFRUNCOMMAND, sizeof(arg0)); if (zret == (size_t) -1) { goto protocol_error; } zret = PreprocessRequestPath(arg0, sizeof(arg0)); if (zret == (size_t) -1) { goto protocol_error; } /* TODO EXEC should not just use paths_acl access control, but * specific "path_exec" ACL. Then different command execution could be * allowed per host, and the host could even set argv[0] in his EXEC * request, rather than only the arguments. */ if (acl_CheckPath(paths_acl, arg0, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "EXEC denied due to ACL for file: %s", arg0); RefuseAccess(conn, recvbuffer); return true; } if (!MatchClasses(ctx, conn)) { Log(LOG_LEVEL_INFO, "EXEC denied due to failed class match"); Terminate(conn->conn_info); return true; } DoExec(ctx, conn, args); Terminate(conn->conn_info); return true; } case PROTOCOL_COMMAND_VERSION: snprintf(sendbuffer, sizeof(sendbuffer), "OK: %s", Version()); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return true; case PROTOCOL_COMMAND_GET: { int ret = sscanf(recvbuffer, "GET %d %[^\n]", &(get_args.buf_size), filename); if (ret != 2 || get_args.buf_size <= 0 || get_args.buf_size > CF_BUFSIZE) { goto protocol_error; } Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Received:", "GET", filename); /* TODO batch all the following in one function since it's very * similar in all of GET, OPENDIR and STAT. */ size_t zret = ShortcutsExpand(filename, sizeof(filename), SV.path_shortcuts, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); if (zret == (size_t) -1) { goto protocol_error; } zret = PreprocessRequestPath(filename, sizeof(filename)); if (zret == (size_t) -1) { goto protocol_error; } PathRemoveTrailingSlash(filename, strlen(filename)); Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Translated to:", "GET", filename); if (acl_CheckPath(paths_acl, filename, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to GET: %s", filename); RefuseAccess(conn, recvbuffer); return true; } memset(sendbuffer, 0, sizeof(sendbuffer)); if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } /* TODO eliminate! */ get_args.conn = conn; get_args.encrypt = false; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfGetFile(&get_args); return true; } case PROTOCOL_COMMAND_OPENDIR: { memset(filename, 0, sizeof(filename)); int ret = sscanf(recvbuffer, "OPENDIR %[^\n]", filename); if (ret != 1) { goto protocol_error; } Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Received:", "OPENDIR", filename); /* sizeof()-1 because we need one extra byte for appending '/' afterwards. */ size_t zret = ShortcutsExpand(filename, sizeof(filename) - 1, SV.path_shortcuts, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); if (zret == (size_t) -1) { goto protocol_error; } zret = PreprocessRequestPath(filename, sizeof(filename) - 1); if (zret == (size_t) -1) { goto protocol_error; } /* OPENDIR *must* be directory. */ PathAppendTrailingSlash(filename, strlen(filename)); Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Translated to:", "OPENDIR", filename); if (acl_CheckPath(paths_acl, filename, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to OPENDIR: %s", filename); RefuseAccess(conn, recvbuffer); return true; } CfOpenDirectory(conn, sendbuffer, filename); return true; } case PROTOCOL_COMMAND_SYNCH: { long time_no_see = 0; memset(filename, 0, sizeof(filename)); int ret = sscanf(recvbuffer, "SYNCH %ld STAT %[^\n]", &time_no_see, filename); if (ret != 2 || time_no_see == 0 || filename[0] == '\0') { goto protocol_error; } time_t tloc = time(NULL); if (tloc == -1) { /* Should never happen. */ Log(LOG_LEVEL_ERR, "Couldn't read system clock. (time: %s)", GetErrorStr()); SendTransaction(conn->conn_info, "BAD: clocks out of synch", 0, CF_DONE); return true; } time_t trem = (time_t) time_no_see; int drift = (int) (tloc - trem); Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Received:", "STAT", filename); /* sizeof()-1 because we need one extra byte for appending '/' afterwards. */ size_t zret = ShortcutsExpand(filename, sizeof(filename) - 1, SV.path_shortcuts, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); if (zret == (size_t) -1) { goto protocol_error; } zret = PreprocessRequestPath(filename, sizeof(filename) - 1); if (zret == (size_t) -1) { RefuseAccess(conn, recvbuffer); return true; } if (IsDirReal(filename) == 1) { PathAppendTrailingSlash(filename, strlen(filename)); } else { PathRemoveTrailingSlash(filename, strlen(filename)); } Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Translated to:", "STAT", filename); if (acl_CheckPath(paths_acl, filename, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to STAT: %s", filename); RefuseAccess(conn, recvbuffer); return true; } if (DENYBADCLOCKS && (drift * drift > CLOCK_DRIFT * CLOCK_DRIFT)) { snprintf(sendbuffer, sizeof(sendbuffer), "BAD: Clocks are too far unsynchronized %ld/%ld", (long) tloc, (long) trem); Log(LOG_LEVEL_INFO, "denybadclocks %s", sendbuffer); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return true; } else { Log(LOG_LEVEL_DEBUG, "Clocks were off by %ld", (long) tloc - (long) trem); StatFile(conn, sendbuffer, filename); } return true; } case PROTOCOL_COMMAND_MD5: { int ret = sscanf(recvbuffer, "MD5 %[^\n]", filename); if (ret != 1) { goto protocol_error; } Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Received:", "MD5", filename); /* TODO batch all the following in one function since it's very * similar in all of GET, OPENDIR and STAT. */ size_t zret = ShortcutsExpand(filename, sizeof(filename), SV.path_shortcuts, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))); if (zret == (size_t) -1) { goto protocol_error; } zret = PreprocessRequestPath(filename, sizeof(filename)); if (zret == (size_t) -1) { goto protocol_error; } PathRemoveTrailingSlash(filename, strlen(filename)); Log(LOG_LEVEL_VERBOSE, "%14s %7s %s", "Translated to:", "MD5", filename); if (acl_CheckPath(paths_acl, filename, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to file: %s", filename); RefuseAccess(conn, recvbuffer); return true; } assert(CF_DEFAULT_DIGEST_LEN <= EVP_MAX_MD_SIZE); unsigned char digest[EVP_MAX_MD_SIZE + 1]; assert(CF_BUFSIZE + CF_SMALL_OFFSET + CF_DEFAULT_DIGEST_LEN <= sizeof(recvbuffer)); memcpy(digest, recvbuffer + strlen(recvbuffer) + CF_SMALL_OFFSET, CF_DEFAULT_DIGEST_LEN); CompareLocalHash(filename, digest, sendbuffer); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); return true; } case PROTOCOL_COMMAND_VAR: { char var[256]; int ret = sscanf(recvbuffer, "VAR %255[^\n]", var); if (ret != 1) { goto protocol_error; } /* TODO if this is literals_acl, then when should I check vars_acl? */ if (acl_CheckExact(literals_acl, var, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to variable: %s", var); RefuseAccess(conn, recvbuffer); return true; } GetServerLiteral(ctx, conn, sendbuffer, recvbuffer, encrypted); return true; } case PROTOCOL_COMMAND_CONTEXT: { char client_regex[256]; int ret = sscanf(recvbuffer, "CONTEXT %255[^\n]", client_regex); if (ret != 1) { goto protocol_error; } /* WARNING: this comes from legacy code and must be killed if we care * about performance. We should not accept regular expressions from * the client, but this will break backwards compatibility. * * I replicated the code in raw form here to emphasize complexity, * it's the only *slow* command currently in the protocol. */ Item *persistent_classes = ListPersistentClasses(); Item *matched_classes = NULL; /* For all persistent classes */ for (Item *ip = persistent_classes; ip != NULL; ip = ip->next) { const char *class_name = ip->name; /* Does this class match the regex the client sent? */ if (StringMatchFull(client_regex, class_name)) { /* For all ACLs */ for (size_t i = 0; i < classes_acl->len; i++) { struct resource_acl *racl = &classes_acl->acls[i]; /* Does this ACL apply to this host? */ if (access_CheckResource(racl, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == true) { const char *allowed_classes_regex = classes_acl->resource_names->list[i]->str; /* Does this ACL admits access for this class to the * connected host? */ if (StringMatchFull(allowed_classes_regex, class_name)) { PrependItem(&matched_classes, class_name, NULL); } } } } } if (matched_classes == NULL) { Log(LOG_LEVEL_INFO, "No allowed classes for remoteclassesmatching: %s", client_regex); RefuseAccess(conn, recvbuffer); return true; } ReplyServerContext(conn, encrypted, matched_classes); return true; } case PROTOCOL_COMMAND_QUERY: { char query[256], name[128]; int ret1 = sscanf(recvbuffer, "QUERY %255[^\n]", query); int ret2 = sscanf(recvbuffer, "QUERY %127s", name); if (ret1 != 1 || ret2 != 1) { goto protocol_error; } if (acl_CheckExact(query_acl, name, conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to query: %s", query); RefuseAccess(conn, recvbuffer); return true; } if (GetServerQuery(conn, recvbuffer, encrypted)) { return true; } break; } case PROTOCOL_COMMAND_CALL_ME_BACK: if (acl_CheckExact(query_acl, "collect_calls", conn->ipaddr, conn->revdns, KeyPrintableHash(ConnectionInfoKey(conn->conn_info))) == false) { Log(LOG_LEVEL_INFO, "access denied to Call-Collect, check the ACL for class: collect_calls"); return false; } ReceiveCollectCall(conn); /* On success that returned true; otherwise, it did all * relevant Log()ging. Either way, it closed the connection, * so we're no longer busy with it: */ return false; case PROTOCOL_COMMAND_BAD: Log(LOG_LEVEL_WARNING, "Unexpected protocol command: %s", recvbuffer); } /* We should only reach this point if something went really bad, and * close connection. In all other cases (like access denied) connection * shouldn't be closed. * TODO So we need this function to return more than true/false, because * now we return true even when access is denied! E.g. return -1 for * error, 0 on success, 1 on access denied. It can be an option if * connection will close on denial. */ protocol_error: strcpy(sendbuffer, "BAD: Request denied"); SendTransaction(conn->conn_info, sendbuffer, 0, CF_DONE); Log(LOG_LEVEL_INFO, "Closing connection due to request: %s", recvbuffer); return false; } cfengine-3.6.2/cf-serverd/server.h0000664000175100017510000001115312400110676016533 0ustar00a10038a1003800000000000000/* Copyright (C) CFEngine AS This file is part of CFEngine 3 - written and maintained by CFEngine AS. 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; version 3. 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 To the extent this program is licensed as part of the Enterprise versions of CFEngine, the applicable Commercial Open Source License (COSL) may apply to this file if you as a licensee so wish it. See included file COSL.txt. */ #ifndef CFENGINE_SERVER_H #define CFENGINE_SERVER_H #include #include /* AgentConnection */ #include //******************************************************************* // TYPES //******************************************************************* typedef struct Auth_ Auth; /* Access rights for a path, literal, context (classpattern), variable */ /* LEGACY CODE the new struct is paths_acl etc. */ struct Auth_ { char *path; int literal; int classpattern; int variable; Item *accesslist; /* which hosts -- IP or hostnames */ Item *maproot; /* which hosts should have root read access */ int encrypt; /* which files HAVE to be transmitted securely */ Auth *next; }; typedef struct { Item *connectionlist; /* List of currently open connections */ /* body server control options */ Item *nonattackerlist; /* "allowconnects" */ Item *attackerlist; /* "denyconnects" */ Item *allowuserlist; /* "allowusers" */ Item *multiconnlist; /* "allowallconnects" */ Item *trustkeylist; /* "trustkeysfrom" */ Item *allowlegacyconnects; char *allowciphers; /* ACL for resource_type "path". */ Auth *admit; Auth *admittail; Auth *deny; Auth *denytail; /* ACL for resource_types "literal", "query", "context", "variable". */ Auth *varadmit; Auth *varadmittail; Auth *vardeny; Auth *vardenytail; Auth *roles; Auth *rolestail; int logconns; /* bundle server access_rules: shortcut for ACL entries, which expands to * the ACL entry when seen in client requests. */ StringMap *path_shortcuts; } ServerAccess; /* TODO rename to IncomingConnection */ struct ServerConnectionState_ { ConnectionInfo *conn_info; /* TODO sockaddr_storage, even though we can keep the text as cache. */ char ipaddr[CF_MAX_IP_LEN]; char revdns[MAXHOSTNAMELEN]; /* only populated in new protocol */ #ifdef __MINGW32__ /* We avoid dynamically allocated buffers due to potential memory leaks, * but this is still too big at 2K! */ char sid[CF_MAXSIDSIZE]; #endif uid_t uid; /* TODO move username, hostname etc to a new struct identity. */ char username[CF_MAXVARSIZE]; /* TODO the following are useless with the new protocol */ char hostname[CF_MAXVARSIZE]; /* hostname is copied from client-supplied CAUTH command */ int user_data_set; int rsa_auth; int maproot; unsigned char *session_key; char encryption_type; /* TODO pass it through function arguments, EvalContext has nothing to do * with connection-specific data. */ EvalContext *ctx; }; typedef struct { ServerConnectionState *conn; int encrypt; int buf_size; char *replybuff; char *replyfile; } ServerFileGetState; /* Used in cf-serverd-functions.c. */ void ServerEntryPoint(EvalContext *ctx, const char *ipaddr, ConnectionInfo *info); AgentConnection *ExtractCallBackChannel(ServerConnectionState *conn); //******************************************************************* // STATE //******************************************************************* #define CLOCK_DRIFT 3600 extern int ACTIVE_THREADS; extern int CFD_MAXPROCESSES; extern bool DENYBADCLOCKS; extern int MAXTRIES; extern bool LOGENCRYPT; extern int COLLECT_INTERVAL; extern bool SERVER_LISTEN; extern ServerAccess SV; extern char CFRUNCOMMAND[CF_MAXVARSIZE]; extern bool NEED_REVERSE_LOOKUP; #endif cfengine-3.6.2/configure0000775000175100017510000237623712412324465014754 0ustar00a10038a1003800000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="libpromises/generic_agent.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_config_libobj_dir=libcompat ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS post_macros LCOV_GENHTML LCOV HOSTNAME piddir logdir inputdir masterdir workdir XNU_FALSE XNU_TRUE NETBSD_FALSE NETBSD_TRUE FREEBSD_FALSE FREEBSD_TRUE HPUX_FALSE HPUX_TRUE AIX_FALSE AIX_TRUE CYGWIN_FALSE CYGWIN_TRUE NT_FALSE NT_TRUE SOLARIS_FALSE SOLARIS_TRUE MACOSX_FALSE MACOSX_TRUE LINUX_FALSE LINUX_TRUE CORE_LIBS CORE_LDFLAGS CORE_CFLAGS CORE_CPPFLAGS hw_cv_func_rename_proper hw_cv_func_stat_proper hw_cv_func_mkdir_proper hw_cv_func_ctime_proper HAVE_USERS_PROMISE_DEPS_FALSE HAVE_USERS_PROMISE_DEPS_TRUE PAM_LIBS PAM_LDFLAGS PAM_CFLAGS PAM_CPPFLAGS PAM_PATH GETLOADAVG_LIBS KMEM_GROUP NEED_SETGID LIBOBJS HAVE_AVAHI_COMMON_FALSE HAVE_AVAHI_COMMON_TRUE HAVE_AVAHI_CLIENT_FALSE HAVE_AVAHI_CLIENT_TRUE HAVE_LIBXML2_FALSE HAVE_LIBXML2_TRUE LIBXML2_LIBS LIBXML2_LDFLAGS LIBXML2_CFLAGS LIBXML2_CPPFLAGS LIBXML2_PATH LIBACL_LIBS LIBACL_LDFLAGS LIBACL_CFLAGS LIBACL_CPPFLAGS LIBACL_PATH LIBVIRT_LIBS LIBVIRT_LDFLAGS LIBVIRT_CFLAGS LIBVIRT_CPPFLAGS LIBVIRT_PATH PCRE_LIBS PCRE_LDFLAGS PCRE_CFLAGS PCRE_CPPFLAGS PCRE_PATH OPENSSL_LIBS OPENSSL_LDFLAGS OPENSSL_CFLAGS OPENSSL_CPPFLAGS OPENSSL_PATH LMDB_LIBS LMDB_LDFLAGS LMDB_CFLAGS LMDB_CPPFLAGS LMDB_PATH TOKYOCABINET_LIBS TOKYOCABINET_LDFLAGS TOKYOCABINET_CFLAGS TOKYOCABINET_CPPFLAGS TOKYOCABINET_PATH QDBM_LIBS QDBM_LDFLAGS QDBM_CFLAGS QDBM_CPPFLAGS QDBM_PATH MYSQL_LIBS MYSQL_LDFLAGS MYSQL_CFLAGS MYSQL_CPPFLAGS MYSQL_PATH POSTGRESQL_LIBS POSTGRESQL_LDFLAGS POSTGRESQL_CFLAGS POSTGRESQL_CPPFLAGS POSTGRESQL_PATH NDEBUG_FALSE NDEBUG_TRUE projlibdir enable_builtin_extensions BUILTIN_EXTENSIONS_FALSE BUILTIN_EXTENSIONS_TRUE PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC acx_pthread_config CROSS_COMPILING_FALSE CROSS_COMPILING_TRUE GETCONF YFLAGS YACC LEXLIB LEX_OUTPUT_ROOT LEX OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED LIBTOOL CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM MAKEINFO target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking enable_static enable_shared with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock with_pthreads enable_builtin_extensions enable_fhs enable_debug with_sql with_postgresql with_mysql with_qdbm with_tokyocabinet with_lmdb with_openssl with_pcre with_libvirt with_libacl with_libxml2 enable_largefile with_pam enable_selinux with_workdir with_masterdir with_inputdir with_logdir with_piddir with_shell enable_coverage ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP YACC YFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --disable-maintainer-mode disable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) Build binaries with builtin extensions --enable-fhs Enable FHS compliance. Defaults to custom CFEngine files layout --enable-debug Enable debugging --disable-largefile omit support for large files --enable-selinux Deprecated. SELinux support is always enabled --enable-coverage Enable code coverage Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-pthreads[=PATH] Specify path to pthreads, if not the part of operating system --with-sql[=PATH] Enable SQL database connectors (deprecated, use --with[[out]]-postgresql and --with[[out]]-mysql instead) --with-postgresql[=PATH] Enable PostgreSQL connector --with-mysql[=PATH] Enable MySQL connector --with-qdbm[=PATH] use QDBM to store runtime data --with-tokyocabinet[=PATH] use Tokyo Cabinet to store runtime data --with-lmdb[=PATH] use Lightning MDB to store runtime data --with-openssl[=PATH] Specify OpenSSL path --with-pcre[=PATH] Specify PCRE path --with-libvirt[=PATH] support virtual machine management --with-libacl[=PATH] Specify libacl path --with-libxml2[=PATH] Specify libxml2 path --with-pam Compile with PAM support --with-workdir=WORKDIR default internal for trusted cache --with-masterdir=MASTERDIR default internal for masterfiles directory --with-inputdir=INPUTDIR default internal for inputs directory --with-logdir=LOGDIR default internal for log directory --with-piddir=LOGDIR default internal for pid directory --with-shell=PATH Specify path to POSIX-compatible shell (if not /bin/sh) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor YACC The `Yet Another Compiler Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- # Extract the first word of "makeinfo", so it can be a program name with args. set dummy makeinfo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MAKEINFO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MAKEINFO"; then ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MAKEINFO="makeinfo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MAKEINFO=$ac_cv_prog_MAKEINFO if test -n "$MAKEINFO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 $as_echo "$MAKEINFO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi am__api_version='1.14' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=cfengine VERSION=3.6.2 cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar plaintar pax cpio none' # The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 $as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } if test $am_uid -le $am_max_uid; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } _am_tools=none fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 $as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } if test $am_gid -le $am_max_gid; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } _am_tools=none fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 $as_echo_n "checking how to create a ustar tar archive... " >&6; } # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_ustar-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x ustar -w "$$tardir"' am__tar_='pax -L -x ustar -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H ustar -L' am__tar_='find "$tardir" -print | cpio -o -H ustar -L' am__untar='cpio -i -H ustar -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_ustar}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar &5 ($am__untar &5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 (cat conftest.dir/file) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if ${am_cv_prog_tar_ustar+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_prog_tar_ustar=$_am_tool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 $as_echo "$am_cv_prog_tar_ustar" >&6; } # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE $as_echo "#define BUILD_YEAR 2014" >>confdefs.h cat >>confdefs.h <<_ACEOF #define ABS_TOP_SRCDIR "`cd -- "$srcdir"; pwd`" _ACEOF # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' ac_config_headers="$ac_config_headers libutils/config.h" ENV_CFLAGS="$CFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HP-UX aC" >&5 $as_echo_n "checking for HP-UX aC... " >&6; } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined __HP_cc #This is HP-UX ANSI C #endif _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$CFLAGS -Agcc" CPPFLAGS="$CPPFLAGS -Agcc" HP_UX_AC=yes fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC specific compile flags" >&5 $as_echo_n "checking for GCC specific compile flags... " >&6; } if test x"$GCC" = "xyes" && test x"$HP_UX_AC" != x"yes"; then CFLAGS="$CFLAGS -g -Wall" CPPFLAGS="$CPPFLAGS -std=gnu99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wno-pointer-sign" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wno-pointer-sign" >&5 $as_echo_n "checking for -Wno-pointer-sign... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() {} _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror=implicit-function-declaration" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Werror=implicit-function-declaration" >&5 $as_echo_n "checking for -Werror=implicit-function-declaration... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() {} _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wunused-parameter" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wunused-parameter" >&5 $as_echo_n "checking for -Wunused-parameter... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main() {} _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wno-duplicate-decl-specifier" >&5 $as_echo_n "checking for -Wno-duplicate-decl-specifier... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __clang__ # error Not a clang #endif int main() {} _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS -Wno-duplicate-decl-specifier" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Use either new LT_INIT or old AC_DISABLE_STATIC/AC_PROG_LIBTOOL macros case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LEX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LEX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 $as_echo "$LEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test "x$LEX" != "x:"; then cat >conftest.l <<_ACEOF %% a { ECHO; } b { REJECT; } c { yymore (); } d { yyless (1); } e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ yyless ((input () != 0)); } f { unput (yytext[0]); } . { BEGIN INITIAL; } %% #ifdef YYTEXT_POINTER extern char *yytext; #endif int main (void) { return ! yylex () + ! yywrap (); } _ACEOF { { ac_try="$LEX conftest.l" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$LEX conftest.l") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 $as_echo_n "checking lex output file root... " >&6; } if ${ac_cv_prog_lex_root+:} false; then : $as_echo_n "(cached) " >&6 else if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 $as_echo "$ac_cv_prog_lex_root" >&6; } LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root if test -z "${LEXLIB+set}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 $as_echo_n "checking lex library... " >&6; } if ${ac_cv_lib_lex+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS=$LIBS ac_cv_lib_lex='none needed' for ac_lib in '' -lfl -ll; do LIBS="$ac_lib $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lex=$ac_lib fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext test "$ac_cv_lib_lex" != 'none needed' && break done LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 $as_echo "$ac_cv_lib_lex" >&6; } test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 $as_echo_n "checking whether yytext is a pointer... " >&6; } if ${ac_cv_prog_lex_yytext_pointer+:} false; then : $as_echo_n "(cached) " >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no ac_save_LIBS=$LIBS LIBS="$LEXLIB $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_prog_lex_yytext_pointer=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 $as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } if test $ac_cv_prog_lex_yytext_pointer = yes; then $as_echo "#define YYTEXT_POINTER 1" >>confdefs.h fi rm -f conftest.l $LEX_OUTPUT_ROOT.c fi if test "$LEX" = :; then LEX=${am_missing_run}flex fi for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_YACC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_YACC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" # Extract the first word of "getconf", so it can be a program name with args. set dummy getconf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GETCONF+:} false; then : $as_echo_n "(cached) " >&6 else case $GETCONF in [\\/]* | ?:[\\/]*) ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GETCONF" && ac_cv_path_GETCONF="false" ;; esac fi GETCONF=$ac_cv_path_GETCONF if test -n "$GETCONF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GETCONF" >&5 $as_echo "$GETCONF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$cross_compiling" = "xyes"; then CROSS_COMPILING_TRUE= CROSS_COMPILING_FALSE='#' else CROSS_COMPILING_TRUE='#' CROSS_COMPILING_FALSE= fi # Check whether --with-pthreads was given. if test "${with_pthreads+set}" = set; then : withval=$with_pthreads; fi if test "x$with_pthreads" != x && test "x$with_pthreads" != "xyes" && test "x$with_pthreads" != "xno"; then LIBS="$LIBS -L$with_pthreads/lib" CPPFLAGS="-I$with_pthreads/include $CPPFLAGS" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt -mthreads pthread --thread-safe pthread-config pthreadGC2" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_acx_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$acx_pthread_config"; then ac_cv_prog_acx_pthread_config="$acx_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_acx_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_acx_pthread_config" && ac_cv_prog_acx_pthread_config="no" fi fi acx_pthread_config=$ac_cv_prog_acx_pthread_config if test -n "$acx_pthread_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_config" >&5 $as_echo "$acx_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=$attr; return attr; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : attr_name=$attr; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 $as_echo "$attr_name" >&6; } if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then cat >>confdefs.h <<_ACEOF #define PTHREAD_CREATE_JOINABLE $attr_name _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then for ac_prog in xlc_r cc_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="${CC}" else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h : else acx_pthread_ok=no as_fn_error $? "pthread-compatible library is required to build CFEngine" "$LINENO" 5 fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$PTHREAD_CC" CFLAGS="$PTHREAD_CFLAGS $CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" # Check whether --enable-builtin-extensions was given. if test "${enable_builtin_extensions+set}" = set; then : enableval=$enable_builtin_extensions; else case ${target_os} in #( mingw*) : enable_builtin_extensions=yes ;; #( *) : enable_builtin_extensions=no ;; esac fi if test "x$enable_builtin_extensions" = "xyes"; then BUILTIN_EXTENSIONS_TRUE= BUILTIN_EXTENSIONS_FALSE='#' else BUILTIN_EXTENSIONS_TRUE='#' BUILTIN_EXTENSIONS_FALSE= fi if test "x$enable_builtin_extensions" = "xyes"; then : $as_echo "#define BUILTIN_EXTENSIONS 1" >>confdefs.h fi # Check whether --enable-fhs was given. if test "${enable_fhs+set}" = set; then : enableval=$enable_fhs; fi # # pkglibdir/pkgdatadir are not overridable, so use our own invention instead. # if test x"$enable_fhs" = xyes; then : projlibdir='${libdir}/cfengine' datadir='${exec_prefix}/share/cfengine' WORKDIR='${localstatedir}/lib/cfengine' MASTERDIR='default' INPUTDIR='default' LOGDIR='${localstatedir}/lib/cfengine' PIDDIR='${localstatedir}/lib/cfengine' else if test x"$prefix" = xNONE || test x"$prefix" = x/var/cfengine; then prefix=/var/cfengine case "$target_os" in mingw*) WORKDIR=$(cmd /c "echo %PROGRAMFILES%\\Cfengine" | sed 's/\\/\\\\/g') MASTERDIR=default INPUTDIR=default LOGDIR=$(cmd /c "echo %PROGRAMFILES%\\Cfengine" | sed 's/\\/\\\\/g') PIDDIR=$(cmd /c "echo %PROGRAMFILES%\\Cfengine" | sed 's/\\/\\\\/g') ;; *) WORKDIR=/var/cfengine MASTERDIR=default INPUTDIR=default LOGDIR=/var/cfengine PIDDIR=/var/cfengine ;; esac else WORKDIR="${localstatedir}/cfengine" MASTERDIR="default" INPUTDIR="default" LOGDIR="${localstatedir}/cfengine" PIDDIR="${localstatedir}/cfengine" fi sbindir='${exec_prefix}/bin' # /var/cfengine/bin despite being sbin_? projlibdir='${exec_prefix}/lib' mandir='${exec_prefix}/share/man' fi case ${target_os} in #( mingw*) : # Disable printf format warnings, because our wrapper supports more # flags than vanilla Windows version, so they are false positives. CFLAGS="$CFLAGS -Wno-format" ;; #( *) : ;; esac # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; debug=$enableval else debug=no fi if test x"$debug" = x"no"; then NDEBUG_TRUE= NDEBUG_FALSE='#' else NDEBUG_TRUE='#' NDEBUG_FALSE= fi if test x"$debug" = x"yes" then CFLAGS="$CFLAGS -g3 -O0 $ENV_CFLAGS" else CFLAGS="$CFLAGS -O2 -DNDEBUG $ENV_CFLAGS" fi # TODO remove # Check whether --with-sql was given. if test "${with_sql+set}" = set; then : withval=$with_sql; with_postgresql=$with_sql; with_mysql=$with_sql fi # Check whether --with-postgresql was given. if test "${with_postgresql+set}" = set; then : withval=$with_postgresql; else with_postgresql=check fi if test "x$with_postgresql" != "xno" then if test "x$with_postgresql" != xyes && test "x$with_postgresql" != xcheck then PG_CONFIG=$with_postgresql/bin/pg_config else PG_CONFIG=pg_config fi # pg_config is only for native builds if test "x$cross_compiling" = "xno" then if test x`which $PG_CONFIG` != x then pg_include_dir=`$PG_CONFIG --includedir` if test -n "$pg_include_dir" then POSTGRESQL_CPPFLAGS="-I$pg_include_dir" fi fi fi # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_postgresql" != xyes && test "x$with_postgresql" != xcheck && test "x$with_postgresql" != x; then test -z "$POSTGRESQL_PATH" && POSTGRESQL_PATH="$with_postgresql" if test "x$with_postgresql" != x/usr && test "x$with_postgresql" != x/; then test -z "$POSTGRESQL_CFLAGS" && POSTGRESQL_CFLAGS="" test -z "$POSTGRESQL_CPPFLAGS" && POSTGRESQL_CPPFLAGS="-I$with_postgresql/include" test -z "$POSTGRESQL_LDFLAGS" && POSTGRESQL_LDFLAGS="-L$with_postgresql/lib" fi else POSTGRESQL_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $POSTGRESQL_CFLAGS" CPPFLAGS="$CPPFLAGS $POSTGRESQL_CPPFLAGS" LDFLAGS="$LDFLAGS $POSTGRESQL_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQconnectdb in -lpq" >&5 $as_echo_n "checking for PQconnectdb in -lpq... " >&6; } if ${ac_cv_lib_pq_PQconnectdb+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpq $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char PQconnectdb (); int main () { return PQconnectdb (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pq_PQconnectdb=yes else ac_cv_lib_pq_PQconnectdb=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQconnectdb" >&5 $as_echo "$ac_cv_lib_pq_PQconnectdb" >&6; } if test "x$ac_cv_lib_pq_PQconnectdb" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPQ 1 _ACEOF LIBS="-lpq $LIBS" else if test "x$with_postgresql" != xcheck; then as_fn_error $? "Cannot find PostgreSQL client library" "$LINENO" 5; fi fi for ac_header in libpq-fe.h do : ac_fn_c_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default" if test "x$ac_cv_header_libpq_fe_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPQ_FE_H 1 _ACEOF else if test "x$with_postgresql" != xcheck; then as_fn_error $? "Cannot find PostgreSQL client library" "$LINENO" 5; fi fi done # # Pick up any libraries added by tests # test -z "$POSTGRESQL_LIBS" && POSTGRESQL_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_postgresql" != xyes && test "x$with_postgresql" != xcheck; then if test "x$with_postgresql" != x/usr && test "x$with_postgresql" != x/; then POSTGRESQL_LDFLAGS="$POSTGRESQL_LDFLAGS -R$with_postgresql/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # Check whether --with-mysql was given. if test "${with_mysql+set}" = set; then : withval=$with_mysql; else with_mysql=check fi if test "x$with_mysql" != "xno" then if test "x$with_mysql" != xyes && test "x$with_mysql" != xcheck then MYSQL_CONFIG=$with_mysql/bin/mysql_config else MYSQL_CONFIG=mysql_config fi # mysql_config is only for native builds if test "x$cross_compiling" = "xno" then if test x`which $MYSQL_CONFIG` != x then mysql_include_dir=`$MYSQL_CONFIG --include` if test -n "$mysql_include_dir" then MYSQL_CPPFLAGS="$mysql_include_dir" fi fi fi # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_mysql" != xyes && test "x$with_mysql" != xcheck && test "x$with_mysql" != x; then test -z "$MYSQL_PATH" && MYSQL_PATH="$with_mysql" if test "x$with_mysql" != x/usr && test "x$with_mysql" != x/; then test -z "$MYSQL_CFLAGS" && MYSQL_CFLAGS="" test -z "$MYSQL_CPPFLAGS" && MYSQL_CPPFLAGS="-I$with_mysql/include" test -z "$MYSQL_LDFLAGS" && MYSQL_LDFLAGS="-L$with_mysql/lib" fi else MYSQL_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $MYSQL_CFLAGS" CPPFLAGS="$CPPFLAGS $MYSQL_CPPFLAGS" LDFLAGS="$LDFLAGS $MYSQL_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_real_connect in -lmysqlclient" >&5 $as_echo_n "checking for mysql_real_connect in -lmysqlclient... " >&6; } if ${ac_cv_lib_mysqlclient_mysql_real_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mysql_real_connect (); int main () { return mysql_real_connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mysqlclient_mysql_real_connect=yes else ac_cv_lib_mysqlclient_mysql_real_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_real_connect" >&5 $as_echo "$ac_cv_lib_mysqlclient_mysql_real_connect" >&6; } if test "x$ac_cv_lib_mysqlclient_mysql_real_connect" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBMYSQLCLIENT 1 _ACEOF LIBS="-lmysqlclient $LIBS" else if test "x$with_mysql" != xcheck; then as_fn_error $? "Cannot find MySQL client library" "$LINENO" 5; fi fi for ac_header in mysql.h do : ac_fn_c_check_header_mongrel "$LINENO" "mysql.h" "ac_cv_header_mysql_h" "$ac_includes_default" if test "x$ac_cv_header_mysql_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MYSQL_H 1 _ACEOF else if test "x$with_mysql" != xcheck; then as_fn_error $? "Cannot find MySQL clientlibrary" "$LINENO" 5; fi fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_CIPHER_CTX_init in -lmysqlclient" >&5 $as_echo_n "checking for EVP_CIPHER_CTX_init in -lmysqlclient... " >&6; } if ${ac_cv_lib_mysqlclient_EVP_CIPHER_CTX_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmysqlclient $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char EVP_CIPHER_CTX_init (); int main () { return EVP_CIPHER_CTX_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mysqlclient_EVP_CIPHER_CTX_init=yes else ac_cv_lib_mysqlclient_EVP_CIPHER_CTX_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_EVP_CIPHER_CTX_init" >&5 $as_echo "$ac_cv_lib_mysqlclient_EVP_CIPHER_CTX_init" >&6; } if test "x$ac_cv_lib_mysqlclient_EVP_CIPHER_CTX_init" = xyes; then : as_fn_error $? "MySQL client library exports symbols clashing \ with OpenSSL. Get the update from distribution provider, \ recompile MySQL library or disable MySQL connector. See \ http://bugs.mysql.com/bug.php?id=65055 for details." "$LINENO" 5 fi # # Pick up any libraries added by tests # test -z "$MYSQL_LIBS" && MYSQL_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_mysql" != xyes && test "x$with_mysql" != xcheck; then if test "x$with_mysql" != x/usr && test "x$with_mysql" != x/; then MYSQL_LDFLAGS="$MYSQL_LDFLAGS -R$with_mysql/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # Check whether --with-qdbm was given. if test "${with_qdbm+set}" = set; then : withval=$with_qdbm; fi if test -n "$with_qdbm" && test "x$with_qdbm" != "xno"; then : WITH_QDBM=1 else WITH_QDBM=0 fi if test $WITH_QDBM = 1; then # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_qdbm" != xyes && test "x$with_qdbm" != xcheck && test "x$with_qdbm" != x; then test -z "$QDBM_PATH" && QDBM_PATH="$with_qdbm" if test "x$with_qdbm" != x/usr && test "x$with_qdbm" != x/; then test -z "$QDBM_CFLAGS" && QDBM_CFLAGS="" test -z "$QDBM_CPPFLAGS" && QDBM_CPPFLAGS="-I$with_qdbm/include" test -z "$QDBM_LDFLAGS" && QDBM_LDFLAGS="-L$with_qdbm/lib" fi else QDBM_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $QDBM_CFLAGS" CPPFLAGS="$CPPFLAGS $QDBM_CPPFLAGS" LDFLAGS="$LDFLAGS $QDBM_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dpopen in -lqdbm" >&5 $as_echo_n "checking for dpopen in -lqdbm... " >&6; } if ${ac_cv_lib_qdbm_dpopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lqdbm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dpopen (); int main () { return dpopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_qdbm_dpopen=yes else ac_cv_lib_qdbm_dpopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_qdbm_dpopen" >&5 $as_echo "$ac_cv_lib_qdbm_dpopen" >&6; } if test "x$ac_cv_lib_qdbm_dpopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBQDBM 1 _ACEOF LIBS="-lqdbm $LIBS" else as_fn_error $? "Cannot find QDBM" "$LINENO" 5 fi for ac_header in depot.h do : ac_fn_c_check_header_mongrel "$LINENO" "depot.h" "ac_cv_header_depot_h" "$ac_includes_default" if test "x$ac_cv_header_depot_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DEPOT_H 1 _ACEOF else as_fn_error $? "Cannot find QDBM" "$LINENO" 5 fi done $as_echo "#define QDB 1" >>confdefs.h # # Pick up any libraries added by tests # test -z "$QDBM_LIBS" && QDBM_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_qdbm" != xyes && test "x$with_qdbm" != xcheck; then if test "x$with_qdbm" != x/usr && test "x$with_qdbm" != x/; then QDBM_LDFLAGS="$QDBM_LDFLAGS -R$with_qdbm/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # Check whether --with-tokyocabinet was given. if test "${with_tokyocabinet+set}" = set; then : withval=$with_tokyocabinet; fi if test $WITH_QDBM -eq 0 && test -n "$with_tokyocabinet" && test "x$with_tokyocabinet" != "xno"; then : WITH_TOKYO=1 else WITH_TOKYO=0 fi if test $WITH_TOKYO = 1; then # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_tokyocabinet" != xyes && test "x$with_tokyocabinet" != xcheck && test "x$with_tokyocabinet" != x; then test -z "$TOKYOCABINET_PATH" && TOKYOCABINET_PATH="$with_tokyocabinet" if test "x$with_tokyocabinet" != x/usr && test "x$with_tokyocabinet" != x/; then test -z "$TOKYOCABINET_CFLAGS" && TOKYOCABINET_CFLAGS="" test -z "$TOKYOCABINET_CPPFLAGS" && TOKYOCABINET_CPPFLAGS="-I$with_tokyocabinet/include" test -z "$TOKYOCABINET_LDFLAGS" && TOKYOCABINET_LDFLAGS="-L$with_tokyocabinet/lib" fi else TOKYOCABINET_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $TOKYOCABINET_CFLAGS" CPPFLAGS="$CPPFLAGS $TOKYOCABINET_CPPFLAGS" LDFLAGS="$LDFLAGS $TOKYOCABINET_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tchdbnew in -ltokyocabinet" >&5 $as_echo_n "checking for tchdbnew in -ltokyocabinet... " >&6; } if ${ac_cv_lib_tokyocabinet_tchdbnew+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ltokyocabinet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char tchdbnew (); int main () { return tchdbnew (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_tokyocabinet_tchdbnew=yes else ac_cv_lib_tokyocabinet_tchdbnew=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tokyocabinet_tchdbnew" >&5 $as_echo "$ac_cv_lib_tokyocabinet_tchdbnew" >&6; } if test "x$ac_cv_lib_tokyocabinet_tchdbnew" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBTOKYOCABINET 1 _ACEOF LIBS="-ltokyocabinet $LIBS" else as_fn_error $? "Cannot find Tokyo Cabinet" "$LINENO" 5 fi for ac_header in tcutil.h do : ac_fn_c_check_header_mongrel "$LINENO" "tcutil.h" "ac_cv_header_tcutil_h" "$ac_includes_default" if test "x$ac_cv_header_tcutil_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TCUTIL_H 1 _ACEOF else as_fn_error $? "Cannot find Tokyo Cabinet" "$LINENO" 5 fi done for ac_header in tchdb.h do : ac_fn_c_check_header_mongrel "$LINENO" "tchdb.h" "ac_cv_header_tchdb_h" "$ac_includes_default" if test "x$ac_cv_header_tchdb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TCHDB_H 1 _ACEOF else as_fn_error $? "Cannot find Tokyo Cabinet" "$LINENO" 5 fi done $as_echo "#define TCDB 1" >>confdefs.h # # Pick up any libraries added by tests # test -z "$TOKYOCABINET_LIBS" && TOKYOCABINET_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_tokyocabinet" != xyes && test "x$with_tokyocabinet" != xcheck; then if test "x$with_tokyocabinet" != x/usr && test "x$with_tokyocabinet" != x/; then TOKYOCABINET_LDFLAGS="$TOKYOCABINET_LDFLAGS -R$with_tokyocabinet/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # Check whether --with-lmdb was given. if test "${with_lmdb+set}" = set; then : withval=$with_lmdb; fi if test $WITH_TOKYO -eq 0 && test $WITH_QDBM -eq 0 && (! test -n "$with_lmdb" || test "x$with_lmdb" != "xno"); then : WITH_LMDB=1 else WITH_LMDB=0 fi if test $WITH_LMDB = 1; then # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_lmdb" != xyes && test "x$with_lmdb" != xcheck && test "x$with_lmdb" != x; then test -z "$LMDB_PATH" && LMDB_PATH="$with_lmdb" if test "x$with_lmdb" != x/usr && test "x$with_lmdb" != x/; then test -z "$LMDB_CFLAGS" && LMDB_CFLAGS="" test -z "$LMDB_CPPFLAGS" && LMDB_CPPFLAGS="-I$with_lmdb/include" test -z "$LMDB_LDFLAGS" && LMDB_LDFLAGS="-L$with_lmdb/lib" fi else LMDB_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $LMDB_CFLAGS" CPPFLAGS="$CPPFLAGS $LMDB_CPPFLAGS" LDFLAGS="$LDFLAGS $LMDB_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mdb_dbi_open in -llmdb" >&5 $as_echo_n "checking for mdb_dbi_open in -llmdb... " >&6; } if ${ac_cv_lib_lmdb_mdb_dbi_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llmdb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mdb_dbi_open (); int main () { return mdb_dbi_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lmdb_mdb_dbi_open=yes else ac_cv_lib_lmdb_mdb_dbi_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmdb_mdb_dbi_open" >&5 $as_echo "$ac_cv_lib_lmdb_mdb_dbi_open" >&6; } if test "x$ac_cv_lib_lmdb_mdb_dbi_open" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLMDB 1 _ACEOF LIBS="-llmdb $LIBS" else as_fn_error $? "Cannot find Lightning MDB" "$LINENO" 5 fi for ac_header in lmdb.h do : ac_fn_c_check_header_mongrel "$LINENO" "lmdb.h" "ac_cv_header_lmdb_h" "$ac_includes_default" if test "x$ac_cv_header_lmdb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LMDB_H 1 _ACEOF else as_fn_error $? "Cannot find Lightning MDB" "$LINENO" 5 fi done $as_echo "#define LMDB 1" >>confdefs.h # # Pick up any libraries added by tests # test -z "$LMDB_LIBS" && LMDB_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_lmdb" != xyes && test "x$with_lmdb" != xcheck; then if test "x$with_lmdb" != x/usr && test "x$with_lmdb" != x/; then LMDB_LDFLAGS="$LMDB_LDFLAGS -R$with_lmdb/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi if test $WITH_QDBM -eq 0 && test $WITH_TOKYO -eq 0 && test $WITH_LMDB -eq 0; then as_fn_error LMDB "Either Tokyo Cabinet" "$LINENO" 5 fi # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; else with_openssl=yes fi if test x"$with_openssl" = xno ; then as_fn_error $? "This release of CFEngine requires OpenSSL >= 0.9.7" "$LINENO" 5 fi # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_openssl" != xyes && test "x$with_openssl" != xcheck && test "x$with_openssl" != x; then test -z "$OPENSSL_PATH" && OPENSSL_PATH="$with_openssl" if test "x$with_openssl" != x/usr && test "x$with_openssl" != x/; then test -z "$OPENSSL_CFLAGS" && OPENSSL_CFLAGS="" test -z "$OPENSSL_CPPFLAGS" && OPENSSL_CPPFLAGS="-I$with_openssl/include" test -z "$OPENSSL_LDFLAGS" && OPENSSL_LDFLAGS="-L$with_openssl/lib" fi else OPENSSL_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $OPENSSL_CFLAGS" CPPFLAGS="$CPPFLAGS $OPENSSL_CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RSA_generate_key_ex in -lcrypto" >&5 $as_echo_n "checking for RSA_generate_key_ex in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_RSA_generate_key_ex+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char RSA_generate_key_ex (); int main () { return RSA_generate_key_ex (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypto_RSA_generate_key_ex=yes else ac_cv_lib_crypto_RSA_generate_key_ex=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_RSA_generate_key_ex" >&5 $as_echo "$ac_cv_lib_crypto_RSA_generate_key_ex" >&6; } if test "x$ac_cv_lib_crypto_RSA_generate_key_ex" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBCRYPTO 1 _ACEOF LIBS="-lcrypto $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_library_init in -lssl" >&5 $as_echo_n "checking for SSL_library_init in -lssl... " >&6; } if ${ac_cv_lib_ssl_SSL_library_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_library_init (); int main () { return SSL_library_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssl_SSL_library_init=yes else ac_cv_lib_ssl_SSL_library_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_library_init" >&5 $as_echo "$ac_cv_lib_ssl_SSL_library_init" >&6; } if test "x$ac_cv_lib_ssl_SSL_library_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBSSL 1 _ACEOF LIBS="-lssl $LIBS" fi ac_fn_c_check_decl "$LINENO" "SSL_CTX_clear_options" "ac_cv_have_decl_SSL_CTX_clear_options" "#include " if test "x$ac_cv_have_decl_SSL_CTX_clear_options" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SSL_CTX_CLEAR_OPTIONS $ac_have_decl _ACEOF for ac_header in openssl/opensslv.h do : ac_fn_c_check_header_mongrel "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_opensslv_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OPENSSL_OPENSSLV_H 1 _ACEOF else as_fn_error $? "Cannot find OpenSSL" "$LINENO" 5 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL version" >&5 $as_echo_n "checking for OpenSSL version... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if OPENSSL_VERSION_NUMBER < 0x0090602fL #This OpenSSL is too old #endif _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: OK" >&5 $as_echo "OK" >&6; } else as_fn_error $? "This release of CFEngine requires OpenSSL >= 0.9.7" "$LINENO" 5 fi rm -f conftest.err conftest.i conftest.$ac_ext if test "x$ac_cv_lib_crypto_RSA_generate_key_ex" = "xyes" ; then $as_echo "#define OPENSSL_NO_DEPRECATED 1" >>confdefs.h fi if test "x$ac_cv_lib_crypto_RSA_generate_key_ex" = "xno" && \ test "x$ac_cv_lib_crypto_RSA_generate_key" = "xno" ; then as_fn_error $? "Cannot find OpenSSL" "$LINENO" 5 fi # # Pick up any libraries added by tests # test -z "$OPENSSL_LIBS" && OPENSSL_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_openssl" != xyes && test "x$with_openssl" != xcheck; then if test "x$with_openssl" != x/usr && test "x$with_openssl" != x/; then OPENSSL_LDFLAGS="$OPENSSL_LDFLAGS -R$with_openssl/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" # Check whether --with-pcre was given. if test "${with_pcre+set}" = set; then : withval=$with_pcre; else with_pcre=yes fi if test "x$with_pcre" = "xno"; then as_fn_error $? "PCRE is required" "$LINENO" 5 fi # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_pcre" != xyes && test "x$with_pcre" != xcheck && test "x$with_pcre" != x; then test -z "$PCRE_PATH" && PCRE_PATH="$with_pcre" if test "x$with_pcre" != x/usr && test "x$with_pcre" != x/; then test -z "$PCRE_CFLAGS" && PCRE_CFLAGS="" test -z "$PCRE_CPPFLAGS" && PCRE_CPPFLAGS="-I$with_pcre/include" test -z "$PCRE_LDFLAGS" && PCRE_LDFLAGS="-L$with_pcre/lib" fi else PCRE_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $PCRE_CFLAGS" CPPFLAGS="$CPPFLAGS $PCRE_CPPFLAGS" LDFLAGS="$LDFLAGS $PCRE_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_exec in -lpcre" >&5 $as_echo_n "checking for pcre_exec in -lpcre... " >&6; } if ${ac_cv_lib_pcre_pcre_exec+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcre $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcre_exec (); int main () { return pcre_exec (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcre_pcre_exec=yes else ac_cv_lib_pcre_pcre_exec=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_exec" >&5 $as_echo "$ac_cv_lib_pcre_pcre_exec" >&6; } if test "x$ac_cv_lib_pcre_pcre_exec" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCRE 1 _ACEOF LIBS="-lpcre $LIBS" else as_fn_error $? "Cannot find PCRE" "$LINENO" 5 fi for ac_header in pcre.h do : ac_fn_c_check_header_mongrel "$LINENO" "pcre.h" "ac_cv_header_pcre_h" "$ac_includes_default" if test "x$ac_cv_header_pcre_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCRE_H 1 _ACEOF else for ac_header in pcre/pcre.h do : ac_fn_c_check_header_mongrel "$LINENO" "pcre/pcre.h" "ac_cv_header_pcre_pcre_h" "$ac_includes_default" if test "x$ac_cv_header_pcre_pcre_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCRE_PCRE_H 1 _ACEOF else as_fn_error $? "Cannot find PCRE" "$LINENO" 5 fi done fi done # # Pick up any libraries added by tests # test -z "$PCRE_LIBS" && PCRE_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_pcre" != xyes && test "x$with_pcre" != xcheck; then if test "x$with_pcre" != x/usr && test "x$with_pcre" != x/; then PCRE_LDFLAGS="$PCRE_LDFLAGS -R$with_pcre/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" # Check whether --with-libvirt was given. if test "${with_libvirt+set}" = set; then : withval=$with_libvirt; else with_libvirt=check fi if test "x$with_libvirt" != xno; then # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_libvirt" != xyes && test "x$with_libvirt" != xcheck && test "x$with_libvirt" != x; then test -z "$LIBVIRT_PATH" && LIBVIRT_PATH="$with_libvirt" if test "x$with_libvirt" != x/usr && test "x$with_libvirt" != x/; then test -z "$LIBVIRT_CFLAGS" && LIBVIRT_CFLAGS="" test -z "$LIBVIRT_CPPFLAGS" && LIBVIRT_CPPFLAGS="-I$with_libvirt/include" test -z "$LIBVIRT_LDFLAGS" && LIBVIRT_LDFLAGS="-L$with_libvirt/lib" fi else LIBVIRT_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $LIBVIRT_CFLAGS" CPPFLAGS="$CPPFLAGS $LIBVIRT_CPPFLAGS" LDFLAGS="$LDFLAGS $LIBVIRT_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for virConnectOpen in -lvirt" >&5 $as_echo_n "checking for virConnectOpen in -lvirt... " >&6; } if ${ac_cv_lib_virt_virConnectOpen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvirt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char virConnectOpen (); int main () { return virConnectOpen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_virt_virConnectOpen=yes else ac_cv_lib_virt_virConnectOpen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_virt_virConnectOpen" >&5 $as_echo "$ac_cv_lib_virt_virConnectOpen" >&6; } if test "x$ac_cv_lib_virt_virConnectOpen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBVIRT 1 _ACEOF LIBS="-lvirt $LIBS" else if test "x$with_libvirt" != xcheck; then as_fn_error $? "Cannot find libvirt library" "$LINENO" 5; fi fi for ac_header in libvirt/libvirt.h do : ac_fn_c_check_header_mongrel "$LINENO" "libvirt/libvirt.h" "ac_cv_header_libvirt_libvirt_h" "$ac_includes_default" if test "x$ac_cv_header_libvirt_libvirt_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBVIRT_LIBVIRT_H 1 _ACEOF else if test "x$with_libvirt" != xcheck; then as_fn_error $? "Cannot find libvirt library headers" "$LINENO" 5; fi fi done # # Pick up any libraries added by tests # test -z "$LIBVIRT_LIBS" && LIBVIRT_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_libvirt" != xyes && test "x$with_libvirt" != xcheck; then if test "x$with_libvirt" != x/usr && test "x$with_libvirt" != x/; then LIBVIRT_LDFLAGS="$LIBVIRT_LDFLAGS -R$with_libvirt/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # Check whether --with-libacl was given. if test "${with_libacl+set}" = set; then : withval=$with_libacl; else with_libacl=check fi if test "x$with_libacl" != xno; then # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_libacl" != xyes && test "x$with_libacl" != xcheck && test "x$with_libacl" != x; then test -z "$LIBACL_PATH" && LIBACL_PATH="$with_libacl" if test "x$with_libacl" != x/usr && test "x$with_libacl" != x/; then test -z "$LIBACL_CFLAGS" && LIBACL_CFLAGS="" test -z "$LIBACL_CPPFLAGS" && LIBACL_CPPFLAGS="-I$with_libacl/include" test -z "$LIBACL_LDFLAGS" && LIBACL_LDFLAGS="-L$with_libacl/lib" fi else LIBACL_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $LIBACL_CFLAGS" CPPFLAGS="$CPPFLAGS $LIBACL_CPPFLAGS" LDFLAGS="$LDFLAGS $LIBACL_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for acl_init in -lacl" >&5 $as_echo_n "checking for acl_init in -lacl... " >&6; } if ${ac_cv_lib_acl_acl_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lacl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char acl_init (); int main () { return acl_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_acl_acl_init=yes else ac_cv_lib_acl_acl_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_acl_acl_init" >&5 $as_echo "$ac_cv_lib_acl_acl_init" >&6; } if test "x$ac_cv_lib_acl_acl_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBACL 1 _ACEOF LIBS="-lacl $LIBS" else if test "x$with_libacl" != xcheck; then as_fn_error $? "Cannot find libacl library" "$LINENO" 5; fi fi for ac_header in acl.h sys/acl.h acl/libacl.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF libacl_header_found=yes fi done if test "x$libacl_header_found" != "xyes" && test "x$with_libacl" != xcheck; then as_fn_error $? "Cannot find libacl library headers" "$LINENO" 5; fi # # Pick up any libraries added by tests # test -z "$LIBACL_LIBS" && LIBACL_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_libacl" != xyes && test "x$with_libacl" != xcheck; then if test "x$with_libacl" != x/usr && test "x$with_libacl" != x/; then LIBACL_LDFLAGS="$LIBACL_LDFLAGS -R$with_libacl/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi # Check whether --with-libxml2 was given. if test "${with_libxml2+set}" = set; then : withval=$with_libxml2; else with_libxml2=check fi if test "x$with_libxml2" != xno then if test "x$with_libxml2" != xyes && test "x$with_libxml2" != xcheck then XML2_CONFIG=$with_libxml2/bin/xml2-config else XML2_CONFIG=xml2-config fi # xml2-config is only for native builds if test "x$cross_compiling" = "xno" && test x`which $XML2_CONFIG` != x then xml2_include_dir=`$XML2_CONFIG --cflags` if test -n "$xml2_include_dir" then LIBXML2_CPPFLAGS="$xml2_include_dir" fi else # xml2-config not found # if a path, e.g. /var/cfengine was given, then we # must take into account that libxml2 includes are in # /var/cfengine/include/libxml2 LIBXML2_CPPFLAGS=-I$with_libxml2/include/libxml2 fi # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_libxml2" != xyes && test "x$with_libxml2" != xcheck && test "x$with_libxml2" != x; then test -z "$LIBXML2_PATH" && LIBXML2_PATH="$with_libxml2" if test "x$with_libxml2" != x/usr && test "x$with_libxml2" != x/; then test -z "$LIBXML2_CFLAGS" && LIBXML2_CFLAGS="" test -z "$LIBXML2_CPPFLAGS" && LIBXML2_CPPFLAGS="-I$with_libxml2/include" test -z "$LIBXML2_LDFLAGS" && LIBXML2_LDFLAGS="-L$with_libxml2/lib" fi else LIBXML2_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $LIBXML2_CFLAGS" CPPFLAGS="$CPPFLAGS $LIBXML2_CPPFLAGS" LDFLAGS="$LDFLAGS $LIBXML2_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlFirstElementChild in -lxml2" >&5 $as_echo_n "checking for xmlFirstElementChild in -lxml2... " >&6; } if ${ac_cv_lib_xml2_xmlFirstElementChild+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lxml2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char xmlFirstElementChild (); int main () { return xmlFirstElementChild (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_xml2_xmlFirstElementChild=yes else ac_cv_lib_xml2_xmlFirstElementChild=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlFirstElementChild" >&5 $as_echo "$ac_cv_lib_xml2_xmlFirstElementChild" >&6; } if test "x$ac_cv_lib_xml2_xmlFirstElementChild" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBXML2 1 _ACEOF LIBS="-lxml2 $LIBS" else if test "x$with_libxml2" != xcheck; then as_fn_error $? "Cannotfind libxml2" "$LINENO" 5; fi fi for ac_header in libxml/xmlwriter.h do : ac_fn_c_check_header_mongrel "$LINENO" "libxml/xmlwriter.h" "ac_cv_header_libxml_xmlwriter_h" "$ac_includes_default" if test "x$ac_cv_header_libxml_xmlwriter_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBXML_XMLWRITER_H 1 _ACEOF break else if test "x$with_libxml2" != xcheck; then as_fn_error $? "Cannot find libxml2" "$LINENO" 5; fi fi done # # Pick up any libraries added by tests # test -z "$LIBXML2_LIBS" && LIBXML2_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_libxml2" != xyes && test "x$with_libxml2" != xcheck; then if test "x$with_libxml2" != x/usr && test "x$with_libxml2" != x/; then LIBXML2_LDFLAGS="$LIBXML2_LDFLAGS -R$with_libxml2/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" fi if test "x$with_libxml2" != xno && test "x$ac_cv_lib_xml2_xmlFirstElementChild" = xyes; then HAVE_LIBXML2_TRUE= HAVE_LIBXML2_FALSE='#' else HAVE_LIBXML2_TRUE='#' HAVE_LIBXML2_FALSE= fi for ac_header in avahi-client/client.h do : ac_fn_c_check_header_mongrel "$LINENO" "avahi-client/client.h" "ac_cv_header_avahi_client_client_h" "$ac_includes_default" if test "x$ac_cv_header_avahi_client_client_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_AVAHI_CLIENT_CLIENT_H 1 _ACEOF if true; then HAVE_AVAHI_CLIENT_TRUE= HAVE_AVAHI_CLIENT_FALSE='#' else HAVE_AVAHI_CLIENT_TRUE='#' HAVE_AVAHI_CLIENT_FALSE= fi else if false; then HAVE_AVAHI_CLIENT_TRUE= HAVE_AVAHI_CLIENT_FALSE='#' else HAVE_AVAHI_CLIENT_TRUE='#' HAVE_AVAHI_CLIENT_FALSE= fi fi done for ac_header in avahi-common/address.h do : ac_fn_c_check_header_mongrel "$LINENO" "avahi-common/address.h" "ac_cv_header_avahi_common_address_h" "$ac_includes_default" if test "x$ac_cv_header_avahi_common_address_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_AVAHI_COMMON_ADDRESS_H 1 _ACEOF if true; then HAVE_AVAHI_COMMON_TRUE= HAVE_AVAHI_COMMON_FALSE='#' else HAVE_AVAHI_COMMON_TRUE='#' HAVE_AVAHI_COMMON_FALSE= fi else if false; then HAVE_AVAHI_COMMON_TRUE= HAVE_AVAHI_COMMON_FALSE='#' else HAVE_AVAHI_COMMON_TRUE='#' HAVE_AVAHI_COMMON_FALSE= fi fi done for ac_header in unistd.h stdlib.h sys/loadavg.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/param.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" if test "x$ac_cv_header_sys_param_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_PARAM_H 1 _ACEOF fi done # sys/param.h is required for sys/mount.h on OpenBSD for ac_header in sys/mount.h do : ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" "$ac_includes_default #ifdef HAVE_SYS_PARAM_H # include #endif " if test "x$ac_cv_header_sys_mount_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_MOUNT_H 1 _ACEOF fi done # Required on BSD to get struct sockaddr_dl (for retrieving MAC addresses from getifaddrs()) for ac_header in net/if_dl.h do : ac_fn_c_check_header_mongrel "$LINENO" "net/if_dl.h" "ac_cv_header_net_if_dl_h" "$ac_includes_default" if test "x$ac_cv_header_net_if_dl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NET_IF_DL_H 1 _ACEOF fi done for ac_header in utime.h do : ac_fn_c_check_header_mongrel "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default" if test "x$ac_cv_header_utime_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UTIME_H 1 _ACEOF fi done for ac_header in time.h do : ac_fn_c_check_header_mongrel "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" if test "x$ac_cv_header_time_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TIME_H 1 _ACEOF fi done for ac_header in sys/time.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TIME_H 1 _ACEOF fi done for ac_header in malloc.h sys/malloc.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in vfs.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfs.h" "ac_cv_header_vfs_h" "$ac_includes_default" if test "x$ac_cv_header_vfs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFS_H 1 _ACEOF fi done for ac_header in sys/vfs.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/vfs.h" "ac_cv_header_sys_vfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_vfs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_VFS_H 1 _ACEOF fi done for ac_header in sys/sockio.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/sockio.h" "ac_cv_header_sys_sockio_h" "$ac_includes_default" if test "x$ac_cv_header_sys_sockio_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SOCKIO_H 1 _ACEOF fi done for ac_header in sys/statvfs.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/statvfs.h" "ac_cv_header_sys_statvfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statvfs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_STATVFS_H 1 _ACEOF fi done for ac_header in sys/statfs.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/statfs.h" "ac_cv_header_sys_statfs_h" "$ac_includes_default" if test "x$ac_cv_header_sys_statfs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_STATFS_H 1 _ACEOF fi done for ac_header in fcntl.h do : ac_fn_c_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" if test "x$ac_cv_header_fcntl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FCNTL_H 1 _ACEOF fi done for ac_header in sys/filesys.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/filesys.h" "ac_cv_header_sys_filesys_h" "$ac_includes_default" if test "x$ac_cv_header_sys_filesys_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_FILESYS_H 1 _ACEOF fi done for ac_header in dustat.h do : ac_fn_c_check_header_mongrel "$LINENO" "dustat.h" "ac_cv_header_dustat_h" "$ac_includes_default" if test "x$ac_cv_header_dustat_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DUSTAT_H 1 _ACEOF fi done for ac_header in sys/systeminfo.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/systeminfo.h" "ac_cv_header_sys_systeminfo_h" "$ac_includes_default" if test "x$ac_cv_header_sys_systeminfo_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SYSTEMINFO_H 1 _ACEOF fi done for ac_header in ieeefp.h do : ac_fn_c_check_header_mongrel "$LINENO" "ieeefp.h" "ac_cv_header_ieeefp_h" "$ac_includes_default" if test "x$ac_cv_header_ieeefp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_IEEEFP_H 1 _ACEOF fi done for ac_header in winsock2.h do : ac_fn_c_check_header_mongrel "$LINENO" "winsock2.h" "ac_cv_header_winsock2_h" "$ac_includes_default" if test "x$ac_cv_header_winsock2_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_WINSOCK2_H 1 _ACEOF fi done for ac_header in ws2tcpip.h do : ac_fn_c_check_header_mongrel "$LINENO" "ws2tcpip.h" "ac_cv_header_ws2tcpip_h" "$ac_includes_default" if test "x$ac_cv_header_ws2tcpip_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_WS2TCPIP_H 1 _ACEOF fi done for ac_header in zone.h do : ac_fn_c_check_header_mongrel "$LINENO" "zone.h" "ac_cv_header_zone_h" "$ac_includes_default" if test "x$ac_cv_header_zone_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ZONE_H 1 _ACEOF fi done for ac_header in sys/uio.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/uio.h" "ac_cv_header_sys_uio_h" "$ac_includes_default" if test "x$ac_cv_header_sys_uio_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_UIO_H 1 _ACEOF fi done for ac_header in sys/types.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" if test "x$ac_cv_header_sys_types_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_TYPES_H 1 _ACEOF fi done for ac_header in sys/mpctl.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/mpctl.h" "ac_cv_header_sys_mpctl_h" "$ac_includes_default" if test "x$ac_cv_header_sys_mpctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_MPCTL_H 1 _ACEOF fi done for ac_header in shadow.h do : ac_fn_c_check_header_mongrel "$LINENO" "shadow.h" "ac_cv_header_shadow_h" "$ac_includes_default" if test "x$ac_cv_header_shadow_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SHADOW_H 1 _ACEOF fi done for ac_header in sys/jail.h do : ac_fn_c_check_header_compile "$LINENO" "sys/jail.h" "ac_cv_header_sys_jail_h" "$ac_includes_default #ifdef HAVE_SYS_PARAM_H # include #endif " if test "x$ac_cv_header_sys_jail_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_JAIL_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if ${ac_cv_header_sys_wait_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 $as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } if ${ac_cv_header_stdbool_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; /* See body of main program for 'e'. */ char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; /* The following fails for HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { bool e = &s; *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdbool_h=yes else ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 $as_echo "$ac_cv_header_stdbool_h" >&6; } ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" if test "x$ac_cv_type__Bool" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "clockid_t" "ac_cv_type_clockid_t" "$ac_includes_default" if test "x$ac_cv_type_clockid_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CLOCKID_T 1 _ACEOF fi ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" " #ifdef HAVE_SYS_TYPES_H # include #endif #include " if test "x$ac_cv_type_socklen_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SOCKLEN_T 1 _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5 $as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } if ${ac_cv_sys_largefile_source+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=no; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGEFILE_SOURCE 1 #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=1; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_cv_sys_largefile_source=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 $as_echo "$ac_cv_sys_largefile_source" >&6; } case $ac_cv_sys_largefile_source in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source _ACEOF ;; esac rm -rf conftest* # We used to try defining _XOPEN_SOURCE=500 too, to work around a bug # in glibc 2.1.3, but that breaks too many other things. # If you want fseeko and ftello with glibc, upgrade to a fixed glibc. if test $ac_cv_sys_largefile_source != unknown; then $as_echo "#define HAVE_FSEEKO 1" >>confdefs.h fi # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 $as_echo_n "checking for special C compiler options needed for large files... " >&6; } if ${ac_cv_sys_largefile_CC+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_largefile_CC=no if test "$GCC" != yes; then ac_save_CC=$CC while :; do # IRIX 6.2 and later do not support large files by default, # so use the C compiler's -n32 option if that helps. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : break fi rm -f core conftest.err conftest.$ac_objext CC="$CC -n32" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_largefile_CC=' -n32'; break fi rm -f core conftest.err conftest.$ac_objext break done CC=$ac_save_CC rm -f conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 $as_echo "$ac_cv_sys_largefile_CC" >&6; } if test "$ac_cv_sys_largefile_CC" != no; then CC=$CC$ac_cv_sys_largefile_CC fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_file_offset_bits=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } case $ac_cv_sys_file_offset_bits in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF ;; esac rm -rf conftest* if test $ac_cv_sys_file_offset_bits = unknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=no; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include /* Check that off_t can represent 2**63 - 1 correctly. We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ #define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1; break fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_sys_large_files=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } case $ac_cv_sys_large_files in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF ;; esac rm -rf conftest* fi fi ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" if test "x$ac_cv_type_off_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define off_t long int _ACEOF fi # # AC_SYS_LARGEFILE correctly figures out necessary macros for large files, but # on AIX there is a gotcha: # # Code generated by flex #includes at the beginning of the file, which # picks up 32-bit wide off_t. Then it #includes which provides LFS # macros, and finally it includes another system header, now with 64-bit wide # off_t, which causes a conflict. # if test "x$ac_cv_sys_large_files" = x1; then CPPFLAGS="-D_LARGE_FILES=1 $CPPFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqrt in -lm" >&5 $as_echo_n "checking for sqrt in -lm... " >&6; } if ${ac_cv_lib_m_sqrt+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sqrt (); int main () { return sqrt (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_sqrt=yes else ac_cv_lib_m_sqrt=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sqrt" >&5 $as_echo "$ac_cv_lib_m_sqrt" >&6; } if test "x$ac_cv_lib_m_sqrt" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 $as_echo_n "checking for clock_gettime in -lrt... " >&6; } if ${ac_cv_lib_rt_clock_gettime+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char clock_gettime (); int main () { return clock_gettime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rt_clock_gettime=yes else ac_cv_lib_rt_clock_gettime=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 $as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBS="-ldl $LIBS" fi ac_fn_c_check_decl "$LINENO" "clock_gettime" "ac_cv_have_decl_clock_gettime" "#include " if test "x$ac_cv_have_decl_clock_gettime" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_CLOCK_GETTIME $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" if test "x$ac_cv_func_clock_gettime" = xyes; then : $as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h else case " $LIBOBJS " in *" clock_gettime.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS clock_gettime.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "unsetenv" "ac_cv_have_decl_unsetenv" "$ac_includes_default" if test "x$ac_cv_have_decl_unsetenv" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_UNSETENV $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" if test "x$ac_cv_func_unsetenv" = xyes; then : $as_echo "#define HAVE_UNSETENV 1" >>confdefs.h else case " $LIBOBJS " in *" unsetenv.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS unsetenv.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strnlen" "ac_cv_have_decl_strnlen" "$ac_includes_default" if test "x$ac_cv_have_decl_strnlen" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRNLEN $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strnlen" "ac_cv_func_strnlen" if test "x$ac_cv_func_strnlen" = xyes; then : $as_echo "#define HAVE_STRNLEN 1" >>confdefs.h else case " $LIBOBJS " in *" strnlen.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strnlen.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strndup" "ac_cv_have_decl_strndup" "$ac_includes_default" if test "x$ac_cv_have_decl_strndup" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRNDUP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strndup" "ac_cv_func_strndup" if test "x$ac_cv_func_strndup" = xyes; then : $as_echo "#define HAVE_STRNDUP 1" >>confdefs.h else case " $LIBOBJS " in *" strndup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strndup.$ac_objext" ;; esac fi if test $ac_cv_have_decl_strndup = no; then HAVE_DECL_STRNDUP=0 fi if test $ac_cv_func_strndup = yes; then HAVE_STRNDUP=1 # AIX 5.3 has a function that tries to copy the entire range specified # by n, instead of just the length of src. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strndup" >&5 $as_echo_n "checking for working strndup... " >&6; } if ${cf3_cv_func_strndup_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : case $host_os in aix | aix[3-6]*) cf3_cv_func_strndup_works="guessing no";; *) cf3_cv_func_strndup_works="guessing yes";; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if !HAVE_DECL_STRNDUP extern #ifdef __cplusplus "C" #endif char *strndup (const char *, size_t); #endif char *s; // Will crash if strndup tries to traverse all 2GB. s = strndup ("string", 2000000000); return 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : cf3_cv_func_strndup_works=yes else cf3_cv_func_strndup_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cf3_cv_func_strndup_works" >&5 $as_echo "$cf3_cv_func_strndup_works" >&6; } case $cf3_cv_func_strndup_works in *no) case " $LIBOBJS " in *" strndup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strndup.$ac_objext" ;; esac ;; esac else HAVE_STRNDUP=0 fi ac_fn_c_check_decl "$LINENO" "setlinebuf" "ac_cv_have_decl_setlinebuf" "$ac_includes_default" if test "x$ac_cv_have_decl_setlinebuf" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SETLINEBUF $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "setlinebuf" "ac_cv_func_setlinebuf" if test "x$ac_cv_func_setlinebuf" = xyes; then : $as_echo "#define HAVE_SETLINEBUF 1" >>confdefs.h else case " $LIBOBJS " in *" setlinebuf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS setlinebuf.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strlcat" "ac_cv_have_decl_strlcat" "$ac_includes_default" if test "x$ac_cv_have_decl_strlcat" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRLCAT $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat" if test "x$ac_cv_func_strlcat" = xyes; then : $as_echo "#define HAVE_STRLCAT 1" >>confdefs.h else case " $LIBOBJS " in *" strlcat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strlcat.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strlcpy" "ac_cv_have_decl_strlcpy" "$ac_includes_default" if test "x$ac_cv_have_decl_strlcpy" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRLCPY $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" if test "x$ac_cv_func_strlcpy" = xyes; then : $as_echo "#define HAVE_STRLCPY 1" >>confdefs.h else case " $LIBOBJS " in *" strlcpy.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "realpath" "ac_cv_have_decl_realpath" "$ac_includes_default" if test "x$ac_cv_have_decl_realpath" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_REALPATH $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "strdup" "ac_cv_have_decl_strdup" "$ac_includes_default" if test "x$ac_cv_have_decl_strdup" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRDUP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" if test "x$ac_cv_func_strdup" = xyes; then : $as_echo "#define HAVE_STRDUP 1" >>confdefs.h else case " $LIBOBJS " in *" strdup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strdup.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "memrchr" "ac_cv_have_decl_memrchr" "$ac_includes_default" if test "x$ac_cv_have_decl_memrchr" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_MEMRCHR $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "memrchr" "ac_cv_func_memrchr" if test "x$ac_cv_func_memrchr" = xyes; then : $as_echo "#define HAVE_MEMRCHR 1" >>confdefs.h else case " $LIBOBJS " in *" memrchr.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memrchr.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "round" "ac_cv_have_decl_round" "#include " if test "x$ac_cv_have_decl_round" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_ROUND $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "round" "ac_cv_func_round" if test "x$ac_cv_func_round" = xyes; then : $as_echo "#define HAVE_ROUND 1" >>confdefs.h else case " $LIBOBJS " in *" round.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS round.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "nanosleep" "ac_cv_have_decl_nanosleep" "$ac_includes_default" if test "x$ac_cv_have_decl_nanosleep" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_NANOSLEEP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep" if test "x$ac_cv_func_nanosleep" = xyes; then : $as_echo "#define HAVE_NANOSLEEP 1" >>confdefs.h else case " $LIBOBJS " in *" nanosleep.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS nanosleep.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "memdup" "ac_cv_have_decl_memdup" "$ac_includes_default" if test "x$ac_cv_have_decl_memdup" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_MEMDUP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "memdup" "ac_cv_func_memdup" if test "x$ac_cv_func_memdup" = xyes; then : $as_echo "#define HAVE_MEMDUP 1" >>confdefs.h else case " $LIBOBJS " in *" memdup.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memdup.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "memmem" "ac_cv_have_decl_memmem" "$ac_includes_default" if test "x$ac_cv_have_decl_memmem" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_MEMMEM $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "memmem" "ac_cv_func_memmem" if test "x$ac_cv_func_memmem" = xyes; then : $as_echo "#define HAVE_MEMMEM 1" >>confdefs.h else case " $LIBOBJS " in *" memmem.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memmem.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "srand48" "ac_cv_have_decl_srand48" "$ac_includes_default" if test "x$ac_cv_have_decl_srand48" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SRAND48 $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "srand48" "ac_cv_func_srand48" if test "x$ac_cv_func_srand48" = xyes; then : $as_echo "#define HAVE_SRAND48 1" >>confdefs.h else case " $LIBOBJS " in *" srand48.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS srand48.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "drand48" "ac_cv_have_decl_drand48" "$ac_includes_default" if test "x$ac_cv_have_decl_drand48" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_DRAND48 $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "drand48" "ac_cv_func_drand48" if test "x$ac_cv_func_drand48" = xyes; then : $as_echo "#define HAVE_DRAND48 1" >>confdefs.h else case " $LIBOBJS " in *" drand48.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS drand48.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strerror" "ac_cv_have_decl_strerror" "$ac_includes_default" if test "x$ac_cv_have_decl_strerror" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRERROR $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" if test "x$ac_cv_func_strerror" = xyes; then : $as_echo "#define HAVE_STRERROR 1" >>confdefs.h else case " $LIBOBJS " in *" strerror.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strerror.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strstr" "ac_cv_have_decl_strstr" "$ac_includes_default" if test "x$ac_cv_have_decl_strstr" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRSTR $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr" if test "x$ac_cv_func_strstr" = xyes; then : $as_echo "#define HAVE_STRSTR 1" >>confdefs.h else case " $LIBOBJS " in *" strstr.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strstr.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strcasestr" "ac_cv_have_decl_strcasestr" "$ac_includes_default" if test "x$ac_cv_have_decl_strcasestr" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRCASESTR $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strcasestr" "ac_cv_func_strcasestr" if test "x$ac_cv_func_strcasestr" = xyes; then : $as_echo "#define HAVE_STRCASESTR 1" >>confdefs.h else case " $LIBOBJS " in *" strcasestr.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strcasestr.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strcasecmp" "ac_cv_have_decl_strcasecmp" "$ac_includes_default" if test "x$ac_cv_have_decl_strcasecmp" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRCASECMP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" if test "x$ac_cv_func_strcasecmp" = xyes; then : $as_echo "#define HAVE_STRCASECMP 1" >>confdefs.h else case " $LIBOBJS " in *" strcasecmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strcasecmp.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strncasecmp" "ac_cv_have_decl_strncasecmp" "$ac_includes_default" if test "x$ac_cv_have_decl_strncasecmp" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRNCASECMP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strncasecmp" "ac_cv_func_strncasecmp" if test "x$ac_cv_func_strncasecmp" = xyes; then : $as_echo "#define HAVE_STRNCASECMP 1" >>confdefs.h else case " $LIBOBJS " in *" strncasecmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strncasecmp.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strsep" "ac_cv_have_decl_strsep" "$ac_includes_default" if test "x$ac_cv_have_decl_strsep" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRSEP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep" if test "x$ac_cv_func_strsep" = xyes; then : $as_echo "#define HAVE_STRSEP 1" >>confdefs.h else case " $LIBOBJS " in *" strsep.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strsep.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strsignal" "ac_cv_have_decl_strsignal" "$ac_includes_default" if test "x$ac_cv_have_decl_strsignal" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRSIGNAL $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal" if test "x$ac_cv_func_strsignal" = xyes; then : $as_echo "#define HAVE_STRSIGNAL 1" >>confdefs.h else case " $LIBOBJS " in *" strsignal.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strsignal.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "gmtime_r" "ac_cv_have_decl_gmtime_r" "#include " if test "x$ac_cv_have_decl_gmtime_r" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GMTIME_R $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r" if test "x$ac_cv_func_gmtime_r" = xyes; then : $as_echo "#define HAVE_GMTIME_R 1" >>confdefs.h else case " $LIBOBJS " in *" gmtime_r.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS gmtime_r.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "getline" "ac_cv_have_decl_getline" "#define _GNU_SOURCE 1 $ac_includes_default " if test "x$ac_cv_have_decl_getline" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETLINE $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline" if test "x$ac_cv_func_getline" = xyes; then : $as_echo "#define HAVE_GETLINE 1" >>confdefs.h else case " $LIBOBJS " in *" getline.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getline.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "localtime_r" "ac_cv_have_decl_localtime_r" "#include " if test "x$ac_cv_have_decl_localtime_r" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_LOCALTIME_R $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" if test "x$ac_cv_func_localtime_r" = xyes; then : $as_echo "#define HAVE_LOCALTIME_R 1" >>confdefs.h else case " $LIBOBJS " in *" localtime_r.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS localtime_r.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "fgetgrent" "ac_cv_have_decl_fgetgrent" "#include " if test "x$ac_cv_have_decl_fgetgrent" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_FGETGRENT $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "isfinite" "ac_cv_have_decl_isfinite" "#include " if test "x$ac_cv_have_decl_isfinite" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_ISFINITE $ac_have_decl _ACEOF for ac_func in getpwent setpwent endpwent do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in fgetspent lckpwdf ulckpwdf do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "getloadavg" "ac_cv_have_decl_getloadavg" "$ac_includes_default" if test "x$ac_cv_have_decl_getloadavg" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETLOADAVG $ac_have_decl _ACEOF ac_have_func=no # yes means we've found a way to get the load average. # Make sure getloadavg.c is where it belongs, at configure-time. test -f "$srcdir/$ac_config_libobj_dir/getloadavg.c" || as_fn_error $? "$srcdir/$ac_config_libobj_dir/getloadavg.c is missing" "$LINENO" 5 ac_save_LIBS=$LIBS # Check for getloadavg, but be sure not to touch the cache variable. (ac_fn_c_check_func "$LINENO" "getloadavg" "ac_cv_func_getloadavg" if test "x$ac_cv_func_getloadavg" = xyes; then : exit 0 else exit 1 fi ) && ac_have_func=yes # On HPUX9, an unprivileged user can get load averages through this function. for ac_func in pstat_getdynamic do : ac_fn_c_check_func "$LINENO" "pstat_getdynamic" "ac_cv_func_pstat_getdynamic" if test "x$ac_cv_func_pstat_getdynamic" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PSTAT_GETDYNAMIC 1 _ACEOF fi done # Solaris has libkstat which does not require root. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5 $as_echo_n "checking for kstat_open in -lkstat... " >&6; } if ${ac_cv_lib_kstat_kstat_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lkstat $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char kstat_open (); int main () { return kstat_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_kstat_kstat_open=yes else ac_cv_lib_kstat_kstat_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5 $as_echo "$ac_cv_lib_kstat_kstat_open" >&6; } if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBKSTAT 1 _ACEOF LIBS="-lkstat $LIBS" fi test $ac_cv_lib_kstat_kstat_open = yes && ac_have_func=yes # Some systems with -lutil have (and need) -lkvm as well, some do not. # On Solaris, -lkvm requires nlist from -lelf, so check that first # to get the right answer into the cache. # For kstat on solaris, we need libelf to force the definition of SVR4 below. if test $ac_have_func = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for elf_begin in -lelf" >&5 $as_echo_n "checking for elf_begin in -lelf... " >&6; } if ${ac_cv_lib_elf_elf_begin+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lelf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char elf_begin (); int main () { return elf_begin (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_elf_elf_begin=yes else ac_cv_lib_elf_elf_begin=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_elf_elf_begin" >&5 $as_echo "$ac_cv_lib_elf_elf_begin" >&6; } if test "x$ac_cv_lib_elf_elf_begin" = xyes; then : LIBS="-lelf $LIBS" fi fi if test $ac_have_func = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_open in -lkvm" >&5 $as_echo_n "checking for kvm_open in -lkvm... " >&6; } if ${ac_cv_lib_kvm_kvm_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lkvm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char kvm_open (); int main () { return kvm_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_kvm_kvm_open=yes else ac_cv_lib_kvm_kvm_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_open" >&5 $as_echo "$ac_cv_lib_kvm_kvm_open" >&6; } if test "x$ac_cv_lib_kvm_kvm_open" = xyes; then : LIBS="-lkvm $LIBS" fi # Check for the 4.4BSD definition of getloadavg. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getloadavg in -lutil" >&5 $as_echo_n "checking for getloadavg in -lutil... " >&6; } if ${ac_cv_lib_util_getloadavg+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lutil $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getloadavg (); int main () { return getloadavg (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_util_getloadavg=yes else ac_cv_lib_util_getloadavg=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_util_getloadavg" >&5 $as_echo "$ac_cv_lib_util_getloadavg" >&6; } if test "x$ac_cv_lib_util_getloadavg" = xyes; then : LIBS="-lutil $LIBS" ac_have_func=yes ac_cv_func_getloadavg_setgid=yes fi fi if test $ac_have_func = no; then # There is a commonly available library for RS/6000 AIX. # Since it is not a standard part of AIX, it might be installed locally. ac_getloadavg_LIBS=$LIBS LIBS="-L/usr/local/lib $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getloadavg in -lgetloadavg" >&5 $as_echo_n "checking for getloadavg in -lgetloadavg... " >&6; } if ${ac_cv_lib_getloadavg_getloadavg+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgetloadavg $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getloadavg (); int main () { return getloadavg (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_getloadavg_getloadavg=yes else ac_cv_lib_getloadavg_getloadavg=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_getloadavg_getloadavg" >&5 $as_echo "$ac_cv_lib_getloadavg_getloadavg" >&6; } if test "x$ac_cv_lib_getloadavg_getloadavg" = xyes; then : LIBS="-lgetloadavg $LIBS" else LIBS=$ac_getloadavg_LIBS fi fi # Make sure it is really in the library, if we think we found it, # otherwise set up the replacement function. for ac_func in getloadavg do : ac_fn_c_check_func "$LINENO" "getloadavg" "ac_cv_func_getloadavg" if test "x$ac_cv_func_getloadavg" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETLOADAVG 1 _ACEOF else case " $LIBOBJS " in *" getloadavg.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getloadavg.$ac_objext" ;; esac $as_echo "#define C_GETLOADAVG 1" >>confdefs.h # Figure out what our getloadavg.c needs. ac_have_func=no ac_fn_c_check_header_mongrel "$LINENO" "sys/dg_sys_info.h" "ac_cv_header_sys_dg_sys_info_h" "$ac_includes_default" if test "x$ac_cv_header_sys_dg_sys_info_h" = xyes; then : ac_have_func=yes $as_echo "#define DGUX 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dg_sys_info in -ldgc" >&5 $as_echo_n "checking for dg_sys_info in -ldgc... " >&6; } if ${ac_cv_lib_dgc_dg_sys_info+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldgc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dg_sys_info (); int main () { return dg_sys_info (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dgc_dg_sys_info=yes else ac_cv_lib_dgc_dg_sys_info=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dgc_dg_sys_info" >&5 $as_echo "$ac_cv_lib_dgc_dg_sys_info" >&6; } if test "x$ac_cv_lib_dgc_dg_sys_info" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDGC 1 _ACEOF LIBS="-ldgc $LIBS" fi fi ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" if test "x$ac_cv_header_locale_h" = xyes; then : fi for ac_func in setlocale do : ac_fn_c_check_func "$LINENO" "setlocale" "ac_cv_func_setlocale" if test "x$ac_cv_func_setlocale" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SETLOCALE 1 _ACEOF fi done # We cannot check for , because Solaris 2 does not use dwarf (it # uses stabs), but it is still SVR4. We cannot check for because # Irix 4.0.5F has the header but not the library. if test $ac_have_func = no && test "$ac_cv_lib_elf_elf_begin" = yes \ && test "$ac_cv_lib_kvm_kvm_open" = yes; then ac_have_func=yes $as_echo "#define SVR4 1" >>confdefs.h fi if test $ac_have_func = no; then ac_fn_c_check_header_mongrel "$LINENO" "inq_stats/cpustats.h" "ac_cv_header_inq_stats_cpustats_h" "$ac_includes_default" if test "x$ac_cv_header_inq_stats_cpustats_h" = xyes; then : ac_have_func=yes $as_echo "#define UMAX 1" >>confdefs.h $as_echo "#define UMAX4_3 1" >>confdefs.h fi fi if test $ac_have_func = no; then ac_fn_c_check_header_mongrel "$LINENO" "sys/cpustats.h" "ac_cv_header_sys_cpustats_h" "$ac_includes_default" if test "x$ac_cv_header_sys_cpustats_h" = xyes; then : ac_have_func=yes; $as_echo "#define UMAX 1" >>confdefs.h fi fi if test $ac_have_func = no; then for ac_header in mach/mach.h do : ac_fn_c_check_header_mongrel "$LINENO" "mach/mach.h" "ac_cv_header_mach_mach_h" "$ac_includes_default" if test "x$ac_cv_header_mach_mach_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MACH_MACH_H 1 _ACEOF fi done fi for ac_header in nlist.h do : ac_fn_c_check_header_mongrel "$LINENO" "nlist.h" "ac_cv_header_nlist_h" "$ac_includes_default" if test "x$ac_cv_header_nlist_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NLIST_H 1 _ACEOF ac_fn_c_check_member "$LINENO" "struct nlist" "n_un.n_name" "ac_cv_member_struct_nlist_n_un_n_name" "#include " if test "x$ac_cv_member_struct_nlist_n_un_n_name" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_NLIST_N_UN_N_NAME 1 _ACEOF $as_echo "#define NLIST_NAME_UNION 1" >>confdefs.h fi fi done fi done # Some definitions of getloadavg require that the program be installed setgid. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getloadavg requires setgid" >&5 $as_echo_n "checking whether getloadavg requires setgid... " >&6; } if ${ac_cv_func_getloadavg_setgid+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include "$srcdir/$ac_config_libobj_dir/getloadavg.c" #ifdef LDAV_PRIVILEGED Yowza Am I SETGID yet #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "Yowza Am I SETGID yet" >/dev/null 2>&1; then : ac_cv_func_getloadavg_setgid=yes else ac_cv_func_getloadavg_setgid=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getloadavg_setgid" >&5 $as_echo "$ac_cv_func_getloadavg_setgid" >&6; } if test $ac_cv_func_getloadavg_setgid = yes; then NEED_SETGID=true $as_echo "#define GETLOADAVG_PRIVILEGED 1" >>confdefs.h else NEED_SETGID=false fi if test $ac_cv_func_getloadavg_setgid = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking group of /dev/kmem" >&5 $as_echo_n "checking group of /dev/kmem... " >&6; } if ${ac_cv_group_kmem+:} false; then : $as_echo_n "(cached) " >&6 else # On Solaris, /dev/kmem is a symlink. Get info on the real file. ac_ls_output=`ls -lgL /dev/kmem 2>/dev/null` # If we got an error (system does not support symlinks), try without -L. test -z "$ac_ls_output" && ac_ls_output=`ls -lg /dev/kmem` ac_cv_group_kmem=`$as_echo "$ac_ls_output" \ | sed -ne 's/[ ][ ]*/ /g; s/^.[sSrwx-]* *[0-9]* *\([^0-9]*\) *.*/\1/; / /s/.* //;p;'` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_group_kmem" >&5 $as_echo "$ac_cv_group_kmem" >&6; } KMEM_GROUP=$ac_cv_group_kmem fi if test "x$ac_save_LIBS" = x; then GETLOADAVG_LIBS=$LIBS else GETLOADAVG_LIBS=`$as_echo "$LIBS" | sed "s|$ac_save_LIBS||"` fi LIBS=$ac_save_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac for ac_header in endian.h do : ac_fn_c_check_header_mongrel "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" if test "x$ac_cv_header_endian_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ENDIAN_H 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "le32toh" "ac_cv_have_decl_le32toh" "#include " if test "x$ac_cv_have_decl_le32toh" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_LE32TOH $ac_have_decl _ACEOF found=0 if test "x/sbin:/usr/sbin:/bin:/usr/bin:$PATH" = "x"; then : path=$PATH else path=/sbin:/usr/sbin:/bin:/usr/bin:$PATH fi $as_echo_n "checking for chpasswd... " for i in $(echo $path | sed -e 's/:/ /g'); do if test -e $i/chpasswd && ls -ld $i/chpasswd | grep '^[^ ][^ ][^ ][xs][^ ][^ ][^ ][^ ][^ ][^ ]' > /dev/null; then : CHPASSWD=$i/chpasswd found=1 break fi done if test "$found" = "1"; then : $as_echo "$CHPASSWD" else $as_echo no CHPASSWD= fi if test "x$CHPASSWD" != "x"; then : $as_echo "#define HAVE_CHPASSWD 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define CHPASSWD "$CHPASSWD" _ACEOF fi found=0 if test "x/sbin:/usr/sbin:/bin:/usr/bin:$PATH" = "x"; then : path=$PATH else path=/sbin:/usr/sbin:/bin:/usr/bin:$PATH fi $as_echo_n "checking for pwdadm... " for i in $(echo $path | sed -e 's/:/ /g'); do if test -e $i/pwdadm && ls -ld $i/pwdadm | grep '^[^ ][^ ][^ ][xs][^ ][^ ][^ ][^ ][^ ][^ ]' > /dev/null; then : PWDADM=$i/pwdadm found=1 break fi done if test "$found" = "1"; then : $as_echo "$PWDADM" else $as_echo no PWDADM= fi if test "x$PWDADM" != "x"; then : $as_echo "#define HAVE_PWDADM 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define PWDADM "$PWDADM" _ACEOF fi found=0 if test "x/sbin:/usr/sbin:/bin:/usr/bin:$PATH" = "x"; then : path=$PATH else path=/sbin:/usr/sbin:/bin:/usr/bin:$PATH fi $as_echo_n "checking for useradd... " for i in $(echo $path | sed -e 's/:/ /g'); do if test -e $i/useradd && ls -ld $i/useradd | grep '^[^ ][^ ][^ ][xs][^ ][^ ][^ ][^ ][^ ][^ ]' > /dev/null; then : USERADD=$i/useradd found=1 break fi done if test "$found" = "1"; then : $as_echo "$USERADD" else $as_echo no USERADD= fi if test "x$USERADD" != "x"; then : $as_echo "#define HAVE_USERADD 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define USERADD "$USERADD" _ACEOF fi found=0 if test "x/sbin:/usr/sbin:/bin:/usr/bin:$PATH" = "x"; then : path=$PATH else path=/sbin:/usr/sbin:/bin:/usr/bin:$PATH fi $as_echo_n "checking for usermod... " for i in $(echo $path | sed -e 's/:/ /g'); do if test -e $i/usermod && ls -ld $i/usermod | grep '^[^ ][^ ][^ ][xs][^ ][^ ][^ ][^ ][^ ][^ ]' > /dev/null; then : USERMOD=$i/usermod found=1 break fi done if test "$found" = "1"; then : $as_echo "$USERMOD" else $as_echo no USERMOD= fi if test "x$USERMOD" != "x"; then : $as_echo "#define HAVE_USERMOD 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define USERMOD "$USERMOD" _ACEOF fi found=0 if test "x/sbin:/usr/sbin:/bin:/usr/bin:$PATH" = "x"; then : path=$PATH else path=/sbin:/usr/sbin:/bin:/usr/bin:$PATH fi $as_echo_n "checking for userdel... " for i in $(echo $path | sed -e 's/:/ /g'); do if test -e $i/userdel && ls -ld $i/userdel | grep '^[^ ][^ ][^ ][xs][^ ][^ ][^ ][^ ][^ ][^ ]' > /dev/null; then : USERDEL=$i/userdel found=1 break fi done if test "$found" = "1"; then : $as_echo "$USERDEL" else $as_echo no USERDEL= fi if test "x$USERDEL" != "x"; then : $as_echo "#define HAVE_USERDEL 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define USERDEL "$USERDEL" _ACEOF fi if test "x$USERADD" != x && \ test "x$USERMOD" != x && test "x$USERDEL" != x; then : have_userprogs=yes else have_userprogs=no fi # Check whether --with-pam was given. if test "${with_pam+set}" = set; then : withval=$with_pam; fi if test x$with_pam != xno; then : # # Populate ${LIBRARY}_{PATH,CFLAGS,LDFLAGS} according to arguments # if test "x$with_pam" != xyes && test "x$with_pam" != xcheck && test "x$with_pam" != x; then test -z "$PAM_PATH" && PAM_PATH="$with_pam" if test "x$with_pam" != x/usr && test "x$with_pam" != x/; then test -z "$PAM_CFLAGS" && PAM_CFLAGS="" test -z "$PAM_CPPFLAGS" && PAM_CPPFLAGS="-I$with_pam/include" test -z "$PAM_LDFLAGS" && PAM_LDFLAGS="-L$with_pam/lib" fi else PAM_PATH="default path" fi # # Save old environment # save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" save_LDFLAGS="$LDFLAGS" save_LIBS="$LIBS" CFLAGS="$CFLAGS $PAM_CFLAGS" CPPFLAGS="$CPPFLAGS $PAM_CPPFLAGS" LDFLAGS="$LDFLAGS $PAM_LDFLAGS" # # Run checks passed as argument # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_start in -lpam" >&5 $as_echo_n "checking for pam_start in -lpam... " >&6; } if ${ac_cv_lib_pam_pam_start+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pam_start (); int main () { return pam_start (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pam_pam_start=yes else ac_cv_lib_pam_pam_start=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_start" >&5 $as_echo "$ac_cv_lib_pam_pam_start" >&6; } if test "x$ac_cv_lib_pam_pam_start" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPAM 1 _ACEOF LIBS="-lpam $LIBS" fi for ac_header in security/pam_appl.h do : ac_fn_c_check_header_mongrel "$LINENO" "security/pam_appl.h" "ac_cv_header_security_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_security_pam_appl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SECURITY_PAM_APPL_H 1 _ACEOF fi done # # Pick up any libraries added by tests # test -z "$PAM_LIBS" && PAM_LIBS="$LIBS" # # libtool understands -R$path, but we are not using libtool in configure # snippets, so -R$path goes to $pkg_LDFLAGS only after autoconf tests # if test "x$with_pam" != xyes && test "x$with_pam" != xcheck; then if test "x$with_pam" != x/usr && test "x$with_pam" != x/; then PAM_LDFLAGS="$PAM_LDFLAGS -R$with_pam/lib" fi fi # # Restore pristine environment # CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" case $target_os in #( *gnu*|*solaris*|*aix*|*hpux*|*hp-ux*) : if test "x$ac_cv_lib_pam_pam_start" != "xyes"; then : as_fn_error $? "Cannot find PAM library" "$LINENO" 5 fi if test "x$ac_cv_header_security_pam_appl_h" != "xyes"; then : as_fn_error $? "Cannot find PAM headers" "$LINENO" 5 fi ;; #( *) : ;; esac if test "x$ac_cv_lib_pam_pam_start" = "xyes" && \ test "x$ac_cv_header_security_pam_appl_h" = "xyes"; then : have_pam=yes else have_pam=no fi for ac_func in fgetpwent fgetgrent do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$have_pam" = "xyes" && \ test "x$have_userprogs" = "xyes" && \ test "x$ac_cv_func_fgetpwent" = "xyes" && \ test "x$ac_cv_func_fgetgrent" = "xyes"; then : users_promises_ok=yes else users_promises_ok=no fi else users_promises_ok=no fi if test "x$users_promises_ok" = "xyes"; then HAVE_USERS_PROMISE_DEPS_TRUE= HAVE_USERS_PROMISE_DEPS_FALSE='#' else HAVE_USERS_PROMISE_DEPS_TRUE='#' HAVE_USERS_PROMISE_DEPS_FALSE= fi ac_fn_c_check_decl "$LINENO" "getnetgrent" "ac_cv_have_decl_getnetgrent" "#include " if test "x$ac_cv_have_decl_getnetgrent" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETNETGRENT $ac_have_decl _ACEOF for ac_func in getnetgrent do : ac_fn_c_check_func "$LINENO" "getnetgrent" "ac_cv_func_getnetgrent" if test "x$ac_cv_func_getnetgrent" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETNETGRENT 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "setnetgrent" "ac_cv_have_decl_setnetgrent" "#include " if test "x$ac_cv_have_decl_setnetgrent" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SETNETGRENT $ac_have_decl _ACEOF for ac_func in setnetgrent do : ac_fn_c_check_func "$LINENO" "setnetgrent" "ac_cv_func_setnetgrent" if test "x$ac_cv_func_setnetgrent" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SETNETGRENT 1 _ACEOF fi done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { extern int setnetgrent(const char *) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define SETNETGRENT_RETURNS_INT 1" >>confdefs.h else $as_echo "#define SETNETGRENT_RETURNS_INT 0" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_fn_c_check_decl "$LINENO" "endnetgrent" "ac_cv_have_decl_endnetgrent" "#include " if test "x$ac_cv_have_decl_endnetgrent" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_ENDNETGRENT $ac_have_decl _ACEOF for ac_func in endnetgrent do : ac_fn_c_check_func "$LINENO" "endnetgrent" "ac_cv_func_endnetgrent" if test "x$ac_cv_func_endnetgrent" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ENDNETGRENT 1 _ACEOF fi done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { extern int endnetgrent(const char *) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define ENDNETGRENT_RETURNS_INT 1" >>confdefs.h else $as_echo "#define ENDNETGRENT_RETURNS_INT 0" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext for ac_func in sendto do : ac_fn_c_check_func "$LINENO" "sendto" "ac_cv_func_sendto" if test "x$ac_cv_func_sendto" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SENDTO 1 _ACEOF fi done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { extern ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define SENDTO_RETURNS_SSIZE_T 1" >>confdefs.h else $as_echo "#define SENDTO_RETURNS_SSIZE_T 0" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_fn_c_check_func "$LINENO" "ctime" "ac_cv_func_ctime" if test "x$ac_cv_func_ctime" = xyes; then : else as_fn_error $? "Unable to find function ctime" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ctime is properly declared" >&5 $as_echo_n "checking whether ctime is properly declared... " >&6; } if ${hw_cv_func_ctime_proper+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #error ctime(3) may produce different results on different OSes. Let's have our POSIX-compliant implementation all the time ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : hw_cv_func_ctime_proper=yes else hw_cv_func_ctime_proper=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_ctime_proper" >&5 $as_echo "$hw_cv_func_ctime_proper" >&6; } if test "$hw_cv_func_ctime_proper" = yes; then : $as_echo "#define HAVE_ctime_PROPER 1" >>confdefs.h else post_macros="$post_macros #define ctime rpl_ctime" fi if test "$hw_cv_func_ctime_proper" = "no"; then : case " $LIBOBJS " in *" rpl_ctime.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS rpl_ctime.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "mkdir" "ac_cv_func_mkdir" if test "x$ac_cv_func_mkdir" = xyes; then : else as_fn_error $? "Unable to find function mkdir" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mkdir is properly declared" >&5 $as_echo_n "checking whether mkdir is properly declared... " >&6; } if ${hw_cv_func_mkdir_proper+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { int mkdir(const char *pathname, mode_t mode); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : hw_cv_func_mkdir_proper=yes else hw_cv_func_mkdir_proper=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_mkdir_proper" >&5 $as_echo "$hw_cv_func_mkdir_proper" >&6; } if test "$hw_cv_func_mkdir_proper" = yes; then : $as_echo "#define HAVE_mkdir_PROPER 1" >>confdefs.h else post_macros="$post_macros #define mkdir rpl_mkdir" fi ac_fn_c_check_func "$LINENO" "stat" "ac_cv_func_stat" if test "x$ac_cv_func_stat" = xyes; then : else as_fn_error $? "Unable to find function stat" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat is properly declared" >&5 $as_echo_n "checking whether stat is properly declared... " >&6; } if ${hw_cv_func_stat_proper+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if defined(__MINGW32__) #error stat in Windows CRT ill-behaves #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : hw_cv_func_stat_proper=yes else hw_cv_func_stat_proper=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_stat_proper" >&5 $as_echo "$hw_cv_func_stat_proper" >&6; } if test "$hw_cv_func_stat_proper" = yes; then : $as_echo "#define HAVE_stat_PROPER 1" >>confdefs.h else post_macros="$post_macros " fi ac_fn_c_check_func "$LINENO" "rename" "ac_cv_func_rename" if test "x$ac_cv_func_rename" = xyes; then : else as_fn_error $? "Unable to find function rename" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether rename is properly declared" >&5 $as_echo_n "checking whether rename is properly declared... " >&6; } if ${hw_cv_func_rename_proper+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #if defined(__MINGW32__) #error rename in Windows CRT ill-behaves #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : hw_cv_func_rename_proper=yes else hw_cv_func_rename_proper=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_rename_proper" >&5 $as_echo "$hw_cv_func_rename_proper" >&6; } if test "$hw_cv_func_rename_proper" = yes; then : $as_echo "#define HAVE_rename_PROPER 1" >>confdefs.h else post_macros="$post_macros #define rename rpl_rename" fi ac_fn_c_check_decl "$LINENO" "mkdtemp" "ac_cv_have_decl_mkdtemp" "$ac_includes_default" if test "x$ac_cv_have_decl_mkdtemp" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_MKDTEMP $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "mkdtemp" "ac_cv_func_mkdtemp" if test "x$ac_cv_func_mkdtemp" = xyes; then : $as_echo "#define HAVE_MKDTEMP 1" >>confdefs.h else case " $LIBOBJS " in *" mkdtemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkdtemp.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "strrstr" "ac_cv_have_decl_strrstr" "$ac_includes_default" if test "x$ac_cv_have_decl_strrstr" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_STRRSTR $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "strrstr" "ac_cv_func_strrstr" if test "x$ac_cv_func_strrstr" = xyes; then : $as_echo "#define HAVE_STRRSTR 1" >>confdefs.h else case " $LIBOBJS " in *" strrstr.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strrstr.$ac_objext" ;; esac fi for ac_func in seteuid setegid setreuid setregid do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in uname gethostname chflags do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in mkfifo statfs statvfs door do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in sysinfo setsid sysconf do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in getzoneid getzonenamebyid do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in fpathconf do : ac_fn_c_check_func "$LINENO" "fpathconf" "ac_cv_func_fpathconf" if test "x$ac_cv_func_fpathconf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FPATHCONF 1 _ACEOF fi done ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_MTIM 1 _ACEOF fi ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimespec" "ac_cv_member_struct_stat_st_mtimespec" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_mtimespec" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_MTIMESPEC 1 _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PRIuMAX/PRIdMAX macros" >&5 $as_echo_n "checking for PRIuMAX/PRIdMAX macros... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include #if defined(PRIuMAX) && defined(PRIdMAX) primacros_found #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "primacros_found" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Unable to find out how to scan intmax_t/uintmax_t types" >&5 $as_echo "Unable to find out how to scan intmax_t/uintmax_t types" >&6; } fi rm -f conftest* for ac_header in stdarg.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDARG_H 1 _ACEOF fi done for ac_header in inttypes.h locale.h stddef.h stdint.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_member "$LINENO" "struct lconv" "decimal_point" "ac_cv_member_struct_lconv_decimal_point" "#include " if test "x$ac_cv_member_struct_lconv_decimal_point" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_LCONV_DECIMAL_POINT 1 _ACEOF fi ac_fn_c_check_member "$LINENO" "struct lconv" "thousands_sep" "ac_cv_member_struct_lconv_thousands_sep" "#include " if test "x$ac_cv_member_struct_lconv_thousands_sep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_LCONV_THOUSANDS_SEP 1 _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long double" >&5 $as_echo_n "checking for long double... " >&6; } if ${ac_cv_type_long_double+:} false; then : $as_echo_n "(cached) " >&6 else if test "$GCC" = yes; then ac_cv_type_long_double=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* The Stardent Vistra knows sizeof (long double), but does not support it. */ long double foo = 0.0L; int main () { static int test_array [1 - 2 * !(/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ sizeof (double) <= sizeof (long double))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_long_double=yes else ac_cv_type_long_double=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_double" >&5 $as_echo "$ac_cv_type_long_double" >&6; } if test $ac_cv_type_long_double = yes; then $as_echo "#define HAVE_LONG_DOUBLE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 $as_echo_n "checking for long long int... " >&6; } if ${ac_cv_type_long_long_int+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* For now, do not test the preprocessor; as of 2007 there are too many implementations with broken preprocessors. Perhaps this can be revisited in 2012. In the meantime, code should not expect #if to work with literals wider than 32 bits. */ /* Test literals. */ long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; unsigned long long int ull = 18446744073709551615ULL; /* Test constant expressions. */ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63; int main () { /* Test availability of runtime routines for shift and division. */ long long int llmax = 9223372036854775807ll; unsigned long long int ullmax = 18446744073709551615ull; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ullmax / ull) | (ullmax % ull)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if test "$cross_compiling" = yes; then : ac_cv_type_long_long_int=yes else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef LLONG_MAX # define HALF \ (1LL << (sizeof (long long int) * CHAR_BIT - 2)) # define LLONG_MAX (HALF - 1 + HALF) #endif int main () { long long int n = 1; int i; for (i = 0; ; i++) { long long int m = n << i; if (m >> i != n) return 1; if (LLONG_MAX / 2 < m) break; } return 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_type_long_long_int=yes else ac_cv_type_long_long_int=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else ac_cv_type_long_long_int=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 $as_echo "$ac_cv_type_long_long_int" >&6; } if test $ac_cv_type_long_long_int = yes; then $as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 $as_echo_n "checking for unsigned long long int... " >&6; } if ${ac_cv_type_unsigned_long_long_int+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* For now, do not test the preprocessor; as of 2007 there are too many implementations with broken preprocessors. Perhaps this can be revisited in 2012. In the meantime, code should not expect #if to work with literals wider than 32 bits. */ /* Test literals. */ long long int ll = 9223372036854775807ll; long long int nll = -9223372036854775807LL; unsigned long long int ull = 18446744073709551615ULL; /* Test constant expressions. */ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) ? 1 : -1)]; typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 ? 1 : -1)]; int i = 63; int main () { /* Test availability of runtime routines for shift and division. */ long long int llmax = 9223372036854775807ll; unsigned long long int ullmax = 18446744073709551615ull; return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) | (llmax / ll) | (llmax % ll) | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) | (ullmax / ull) | (ullmax % ull)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_type_unsigned_long_long_int=yes else ac_cv_type_unsigned_long_long_int=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 $as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } if test $ac_cv_type_unsigned_long_long_int = yes; then $as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "$ac_includes_default" if test "x$ac_cv_type_intmax_t" = xyes; then : $as_echo "#define HAVE_INTMAX_T 1" >>confdefs.h else test $ac_cv_type_long_long_int = yes \ && ac_type='long long int' \ || ac_type='long int' cat >>confdefs.h <<_ACEOF #define intmax_t $ac_type _ACEOF fi ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default" if test "x$ac_cv_type_uintmax_t" = xyes; then : $as_echo "#define HAVE_UINTMAX_T 1" >>confdefs.h else test $ac_cv_type_unsigned_long_long_int = yes \ && ac_type='unsigned long long int' \ || ac_type='unsigned long int' cat >>confdefs.h <<_ACEOF #define uintmax_t $ac_type _ACEOF fi ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" if test "x$ac_cv_type_uintptr_t" = xyes; then : $as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h else for ac_type in 'unsigned int' 'unsigned long int' \ 'unsigned long long int'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat >>confdefs.h <<_ACEOF #define uintptr_t $ac_type _ACEOF ac_type= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test -z "$ac_type" && break done fi ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" if test "x$ac_cv_type_ptrdiff_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PTRDIFF_T 1 _ACEOF fi for ac_func in localeconv do : ac_fn_c_check_func "$LINENO" "localeconv" "ac_cv_func_localeconv" if test "x$ac_cv_func_localeconv" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LOCALECONV 1 _ACEOF fi done ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" if test "x$ac_cv_func_vsnprintf" = xyes; then : hw_cv_func_vsnprintf=yes else hw_cv_func_vsnprintf=no fi if test "$hw_cv_func_vsnprintf" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf is C99 compliant" >&5 $as_echo_n "checking whether vsnprintf is C99 compliant... " >&6; } if ${hw_cv_func_vsnprintf_c99+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : hw_cv_func_vsnprintf_c99=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_STDARG_H #include #endif #include static int testprintf(char *buf, size_t size, const char *format, ...) { int result; va_list ap; va_start(ap, format); result = vsnprintf(buf, size, format, ap); va_end(ap); return result; } int main () { char buf[43]; if (testprintf(buf, 4, "The answer is %27.2g.", 42.0) != 42 || testprintf(buf, 0, "No, it's %32zu.", (size_t)42) != 42 || buf[0] != 'T' || buf[3] != '\0' || testprintf(NULL, 0, "") != 0 || /* POSSIBLE SEGFAULT ON NON-C99 LIBCs!!! */ testprintf(NULL, 0, "Some actual %18s formatting.\nblah %d.\n", "42", 1) != 51) return 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : hw_cv_func_vsnprintf_c99=yes else hw_cv_func_vsnprintf_c99=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_vsnprintf_c99" >&5 $as_echo "$hw_cv_func_vsnprintf_c99" >&6; } else hw_cv_func_snprintf_c99=no fi if test "$hw_cv_func_vsnprintf_c99" = yes; then : $as_echo "#define HAVE_VSNPRINTF 1" >>confdefs.h else $as_echo "#define vsnprintf rpl_vsnprintf" >>confdefs.h $as_echo "#define vprintf rpl_vprintf" >>confdefs.h $as_echo "#define vfprintf rpl_vfprintf" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi for ac_header in stdarg.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDARG_H 1 _ACEOF fi done case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" if test "x$ac_cv_func_snprintf" = xyes; then : hw_cv_func_snprintf=yes else hw_cv_func_snprintf=no fi if test "$hw_cv_func_snprintf" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf is C99 compliant" >&5 $as_echo_n "checking whether snprintf is C99 compliant... " >&6; } if ${hw_cv_func_snprintf_c99+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : hw_cv_func_snprintf_c99=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char buf[43]; if (snprintf(buf, 4, "The answer is %27.2g.", 42.0) != 42 || snprintf(buf, 0, "No, it's %32zu.", (size_t)42) != 42 || buf[0] != 'T' || buf[3] != '\0' || snprintf(NULL, 0, "") != 0 || /* POSSIBLE SEGFAULT ON NON-C99 LIBCs!!! */ snprintf(NULL, 0, "Some actual %18s formatting.\nblah %d.\n", "42", 1) != 51) return 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : hw_cv_func_snprintf_c99=yes else hw_cv_func_snprintf_c99=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_snprintf_c99" >&5 $as_echo "$hw_cv_func_snprintf_c99" >&6; } else hw_cv_func_snprintf_c99=no fi if test "$hw_cv_func_snprintf_c99" = yes; then : $as_echo "#define HAVE_SNPRINTF 1" >>confdefs.h else $as_echo "#define snprintf rpl_snprintf" >>confdefs.h $as_echo "#define printf rpl_printf" >>confdefs.h $as_echo "#define fprintf rpl_fprintf" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi for ac_header in stdarg.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDARG_H 1 _ACEOF fi done case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi for ac_header in varargs.h do : ac_fn_c_check_header_mongrel "$LINENO" "varargs.h" "ac_cv_header_varargs_h" "$ac_includes_default" if test "x$ac_cv_header_varargs_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VARARGS_H 1 _ACEOF fi done for ac_func in vasprintf do : ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" if test "x$ac_cv_func_vasprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VASPRINTF 1 _ACEOF hw_cv_func_vasprintf=yes else hw_cv_func_vasprintf=no fi done if test "$hw_cv_func_vasprintf" = no; then : $as_echo "#define vasprintf rpl_vasprintf" >>confdefs.h for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy" >&5 $as_echo_n "checking for va_copy... " >&6; } if ${hw_cv_func_va_copy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : hw_cv_func_va_copy=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_STDARG_H #include #elif HAVE_VARARGS_H #include #endif int main () { va_list ap, aq; va_copy(aq, ap); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : hw_cv_func_va_copy=yes else hw_cv_func_va_copy=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func_va_copy" >&5 $as_echo "$hw_cv_func_va_copy" >&6; } if test "$hw_cv_func_va_copy" = yes; then : $as_echo "#define HAVE_VA_COPY 1" >>confdefs.h fi if test "$hw_cv_func_va_copy" = no; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __va_copy" >&5 $as_echo_n "checking for __va_copy... " >&6; } if ${hw_cv_func___va_copy+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : hw_cv_func___va_copy=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_STDARG_H #include #elif HAVE_VARARGS_H #include #endif int main () { va_list ap, aq; __va_copy(aq, ap); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : hw_cv_func___va_copy=yes else hw_cv_func___va_copy=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hw_cv_func___va_copy" >&5 $as_echo "$hw_cv_func___va_copy" >&6; } if test "$hw_cv_func___va_copy" = yes; then : $as_echo "#define HAVE___VA_COPY 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi for ac_header in stdarg.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDARG_H 1 _ACEOF fi done case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi for ac_func in asprintf do : ac_fn_c_check_func "$LINENO" "asprintf" "ac_cv_func_asprintf" if test "x$ac_cv_func_asprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ASPRINTF 1 _ACEOF hw_cv_func_asprintf=yes else hw_cv_func_asprintf=no fi done if test "$hw_cv_func_asprintf" = no; then : $as_echo "#define asprintf rpl_asprintf" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi for ac_header in stdarg.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDARG_H 1 _ACEOF fi done case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "dirfd" "ac_cv_have_decl_dirfd" "$ac_includes_default #ifdef HAVE_DIRENT_H # include #endif " if test "x$ac_cv_have_decl_dirfd" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_DIRFD $ac_have_decl _ACEOF for ac_func in dirfd do : ac_fn_c_check_func "$LINENO" "dirfd" "ac_cv_func_dirfd" if test "x$ac_cv_func_dirfd" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DIRFD 1 _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dirfd macro" >&5 $as_echo_n "checking for dirfd macro... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #ifdef HAVE_DIRENT_H # include #endif #ifdef dirfd dirfd_found #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "dirfd_found" >/dev/null 2>&1; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } DIRFD_MACRO_FOUND=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f conftest* if test x$DIRFD_MACRO_FOUND = x; then case " $LIBOBJS " in *" dirfd.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS dirfd.$ac_objext" ;; esac fi fi done for ac_func in jail_get do : ac_fn_c_check_func "$LINENO" "jail_get" "ac_cv_func_jail_get" if test "x$ac_cv_func_jail_get" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_JAIL_GET 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setsockopt" >&5 $as_echo_n "checking for library containing setsockopt... " >&6; } if ${ac_cv_search_setsockopt+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setsockopt (); int main () { return setsockopt (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_setsockopt=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_setsockopt+:} false; then : break fi done if ${ac_cv_search_setsockopt+:} false; then : else ac_cv_search_setsockopt=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setsockopt" >&5 $as_echo "$ac_cv_search_setsockopt" >&6; } ac_res=$ac_cv_search_setsockopt if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostent" >&5 $as_echo_n "checking for library containing gethostent... " >&6; } if ${ac_cv_search_gethostent+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostent (); int main () { return gethostent (); ; return 0; } _ACEOF for ac_lib in '' nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostent=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostent+:} false; then : break fi done if ${ac_cv_search_gethostent+:} false; then : else ac_cv_search_gethostent=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostent" >&5 $as_echo "$ac_cv_search_gethostent" >&6; } ac_res=$ac_cv_search_gethostent if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi for ac_func in socket do : ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" if test "x$ac_cv_func_socket" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SOCKET 1 _ACEOF fi done for ac_func in setsockopt do : ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" if test "x$ac_cv_func_setsockopt" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SETSOCKOPT 1 _ACEOF fi done for ac_func in gethostent do : ac_fn_c_check_func "$LINENO" "gethostent" "ac_cv_func_gethostent" if test "x$ac_cv_func_gethostent" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETHOSTENT 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" " #if HAVE_WINSOCK2_H #include #endif #if HAVE_WS2TCPIP_H #include #else #include #include #endif " if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SOCKADDR_STORAGE 1 _ACEOF fi ac_fn_c_check_decl "$LINENO" "getaddrinfo" "ac_cv_have_decl_getaddrinfo" " #if HAVE_WINSOCK2_H #include #endif #if HAVE_WS2TCPIP_H #include #else #include #include #endif " if test "x$ac_cv_have_decl_getaddrinfo" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETADDRINFO $ac_have_decl _ACEOF if test $ac_have_decl = 1; then : else case " $LIBOBJS " in *" getaddrinfo.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "inet_ntop" "ac_cv_have_decl_inet_ntop" "#include " if test "x$ac_cv_have_decl_inet_ntop" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_INET_NTOP $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "inet_pton" "ac_cv_have_decl_inet_pton" "#include " if test "x$ac_cv_have_decl_inet_pton" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_INET_PTON $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" if test "x$ac_cv_func_inet_ntop" = xyes; then : $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h else case " $LIBOBJS " in *" inet_ntop.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" if test "x$ac_cv_func_inet_pton" = xyes; then : $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h else case " $LIBOBJS " in *" inet_pton.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext" ;; esac fi for ac_func in getifaddrs do : ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs" if test "x$ac_cv_func_getifaddrs" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETIFADDRS 1 _ACEOF fi done for ac_func in getprocs64 do : ac_fn_c_check_func "$LINENO" "getprocs64" "ac_cv_func_getprocs64" if test "x$ac_cv_func_getprocs64" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETPROCS64 1 _ACEOF fi done ac_fn_c_check_func "$LINENO" "lchown" "ac_cv_func_lchown" if test "x$ac_cv_func_lchown" = xyes; then : $as_echo "#define HAVE_LCHOWN 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "pthread_attr_setstacksize" "ac_cv_have_decl_pthread_attr_setstacksize" "#include " if test "x$ac_cv_have_decl_pthread_attr_setstacksize" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_PTHREAD_ATTR_SETSTACKSIZE $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "pthread_attr_setstacksize" "ac_cv_func_pthread_attr_setstacksize" if test "x$ac_cv_func_pthread_attr_setstacksize" = xyes; then : $as_echo "#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1" >>confdefs.h else case " $LIBOBJS " in *" pthread_attr_setstacksize.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS pthread_attr_setstacksize.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "pthread_sigmask" "ac_cv_have_decl_pthread_sigmask" "#include " if test "x$ac_cv_have_decl_pthread_sigmask" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_PTHREAD_SIGMASK $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "pthread_sigmask" "ac_cv_func_pthread_sigmask" if test "x$ac_cv_func_pthread_sigmask" = xyes; then : $as_echo "#define HAVE_PTHREAD_SIGMASK 1" >>confdefs.h else case " $LIBOBJS " in *" pthread_sigmask.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS pthread_sigmask.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "openat" "ac_cv_have_decl_openat" "#include " if test "x$ac_cv_have_decl_openat" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_OPENAT $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "fstatat" "ac_cv_have_decl_fstatat" "#include " if test "x$ac_cv_have_decl_fstatat" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_FSTATAT $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "fchownat" "ac_cv_have_decl_fchownat" "#include " if test "x$ac_cv_have_decl_fchownat" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_FCHOWNAT $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "openat" "ac_cv_func_openat" if test "x$ac_cv_func_openat" = xyes; then : $as_echo "#define HAVE_OPENAT 1" >>confdefs.h else case " $LIBOBJS " in *" openat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS openat.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "fstatat" "ac_cv_func_fstatat" if test "x$ac_cv_func_fstatat" = xyes; then : $as_echo "#define HAVE_FSTATAT 1" >>confdefs.h else case " $LIBOBJS " in *" fstatat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS fstatat.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "fchownat" "ac_cv_func_fchownat" if test "x$ac_cv_func_fchownat" = xyes; then : $as_echo "#define HAVE_FCHOWNAT 1" >>confdefs.h else case " $LIBOBJS " in *" fchownat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS fchownat.$ac_objext" ;; esac fi ac_fn_c_check_decl "$LINENO" "log2" "ac_cv_have_decl_log2" "#include " if test "x$ac_cv_have_decl_log2" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_LOG2 $ac_have_decl _ACEOF ac_fn_c_check_func "$LINENO" "log2" "ac_cv_func_log2" if test "x$ac_cv_func_log2" = xyes; then : $as_echo "#define HAVE_LOG2 1" >>confdefs.h else case " $LIBOBJS " in *" log2.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS log2.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "fexecve" "ac_cv_func_fexecve" if test "x$ac_cv_func_fexecve" = xyes; then : $as_echo "#define HAVE_FEXECVE 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "alarm" "ac_cv_have_decl_alarm" "$ac_includes_default" if test "x$ac_cv_have_decl_alarm" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_ALARM $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "chmod" "ac_cv_have_decl_chmod" "$ac_includes_default" if test "x$ac_cv_have_decl_chmod" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_CHMOD $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "chown" "ac_cv_have_decl_chown" "$ac_includes_default" if test "x$ac_cv_have_decl_chown" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_CHOWN $ac_have_decl _ACEOF for ac_func in fchmod do : ac_fn_c_check_func "$LINENO" "fchmod" "ac_cv_func_fchmod" if test "x$ac_cv_func_fchmod" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FCHMOD 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "uname" "ac_cv_have_decl_uname" "$ac_includes_default" if test "x$ac_cv_have_decl_uname" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_UNAME $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "getuid" "ac_cv_have_decl_getuid" "$ac_includes_default" if test "x$ac_cv_have_decl_getuid" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETUID $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "getgid" "ac_cv_have_decl_getgid" "$ac_includes_default" if test "x$ac_cv_have_decl_getgid" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GETGID $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "lstat" "ac_cv_have_decl_lstat" "$ac_includes_default" if test "x$ac_cv_have_decl_lstat" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_LSTAT $ac_have_decl _ACEOF for ac_func in sleep do : ac_fn_c_check_func "$LINENO" "sleep" "ac_cv_func_sleep" if test "x$ac_cv_func_sleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SLEEP 1 _ACEOF fi done ac_fn_c_check_decl "$LINENO" "socketpair" "ac_cv_have_decl_socketpair" "#include " if test "x$ac_cv_have_decl_socketpair" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_SOCKETPAIR $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "fsync" "ac_cv_have_decl_fsync" "$ac_includes_default" if test "x$ac_cv_have_decl_fsync" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_FSYNC $ac_have_decl _ACEOF ac_fn_c_check_decl "$LINENO" "glob" "ac_cv_have_decl_glob" "#include " if test "x$ac_cv_have_decl_glob" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_GLOB $ac_have_decl _ACEOF ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" " #include #include " if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SOCKADDR_SA_LEN 1 _ACEOF fi ac_fn_c_check_member "$LINENO" "struct ifreq" "ifr_hwaddr" "ac_cv_member_struct_ifreq_ifr_hwaddr" " #include #include " if test "x$ac_cv_member_struct_ifreq_ifr_hwaddr" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_IFREQ_IFR_HWADDR 1 _ACEOF fi for ac_header in sys/sysctl.h do : ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "$ac_includes_default #ifdef HAVE_SYS_PARAM_H # include #endif " if test "x$ac_cv_header_sys_sysctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SYSCTL_H 1 _ACEOF fi done ac_fn_c_check_member "$LINENO" "struct sysinfo" "uptime" "ac_cv_member_struct_sysinfo_uptime" "#include " if test "x$ac_cv_member_struct_sysinfo_uptime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SYSINFO_UPTIME 1 _ACEOF fi for ac_header in sys/sysctl.h do : ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "$ac_includes_default #ifdef HAVE_SYS_PARAM_H # include #endif " if test "x$ac_cv_header_sys_sysctl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SYSCTL_H 1 _ACEOF fi done for ac_header in kstat.h do : ac_fn_c_check_header_mongrel "$LINENO" "kstat.h" "ac_cv_header_kstat_h" "$ac_includes_default" if test "x$ac_cv_header_kstat_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_KSTAT_H 1 _ACEOF fi done for ac_header in utmp.h do : ac_fn_c_check_header_mongrel "$LINENO" "utmp.h" "ac_cv_header_utmp_h" "$ac_includes_default" if test "x$ac_cv_header_utmp_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UTMP_H 1 _ACEOF fi done for ac_header in utmpx.h do : ac_fn_c_check_header_mongrel "$LINENO" "utmpx.h" "ac_cv_header_utmpx_h" "$ac_includes_default" if test "x$ac_cv_header_utmpx_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UTMPX_H 1 _ACEOF fi done rtry=none { $as_echo "$as_me:${as_lineno-$LINENO}: checking for either struct rtentry or struct ortentry" >&5 $as_echo_n "checking for either struct rtentry or struct ortentry... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "rtentry" >/dev/null 2>&1; then : rtry=rtentry fi rm -f conftest* if test "$rtry" = rtentry; then $as_echo "#define HAVE_RTENTRY 1" >>confdefs.h fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ortentry" >/dev/null 2>&1; then : rtry=ortentry fi rm -f conftest* if test "$rtry" = ortentry; then $as_echo "#define HAVE_ORTENTRY 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $rtry" >&5 $as_echo "$rtry" >&6; } for ac_func in listxattr do : ac_fn_c_check_func "$LINENO" "listxattr" "ac_cv_func_listxattr" if test "x$ac_cv_func_listxattr" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LISTXATTR 1 _ACEOF $as_echo "#define WITH_XATTR 1" >>confdefs.h fi done for ac_header in attr/xattr.h sys/xattr.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether xattr functions have extra arguments" >&5 $as_echo_n "checking whether xattr functions have extra arguments... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { (void)listxattr("", 0, 0, 0); (void)getxattr("", "", 0, 0, 0, 0); (void)setxattr("", "", "", 0, 0, 0); (void)removexattr("", "", 0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define WITH_XATTR_EXTRA_ARGS 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check whether --enable-selinux was given. if test "${enable_selinux+set}" = set; then : enableval=$enable_selinux; fi CORE_CPPFLAGS="$LMDB_CPPFLAGS $TOKYOCABINET_CPPFLAGS $QDBM_CPPFLAGS $PCRE_CPPFLAGS $OPENSSL_CPPFLAGS $SQLITE3_CPPFLAGS $LIBACL_CPPFLAGS $POSTGRESQL_CPPFLAGS $MYSQL_CPPFLAGS $LIBXML2_CPPFLAGS $CPPFLAGS" CORE_CFLAGS="$LMDB_CFLAGS $TOKYOCABINET_CFLAGS $QDBM_CFLAGS $PCRE_CFLAGS $OPENSSL_CFLAGS $SQLITE3_CFLAGS $LIBACL_CFLAGS $POSTGRESQL_CFLAGS $MYSQL_CFLAGS $LIBXML2_CFLAGS $CFLAGS" CORE_LDFLAGS="$LMDB_LDFLAGS $TOKYOCABINET_LDFLAGS $QDBM_LDFLAGS $PCRE_LDFLAGS $OPENSSL_LDFLAGS $SQLITE3_LDFLAGS $LIBACL_LDFLAGS $POSTGRESQL_LDFLAGS $MYSQL_LDFLAGS $LIBXML2_LDFLAGS $LDFLAGS" CORE_LIBS="$LMDB_LIBS $TOKYOCABINET_LIBS $QDBM_LIBS $PCRE_LIBS $OPENSSL_LIBS $SQLITE3_LIBS $LIBACL_LIBS $POSTGRESQL_LIBS $MYSQL_LIBS $LIBXML2_LIBS $LIBS" ac_config_files="$ac_config_files configure_flags.env" case "$target_os" in solaris2.8|solaris2.9) $as_echo "#define _XOPEN_SOURCE 500" >>confdefs.h $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h ;; solaris2.10|solaris2.11) $as_echo "#define _XOPEN_SOURCE 600" >>confdefs.h $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h ;; hpux*|hp-ux*) ;; aix*) CPPFLAGS="$CPPFLAGS -w" ;; linux*|*bsd*gnu) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yp_get_default_domain in -lnss_nis" >&5 $as_echo_n "checking for yp_get_default_domain in -lnss_nis... " >&6; } if ${ac_cv_lib_nss_nis_yp_get_default_domain+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnss_nis $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char yp_get_default_domain (); int main () { return yp_get_default_domain (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nss_nis_yp_get_default_domain=yes else ac_cv_lib_nss_nis_yp_get_default_domain=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss_nis_yp_get_default_domain" >&5 $as_echo "$ac_cv_lib_nss_nis_yp_get_default_domain" >&6; } if test "x$ac_cv_lib_nss_nis_yp_get_default_domain" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSS_NIS 1 _ACEOF LIBS="-lnss_nis $LIBS" fi ;; freebsd*|dragonfly*) ;; netbsd*) ;; unicos*) ;; cray*) ;; qnx*) ;; openbsd*|obsd*) ;; gnu*) ;; sysv4.2MP|unix_sv*) ;; cygwin*) ;; mingw*) ;; sco*) ;; darwin*) ;; *) as_fn_error $? "Unknown system type $target_os" "$LINENO" 5 ;; esac # # OS kernels conditionals. Don't use those unless it is really needed (if code # depends on the *kernel* feature, and even then -- some kernel features are # shared by different kernels). # # Good example: use LINUX to select code which uses inotify and netlink sockets. # Bad example: use LINUX to select code which parses output of coreutils' ps(1). # if test -n "`echo ${target_os} | grep linux`"; then LINUX_TRUE= LINUX_FALSE='#' else LINUX_TRUE='#' LINUX_FALSE= fi if test -n "`echo ${target_os} | grep darwin`"; then MACOSX_TRUE= MACOSX_FALSE='#' else MACOSX_TRUE='#' MACOSX_FALSE= fi if test -n "`(echo ${target_os} | egrep 'solaris|sunos')`"; then SOLARIS_TRUE= SOLARIS_FALSE='#' else SOLARIS_TRUE='#' SOLARIS_FALSE= fi if test -n "`(echo ${target_os} | egrep 'mingw|cygwin')`"; then NT_TRUE= NT_FALSE='#' else NT_TRUE='#' NT_FALSE= fi if test -n "`(echo ${target_os} | egrep 'cygwin')`"; then CYGWIN_TRUE= CYGWIN_FALSE='#' else CYGWIN_TRUE='#' CYGWIN_FALSE= fi if test -n "`(echo ${target_os} | grep aix)`"; then AIX_TRUE= AIX_FALSE='#' else AIX_TRUE='#' AIX_FALSE= fi if test -n "`(echo ${target_os} | egrep 'hpux|hp-ux')`"; then HPUX_TRUE= HPUX_FALSE='#' else HPUX_TRUE='#' HPUX_FALSE= fi if test -n "`(echo ${target_os} | grep freebsd)`"; then FREEBSD_TRUE= FREEBSD_FALSE='#' else FREEBSD_TRUE='#' FREEBSD_FALSE= fi if test -n "`(echo ${target_os} | grep netbsd)`"; then NETBSD_TRUE= NETBSD_FALSE='#' else NETBSD_TRUE='#' NETBSD_FALSE= fi if test -n "`(echo ${target_os} | grep darwin)`"; then XNU_TRUE= XNU_FALSE='#' else XNU_TRUE='#' XNU_FALSE= fi # Check whether --with-workdir was given. if test "${with_workdir+set}" = set; then : withval=$with_workdir; if test x$withval != x ; then WORKDIR=$withval LOGDIR=$withval PIDDIR=$withval fi fi _lcl_receval=""${WORKDIR}"" WORKDIR=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "$_lcl_receval_old" != "$_lcl_receval"; do _lcl_receval_old="$_lcl_receval" eval _lcl_receval="\"$_lcl_receval\"" done echo "$_lcl_receval")` cat >>confdefs.h <<_ACEOF #define WORKDIR "${WORKDIR}" _ACEOF workdir="${WORKDIR}" # Check whether --with-masterdir was given. if test "${with_masterdir+set}" = set; then : withval=$with_masterdir; if test x$withval != x ; then MASTERDIR=$withval fi fi _lcl_receval=""${MASTERDIR}"" MASTERDIR=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "$_lcl_receval_old" != "$_lcl_receval"; do _lcl_receval_old="$_lcl_receval" eval _lcl_receval="\"$_lcl_receval\"" done echo "$_lcl_receval")` cat >>confdefs.h <<_ACEOF #define MASTERDIR "${MASTERDIR}" _ACEOF masterdir="${MASTERDIR}" # Check whether --with-inputdir was given. if test "${with_inputdir+set}" = set; then : withval=$with_inputdir; if test x$withval != x ; then INPUTDIR=$withval fi fi _lcl_receval=""${INPUTDIR}"" INPUTDIR=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "$_lcl_receval_old" != "$_lcl_receval"; do _lcl_receval_old="$_lcl_receval" eval _lcl_receval="\"$_lcl_receval\"" done echo "$_lcl_receval")` cat >>confdefs.h <<_ACEOF #define INPUTDIR "${INPUTDIR}" _ACEOF inputdir="${INPUTDIR}" # Check whether --with-logdir was given. if test "${with_logdir+set}" = set; then : withval=$with_logdir; if test x$withval != x ; then LOGDIR=$withval fi fi _lcl_receval=""${LOGDIR}"" LOGDIR=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "$_lcl_receval_old" != "$_lcl_receval"; do _lcl_receval_old="$_lcl_receval" eval _lcl_receval="\"$_lcl_receval\"" done echo "$_lcl_receval")` cat >>confdefs.h <<_ACEOF #define LOGDIR "${LOGDIR}" _ACEOF logdir="${LOGDIR}" # Check whether --with-piddir was given. if test "${with_piddir+set}" = set; then : withval=$with_piddir; if test x$withval != x ; then PIDDIR=$withval fi fi _lcl_receval=""${PIDDIR}"" PIDDIR=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" _lcl_receval_old='' while test "$_lcl_receval_old" != "$_lcl_receval"; do _lcl_receval_old="$_lcl_receval" eval _lcl_receval="\"$_lcl_receval\"" done echo "$_lcl_receval")` cat >>confdefs.h <<_ACEOF #define PIDDIR "${PIDDIR}" _ACEOF piddir="${PIDDIR}" # Check whether --with-shell was given. if test "${with_shell+set}" = set; then : withval=$with_shell; else with_shell=/bin/sh fi if test "x$with_shell" = "xno"; then as_fn_error $? "Please specify full path to POSIX-compatible shell" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define SHELL_PATH "$with_shell" _ACEOF # Extract the first word of "hostname", so it can be a program name with args. set dummy hostname; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_HOSTNAME+:} false; then : $as_echo_n "(cached) " >&6 else case $HOSTNAME in [\\/]* | ?:[\\/]*) ac_cv_path_HOSTNAME="$HOSTNAME" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_HOSTNAME="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_HOSTNAME" && ac_cv_path_HOSTNAME="""" ;; esac fi HOSTNAME=$ac_cv_path_HOSTNAME if test -n "$HOSTNAME"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HOSTNAME" >&5 $as_echo "$HOSTNAME" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF #define AUTOCONF_HOSTNAME "`$HOSTNAME`" _ACEOF cat >>confdefs.h <<_ACEOF #define AUTOCONF_SYSNAME "$target_os" _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Xen cpuid-based HVM detection" >&5 $as_echo_n "checking for Xen cpuid-based HVM detection... " >&6; } if test x"$GCC" = "xyes"; then case $host_cpu in i[3456]86*|x86_64*) $as_echo "#define XEN_CPUID_SUPPORT 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --enable-coverage was given. if test "${enable_coverage+set}" = set; then : enableval=$enable_coverage; use_coverage=$enableval else use_coverage=no fi if test "x$use_coverage" = "xyes"; then if test "$GCC" != "yes"; then as_fn_error $? "GCC is required for --enable-coverage" "$LINENO" 5 fi if test "$debug" != "yes"; then as_fn_error $? "--enable-debug is required for --enable-coverage" "$LINENO" 5 fi # Extract the first word of "lcov", so it can be a program name with args. set dummy lcov; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LCOV+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LCOV"; then ac_cv_prog_LCOV="$LCOV" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LCOV="lcov" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LCOV=$ac_cv_prog_LCOV if test -n "$LCOV"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LCOV" >&5 $as_echo "$LCOV" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "genhtml", so it can be a program name with args. set dummy genhtml; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LCOV_GENHTML+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LCOV_GENHTML"; then ac_cv_prog_LCOV_GENHTML="$LCOV_GENHTML" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LCOV_GENHTML="genhtml" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LCOV_GENHTML=$ac_cv_prog_LCOV_GENHTML if test -n "$LCOV_GENHTML"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LCOV_GENHTML" >&5 $as_echo "$LCOV_GENHTML" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$LCOV"; then as_fn_error $? "Cannot find lcov from the LTP package" "$LINENO" 5 fi if test -z "$LCOV_GENHTML"; then as_fn_error $? "Could not find genhtml from the LTP package" "$LINENO" 5 fi CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage" LDFLAGS="$LDFLAGS -lgcov" fi # # Populate contents of config.post.h # { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Summary of options..." >&5 $as_echo "Summary of options..." >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: > Required libraries" >&5 $as_echo "> Required libraries" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> OpenSSL: $OPENSSL_PATH" >&5 $as_echo "-> OpenSSL: $OPENSSL_PATH" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> PCRE: $PCRE_PATH" >&5 $as_echo "-> PCRE: $PCRE_PATH" >&6; } if test $WITH_TOKYO = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> DB: Tokyo Cabinet: $TOKYOCABINET_PATH" >&5 $as_echo "-> DB: Tokyo Cabinet: $TOKYOCABINET_PATH" >&6; } elif test $WITH_QDBM = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> DB: QDBM: $QDBM_PATH" >&5 $as_echo "-> DB: QDBM: $QDBM_PATH" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: > Optional libraries" >&5 $as_echo "> Optional libraries" >&6; } if test "x$ac_cv_lib_mysqlclient_mysql_real_connect" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> MySQL connector: $MYSQL_PATH" >&5 $as_echo "-> MySQL connector: $MYSQL_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> MySQL connector: disabled" >&5 $as_echo "-> MySQL connector: disabled" >&6; } fi if test "x$ac_cv_lib_pq_PQconnectdb" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> PostgreSQL connector: $POSTGRESQL_PATH" >&5 $as_echo "-> PostgreSQL connector: $POSTGRESQL_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> PostgreSQL connector: disabled" >&5 $as_echo "-> PostgreSQL connector: disabled" >&6; } fi if test $WITH_LMDB = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> DB: Lightning MDB: $LMDB_PATH" >&5 $as_echo "-> DB: Lightning MDB: $LMDB_PATH" >&6; } elif test $WITH_TOKYO = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> DB: Tokyo Cabinet: $TOKYOCABINET_PATH" >&5 $as_echo "-> DB: Tokyo Cabinet: $TOKYOCABINET_PATH" >&6; } elif test $WITH_QDBM = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> DB: QDBM: $QDBM_PATH" >&5 $as_echo "-> DB: QDBM: $QDBM_PATH" >&6; } fi if test "x$ac_cv_lib_virt_virConnectOpen" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> libvirt: $LIBVIRT_PATH" >&5 $as_echo "-> libvirt: $LIBVIRT_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> libvirt: disabled" >&5 $as_echo "-> libvirt: disabled" >&6; } fi if test "x$ac_cv_lib_acl_acl_init" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> libacl: $LIBACL_PATH" >&5 $as_echo "-> libacl: $LIBACL_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> libacl: disabled" >&5 $as_echo "-> libacl: disabled" >&6; } fi if test "x$ac_cv_lib_xml2_xmlFirstElementChild" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> libxml2: $LIBXML2_PATH" >&5 $as_echo "-> libxml2: $LIBXML2_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> libxml2: disabled" >&5 $as_echo "-> libxml2: disabled" >&6; } fi if test "x$users_promises_ok" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> User promises: PAM/user* tools" >&5 $as_echo "-> User promises: PAM/user* tools" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> User promises: disabled" >&5 $as_echo "-> User promises: disabled" >&6; } fi if test "x$enable_builtin_extensions" = "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Enterprise extensions: Built in" >&5 $as_echo "-> Enterprise extensions: Built in" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Enterprise extensions: Plugin or not included" >&5 $as_echo "-> Enterprise extensions: Plugin or not included" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Workdir: $WORKDIR" >&5 $as_echo "-> Workdir: $WORKDIR" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Masterdir: $MASTERDIR" >&5 $as_echo "-> Masterdir: $MASTERDIR" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Inputdir: $INPUTDIR" >&5 $as_echo "-> Inputdir: $INPUTDIR" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Logdir: $LOGDIR" >&5 $as_echo "-> Logdir: $LOGDIR" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: -> Piddir: $PIDDIR" >&5 $as_echo "-> Piddir: $PIDDIR" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } ac_config_files="$ac_config_files Makefile libcompat/Makefile libutils/Makefile libutils/config.post.h libcfnet/Makefile libenv/Makefile libpromises/Makefile cf-agent/Makefile cf-promises/Makefile cf-execd/Makefile cf-key/Makefile cf-monitord/Makefile cf-upgrade/Makefile cf-runagent/Makefile cf-serverd/Makefile ext/Makefile examples/Makefile tests/Makefile tests/acceptance/Makefile tests/unit/Makefile tests/load/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CROSS_COMPILING_TRUE}" && test -z "${CROSS_COMPILING_FALSE}"; then as_fn_error $? "conditional \"CROSS_COMPILING\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILTIN_EXTENSIONS_TRUE}" && test -z "${BUILTIN_EXTENSIONS_FALSE}"; then as_fn_error $? "conditional \"BUILTIN_EXTENSIONS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${NDEBUG_TRUE}" && test -z "${NDEBUG_FALSE}"; then as_fn_error $? "conditional \"NDEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBXML2_TRUE}" && test -z "${HAVE_LIBXML2_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBXML2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_AVAHI_CLIENT_TRUE}" && test -z "${HAVE_AVAHI_CLIENT_FALSE}"; then as_fn_error $? "conditional \"HAVE_AVAHI_CLIENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_AVAHI_CLIENT_TRUE}" && test -z "${HAVE_AVAHI_CLIENT_FALSE}"; then as_fn_error $? "conditional \"HAVE_AVAHI_CLIENT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_AVAHI_COMMON_TRUE}" && test -z "${HAVE_AVAHI_COMMON_FALSE}"; then as_fn_error $? "conditional \"HAVE_AVAHI_COMMON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_AVAHI_COMMON_TRUE}" && test -z "${HAVE_AVAHI_COMMON_FALSE}"; then as_fn_error $? "conditional \"HAVE_AVAHI_COMMON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_USERS_PROMISE_DEPS_TRUE}" && test -z "${HAVE_USERS_PROMISE_DEPS_FALSE}"; then as_fn_error $? "conditional \"HAVE_USERS_PROMISE_DEPS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then as_fn_error $? "conditional \"LINUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MACOSX_TRUE}" && test -z "${MACOSX_FALSE}"; then as_fn_error $? "conditional \"MACOSX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${SOLARIS_TRUE}" && test -z "${SOLARIS_FALSE}"; then as_fn_error $? "conditional \"SOLARIS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${NT_TRUE}" && test -z "${NT_FALSE}"; then as_fn_error $? "conditional \"NT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CYGWIN_TRUE}" && test -z "${CYGWIN_FALSE}"; then as_fn_error $? "conditional \"CYGWIN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AIX_TRUE}" && test -z "${AIX_FALSE}"; then as_fn_error $? "conditional \"AIX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HPUX_TRUE}" && test -z "${HPUX_FALSE}"; then as_fn_error $? "conditional \"HPUX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FREEBSD_TRUE}" && test -z "${FREEBSD_FALSE}"; then as_fn_error $? "conditional \"FREEBSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${NETBSD_TRUE}" && test -z "${NETBSD_FALSE}"; then as_fn_error $? "conditional \"NETBSD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${XNU_TRUE}" && test -z "${XNU_FALSE}"; then as_fn_error $? "conditional \"XNU\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "libutils/config.h") CONFIG_HEADERS="$CONFIG_HEADERS libutils/config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "configure_flags.env") CONFIG_FILES="$CONFIG_FILES configure_flags.env" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "libcompat/Makefile") CONFIG_FILES="$CONFIG_FILES libcompat/Makefile" ;; "libutils/Makefile") CONFIG_FILES="$CONFIG_FILES libutils/Makefile" ;; "libutils/config.post.h") CONFIG_FILES="$CONFIG_FILES libutils/config.post.h" ;; "libcfnet/Makefile") CONFIG_FILES="$CONFIG_FILES libcfnet/Makefile" ;; "libenv/Makefile") CONFIG_FILES="$CONFIG_FILES libenv/Makefile" ;; "libpromises/Makefile") CONFIG_FILES="$CONFIG_FILES libpromises/Makefile" ;; "cf-agent/Makefile") CONFIG_FILES="$CONFIG_FILES cf-agent/Makefile" ;; "cf-promises/Makefile") CONFIG_FILES="$CONFIG_FILES cf-promises/Makefile" ;; "cf-execd/Makefile") CONFIG_FILES="$CONFIG_FILES cf-execd/Makefile" ;; "cf-key/Makefile") CONFIG_FILES="$CONFIG_FILES cf-key/Makefile" ;; "cf-monitord/Makefile") CONFIG_FILES="$CONFIG_FILES cf-monitord/Makefile" ;; "cf-upgrade/Makefile") CONFIG_FILES="$CONFIG_FILES cf-upgrade/Makefile" ;; "cf-runagent/Makefile") CONFIG_FILES="$CONFIG_FILES cf-runagent/Makefile" ;; "cf-serverd/Makefile") CONFIG_FILES="$CONFIG_FILES cf-serverd/Makefile" ;; "ext/Makefile") CONFIG_FILES="$CONFIG_FILES ext/Makefile" ;; "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "tests/acceptance/Makefile") CONFIG_FILES="$CONFIG_FILES tests/acceptance/Makefile" ;; "tests/unit/Makefile") CONFIG_FILES="$CONFIG_FILES tests/unit/Makefile" ;; "tests/load/Makefile") CONFIG_FILES="$CONFIG_FILES tests/load/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: DONE: Configuration done. Run make/gmake to build CFEngine Community." >&5 $as_echo "DONE: Configuration done. Run make/gmake to build CFEngine Community." >&6; }